diff --git a/packages/grafana-ui/src/components/Forms/Button.mdx b/packages/grafana-ui/src/components/Button/Button.mdx similarity index 77% rename from packages/grafana-ui/src/components/Forms/Button.mdx rename to packages/grafana-ui/src/components/Button/Button.mdx index 9a1a508ed6c..5d3797e6e66 100644 --- a/packages/grafana-ui/src/components/Forms/Button.mdx +++ b/packages/grafana-ui/src/components/Button/Button.mdx @@ -59,5 +59,22 @@ Used for removing or deleting entities. +## Link + +Used for for hyperlinks. + + +
+ + + +
+
diff --git a/packages/grafana-ui/src/components/Button/Button.story.tsx b/packages/grafana-ui/src/components/Button/Button.story.tsx index 47f29921a94..106dc4aa7bc 100644 --- a/packages/grafana-ui/src/components/Button/Button.story.tsx +++ b/packages/grafana-ui/src/components/Button/Button.story.tsx @@ -1,45 +1,35 @@ -import { storiesOf } from '@storybook/react'; -import { Button, LinkButton } from './Button'; -// @ts-ignore -import withPropsCombinations from 'react-storybook-addon-props-combinations'; -import { action } from '@storybook/addon-actions'; -import { ThemeableCombinationsRowRenderer } from '../../utils/storybook/CombinationsRowRenderer'; -import { boolean } from '@storybook/addon-knobs'; +import React from 'react'; +import { select, text } from '@storybook/addon-knobs'; +import { Button, ButtonVariant } from './Button'; +import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory'; import { getIconKnob } from '../../utils/storybook/knobs'; +import mdx from './Button.mdx'; +import { ComponentSize } from '../../types/size'; -const ButtonStories = storiesOf('General/Button', module); - -const defaultProps = { - onClick: [action('Button clicked')], - children: ['Click click!'], +export default { + title: 'Forms/Button', + component: Button, + decorators: [withCenteredStory, withHorizontallyCenteredStory], + parameters: { + docs: { + page: mdx, + }, + }, }; -const variants = { - size: ['xs', 'sm', 'md', 'lg'], - variant: ['primary', 'secondary', 'danger', 'inverse', 'transparent', 'link'], -}; -const combinationOptions = { - CombinationRenderer: ThemeableCombinationsRowRenderer, -}; +const variants = ['primary', 'secondary', 'destructive', 'link']; -const renderButtonStory = (buttonComponent: typeof Button | typeof LinkButton) => { - const isDisabled = boolean('Disable button', false); - return withPropsCombinations( - buttonComponent, - { ...variants, ...defaultProps, disabled: [isDisabled] }, - combinationOptions - )(); -}; +const sizes = ['sm', 'md', 'lg']; -ButtonStories.add('as button element', () => renderButtonStory(Button)); - -ButtonStories.add('as link element', () => renderButtonStory(LinkButton)); - -ButtonStories.add('with icon', () => { +export const simple = () => { + const variant = select('Variant', variants, 'primary'); + const size = select('Size', sizes, 'md'); + const buttonText = text('text', 'Button'); const icon = getIconKnob(); - return withPropsCombinations( - Button, - { ...variants, ...defaultProps, icon: [icon && `fa fa-${icon}`] }, - combinationOptions - )(); -}); + + return ( + + ); +}; diff --git a/packages/grafana-ui/src/components/Button/Button.test.tsx b/packages/grafana-ui/src/components/Button/Button.test.tsx deleted file mode 100644 index e71d84f43bf..00000000000 --- a/packages/grafana-ui/src/components/Button/Button.test.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import { Button, LinkButton } from './Button'; -import { mount } from 'enzyme'; - -describe('Button', () => { - it('renders correct html', () => { - const wrapper = mount(); - expect(wrapper.html()).toMatchSnapshot(); - }); -}); - -describe('LinkButton', () => { - it('renders correct html', () => { - const wrapper = mount(Click me); - expect(wrapper.html()).toMatchSnapshot(); - }); - - it('allows a disable state on link button', () => { - const wrapper = mount( - - Click me - - ); - expect(wrapper.find('a[disabled]').length).toBe(1); - }); -}); diff --git a/packages/grafana-ui/src/components/Button/Button.tsx b/packages/grafana-ui/src/components/Button/Button.tsx index 009f67819b2..a9c6ada9f3c 100644 --- a/packages/grafana-ui/src/components/Button/Button.tsx +++ b/packages/grafana-ui/src/components/Button/Button.tsx @@ -1,72 +1,178 @@ import React, { AnchorHTMLAttributes, ButtonHTMLAttributes, useContext } from 'react'; -import { ThemeContext } from '../../themes'; -import { getButtonStyles } from './styles'; +import { css, cx } from 'emotion'; +import tinycolor from 'tinycolor2'; +import { selectThemeVariant, stylesFactory, ThemeContext } from '../../themes'; +import { getFocusStyle, getPropertiesForButtonSize } from '../Forms/commonStyles'; +import { GrafanaTheme } from '@grafana/data'; import { ButtonContent } from './ButtonContent'; import { ComponentSize } from '../../types/size'; -import { ButtonStyles, ButtonVariant } from './types'; -import { cx } from 'emotion'; + +const buttonVariantStyles = (from: string, to: string, textColor: string) => css` + background: linear-gradient(180deg, ${from} 0%, ${to} 100%); + color: ${textColor}; + &:hover { + background: ${from}; + color: ${textColor}; + } + + &:focus { + background: ${from}; + outline: none; + } +`; + +const getPropertiesForVariant = (theme: GrafanaTheme, variant: ButtonVariant) => { + switch (variant) { + case 'secondary': + const from = selectThemeVariant({ light: theme.colors.gray7, dark: theme.colors.gray15 }, theme.type) as string; + const to = selectThemeVariant( + { + light: tinycolor(from) + .darken(5) + .toString(), + dark: tinycolor(from) + .lighten(4) + .toString(), + }, + theme.type + ) as string; + + return { + borderColor: selectThemeVariant({ light: theme.colors.gray85, dark: theme.colors.gray25 }, theme.type), + background: buttonVariantStyles( + from, + to, + selectThemeVariant({ light: theme.colors.gray25, dark: theme.colors.gray4 }, theme.type) as string + ), + }; + + case 'destructive': + return { + borderColor: theme.colors.redShade, + background: buttonVariantStyles(theme.colors.redBase, theme.colors.redShade, theme.colors.white), + }; + + case 'link': + return { + borderColor: 'transparent', + background: buttonVariantStyles('transparent', 'transparent', theme.colors.linkExternal), + variantStyles: css` + &:focus { + outline: none; + box-shadow: none; + } + `, + }; + case 'primary': + default: + return { + borderColor: theme.colors.blueShade, + background: buttonVariantStyles(theme.colors.blueBase, theme.colors.blueShade, theme.colors.white), + }; + } +}; + +export interface StyleProps { + theme: GrafanaTheme; + size: ComponentSize; + variant: ButtonVariant; + textAndIcon?: boolean; +} + +export const getButtonStyles = stylesFactory(({ theme, size, variant }: StyleProps) => { + const { padding, fontSize, height } = getPropertiesForButtonSize(theme, size); + const { background, borderColor, variantStyles } = getPropertiesForVariant(theme, variant); + + return { + button: cx( + css` + label: button; + display: inline-flex; + align-items: center; + font-weight: ${theme.typography.weight.semibold}; + font-family: ${theme.typography.fontFamily.sansSerif}; + font-size: ${fontSize}; + padding: ${padding}; + height: ${height}; + vertical-align: middle; + cursor: pointer; + border: 1px solid ${borderColor}; + border-radius: ${theme.border.radius.sm}; + ${background}; + + &[disabled], + &:disabled { + cursor: not-allowed; + opacity: 0.65; + box-shadow: none; + } + `, + getFocusStyle(theme), + css` + ${variantStyles} + ` + ), + buttonWithIcon: css` + padding-left: ${theme.spacing.sm}; + `, + // used for buttons with icon only + iconButton: css` + padding-right: 0; + `, + iconWrap: css` + label: button-icon-wrap; + & + * { + margin-left: ${theme.spacing.sm}; + } + `, + }; +}); + +export type ButtonVariant = 'primary' | 'secondary' | 'destructive' | 'link'; type CommonProps = { size?: ComponentSize; variant?: ButtonVariant; - /** - * icon prop is a temporary solution. It accepts legacy icon class names for the icon to be rendered. - * TODO: migrate to a component when we are going to migrate icons to @grafana/ui - */ icon?: string; className?: string; - styles?: ButtonStyles; }; export type ButtonProps = CommonProps & ButtonHTMLAttributes; -export const Button = React.forwardRef((props, ref) => { - const theme = useContext(ThemeContext); - const { size, variant, icon, children, className, styles: stylesProp, ...buttonProps } = props; - // Default this to 'button', otherwise html defaults to 'submit' which then submits any form it is in. - buttonProps.type = buttonProps.type || 'button'; - - const styles: ButtonStyles = - stylesProp || - getButtonStyles({ +export const Button = React.forwardRef( + ({ variant, icon, children, className, ...otherProps }, ref) => { + const theme = useContext(ThemeContext); + const styles = getButtonStyles({ theme, - size: size || 'md', + size: otherProps.size || 'md', variant: variant || 'primary', - textAndIcon: !!(children && icon), }); - return ( - - ); -}); + return ( + + ); + } +); Button.displayName = 'Button'; -export type LinkButtonProps = CommonProps & - AnchorHTMLAttributes & { - // We allow disabled here even though it is not standard for a link. We use it as a selector to style it as - // disabled. - disabled?: boolean; - }; - -export const LinkButton = React.forwardRef((props, ref) => { - const theme = useContext(ThemeContext); - const { size, variant, icon, children, className, styles: stylesProp, ...anchorProps } = props; - const styles: ButtonStyles = - stylesProp || - getButtonStyles({ +type ButtonLinkProps = CommonProps & AnchorHTMLAttributes; +export const LinkButton = React.forwardRef( + ({ variant, icon, children, className, ...otherProps }, ref) => { + const theme = useContext(ThemeContext); + const styles = getButtonStyles({ theme, - size: size || 'md', + size: otherProps.size || 'md', variant: variant || 'primary', - textAndIcon: !!(children && icon), }); - return ( - - {children} - - ); -}); + return ( + + {children} + + ); + } +); LinkButton.displayName = 'LinkButton'; diff --git a/packages/grafana-ui/src/components/Button/__snapshots__/Button.test.tsx.snap b/packages/grafana-ui/src/components/Button/__snapshots__/Button.test.tsx.snap deleted file mode 100644 index 2000309fe55..00000000000 --- a/packages/grafana-ui/src/components/Button/__snapshots__/Button.test.tsx.snap +++ /dev/null @@ -1,5 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Button renders correct html 1`] = `""`; - -exports[`LinkButton renders correct html 1`] = `"Click me"`; diff --git a/packages/grafana-ui/src/components/Button/index.ts b/packages/grafana-ui/src/components/Button/index.ts new file mode 100644 index 00000000000..8b166a86e4d --- /dev/null +++ b/packages/grafana-ui/src/components/Button/index.ts @@ -0,0 +1 @@ +export * from './Button'; diff --git a/packages/grafana-ui/src/components/Button/styles.ts b/packages/grafana-ui/src/components/Button/styles.ts deleted file mode 100644 index 24e9bcb677e..00000000000 --- a/packages/grafana-ui/src/components/Button/styles.ts +++ /dev/null @@ -1,164 +0,0 @@ -import tinycolor from 'tinycolor2'; -import { css } from 'emotion'; -import { selectThemeVariant, stylesFactory } from '../../themes'; -import { ComponentSize } from '../../types/size'; -import { StyleDeps } from './types'; -import { GrafanaTheme } from '@grafana/data'; - -const buttonVariantStyles = ( - from: string, - to: string, - textColor: string, - textShadowColor = 'rgba(0, 0, 0, 0.1)', - invert = false -) => css` - background: linear-gradient(to bottom, ${from}, ${to}); - color: ${textColor}; - text-shadow: 0 ${invert ? '1px' : '-1px'} ${textShadowColor}; - &:hover { - background: ${from}; - color: ${textColor}; - } - - &:focus { - background: ${from}; - outline: none; - } -`; - -export const getButtonStyles = stylesFactory(({ theme, size, variant, textAndIcon }: StyleDeps) => { - const borderRadius = theme.border.radius.sm; - const { padding, fontSize, height, fontWeight } = calculateMeasures(theme, size, !!textAndIcon); - - let background; - - switch (variant) { - case 'primary': - background = buttonVariantStyles(theme.colors.greenBase, theme.colors.greenShade, theme.colors.white); - break; - - case 'secondary': - background = buttonVariantStyles(theme.colors.blueBase, theme.colors.blueShade, theme.colors.white); - break; - - case 'danger': - background = buttonVariantStyles(theme.colors.redBase, theme.colors.redShade, theme.colors.white); - break; - - case 'inverse': - const from = selectThemeVariant({ light: theme.colors.gray5, dark: theme.colors.dark6 }, theme.type) as string; - const to = selectThemeVariant( - { - light: tinycolor(from) - .darken(5) - .toString(), - dark: tinycolor(from) - .lighten(4) - .toString(), - }, - theme.type - ) as string; - - background = buttonVariantStyles(from, to, theme.colors.link, 'rgba(0, 0, 0, 0.1)', true); - break; - - case 'transparent': - background = css` - ${buttonVariantStyles('', '', theme.colors.link, 'rgba(0, 0, 0, 0.1)', true)}; - background: transparent; - `; - break; - - case 'link': - background = css` - ${buttonVariantStyles('', '', theme.colors.linkExternal, 'rgba(0, 0, 0, 0.1)', true)}; - background: transparent; - `; - break; - } - - return { - button: css` - label: button; - display: inline-flex; - align-items: center; - font-weight: ${fontWeight}; - font-size: ${fontSize}; - font-family: ${theme.typography.fontFamily.sansSerif}; - line-height: ${theme.typography.lineHeight.md}; - padding: ${padding}; - vertical-align: middle; - cursor: pointer; - border: none; - height: ${height}; - border-radius: ${borderRadius}; - ${background}; - - &[disabled], - &:disabled { - cursor: not-allowed; - opacity: 0.65; - box-shadow: none; - } - `, - iconWrap: css` - label: button-icon-wrap; - & + * { - margin-left: ${theme.spacing.sm}; - } - `, - }; -}); - -type ButtonMeasures = { - padding: string; - fontSize: string; - height: string; - fontWeight: number; -}; - -const calculateMeasures = (theme: GrafanaTheme, size: ComponentSize, textAndIcon: boolean): ButtonMeasures => { - switch (size) { - case 'sm': { - return { - padding: `0 ${theme.spacing.sm}`, - fontSize: theme.typography.size.sm, - height: theme.height.sm, - fontWeight: theme.typography.weight.semibold, - }; - } - - case 'md': { - const leftPadding = textAndIcon ? theme.spacing.sm : theme.spacing.md; - - return { - padding: `0 ${theme.spacing.md} 0 ${leftPadding}`, - fontSize: theme.typography.size.md, - height: theme.height.md, - fontWeight: theme.typography.weight.semibold, - }; - } - - case 'lg': { - const leftPadding = textAndIcon ? theme.spacing.md : theme.spacing.lg; - - return { - padding: `0 ${theme.spacing.lg} 0 ${leftPadding}`, - fontSize: theme.typography.size.lg, - height: theme.height.lg, - fontWeight: theme.typography.weight.regular, - }; - } - - default: { - const leftPadding = textAndIcon ? theme.spacing.sm : theme.spacing.md; - - return { - padding: `0 ${theme.spacing.md} 0 ${leftPadding}`, - fontSize: theme.typography.size.base, - height: theme.height.md, - fontWeight: theme.typography.weight.regular, - }; - } - } -}; diff --git a/packages/grafana-ui/src/components/Button/types.ts b/packages/grafana-ui/src/components/Button/types.ts deleted file mode 100644 index 71a7e0e93f9..00000000000 --- a/packages/grafana-ui/src/components/Button/types.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { GrafanaTheme } from '@grafana/data'; -import { ComponentSize } from '../../types/size'; - -export type ButtonVariant = 'primary' | 'secondary' | 'danger' | 'inverse' | 'transparent' | 'destructive' | 'link'; - -export interface StyleDeps { - theme: GrafanaTheme; - size: ComponentSize; - variant: ButtonVariant; - textAndIcon?: boolean; -} - -export interface ButtonStyles { - button: string; - iconWrap: string; - icon?: string; -} diff --git a/packages/grafana-ui/src/components/ClipboardButton/ClipboardButton.tsx b/packages/grafana-ui/src/components/ClipboardButton/ClipboardButton.tsx index 89e1f22c0f4..33118fb34d7 100644 --- a/packages/grafana-ui/src/components/ClipboardButton/ClipboardButton.tsx +++ b/packages/grafana-ui/src/components/ClipboardButton/ClipboardButton.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import Clipboard from 'clipboard'; -import { Button, ButtonProps } from '../Button/Button'; +import { Button, ButtonProps } from '../Button'; interface Props extends ButtonProps { getText(): string; diff --git a/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.story.tsx b/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.story.tsx index 20feca44efa..5bb392d6798 100644 --- a/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.story.tsx +++ b/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.story.tsx @@ -1,10 +1,11 @@ +export { ClipboardButton } from '../ClipboardButton/ClipboardButton'; import React from 'react'; import { storiesOf } from '@storybook/react'; import { text, boolean, select } from '@storybook/addon-knobs'; import { ConfirmButton } from './ConfirmButton'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { action } from '@storybook/addon-actions'; -import { Button } from '../Button/Button'; +import { Button } from '../Button'; const getKnobs = () => { return { @@ -16,9 +17,8 @@ const getKnobs = () => { { primary: 'primary', secondary: 'secondary', - danger: 'danger', - inverse: 'inverse', - transparent: 'transparent', + destructive: 'destructive', + link: 'link', }, 'primary' ), diff --git a/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.test.tsx b/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.test.tsx index b708e3cf226..e3117ec9336 100644 --- a/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.test.tsx +++ b/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { ConfirmButton } from './ConfirmButton'; import { mount, ShallowWrapper } from 'enzyme'; -import { Button } from '../Button/Button'; +import { Button } from '../Button'; describe('ConfirmButton', () => { let wrapper: any; diff --git a/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.tsx b/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.tsx index a22702e54e2..1d828127e93 100644 --- a/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.tsx +++ b/packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.tsx @@ -4,9 +4,7 @@ import { stylesFactory, withTheme } from '../../themes'; import { GrafanaTheme } from '@grafana/data'; import { Themeable } from '../../types'; import { ComponentSize } from '../../types/size'; -import { Button } from '../Button/Button'; -import Forms from '../Forms'; -import { ButtonVariant } from '../Button/types'; +import { Button, ButtonVariant } from '../Button'; const getStyles = stylesFactory((theme: GrafanaTheme) => { return { @@ -135,9 +133,9 @@ class UnThemedConfirmButton extends PureComponent { {typeof children === 'string' ? ( - + ) : ( @@ -146,7 +144,7 @@ class UnThemedConfirmButton extends PureComponent { )} - - diff --git a/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx b/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx index b3e33522204..7d81f14e01e 100644 --- a/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx +++ b/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx @@ -73,7 +73,7 @@ export const DataLinksEditor: FC = React.memo( )} {(!value || (value && value.length < (maxLinks || Infinity))) && ( - )} diff --git a/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinkEditorModalContent.tsx b/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinkEditorModalContent.tsx index 34c10011318..991aad7cbc5 100644 --- a/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinkEditorModalContent.tsx +++ b/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinkEditorModalContent.tsx @@ -2,7 +2,7 @@ import { DataFrame, DataLink, VariableSuggestion } from '@grafana/data'; import React, { FC, useState } from 'react'; import { DataLinkEditor } from '../DataLinkEditor'; import { HorizontalGroup } from '../../Layout/Layout'; -import Forms from '../../Forms'; +import { Button } from '../../Button'; interface DataLinkEditorModalContentProps { link: DataLink; @@ -34,17 +34,17 @@ export const DataLinkEditorModalContent: FC = ( onRemove={() => {}} /> - { onChange(index, dirtyLink); onClose(); }} > Save - - onClose()}> + + ); diff --git a/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksInlineEditor.tsx b/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksInlineEditor.tsx index 5f00ff9f2b2..7a75972fd14 100644 --- a/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksInlineEditor.tsx +++ b/packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksInlineEditor.tsx @@ -1,7 +1,7 @@ import { DataFrame, DataLink, GrafanaTheme, VariableSuggestion } from '@grafana/data'; import React, { useState } from 'react'; import { css } from 'emotion'; -import Forms from '../../Forms'; +import { Button } from '../../Button/Button'; import cloneDeep from 'lodash/cloneDeep'; import { Modal } from '../../Modal/Modal'; import { FullWidthButtonContainer } from '../../Button/FullWidthButtonContainer'; @@ -100,9 +100,9 @@ export const DataLinksInlineEditor: React.FC = ({ li )} - + ); diff --git a/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.test.tsx b/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.test.tsx index 1f091688a05..8bb9416b02a 100644 --- a/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.test.tsx +++ b/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.test.tsx @@ -57,7 +57,7 @@ describe('Render', () => { }, }, }); - const removeButton = wrapper.find('Button').find({ variant: 'transparent' }); + const removeButton = wrapper.find('Button').find({ variant: 'destructive' }); removeButton.simulate('click', { preventDefault: () => {} }); expect(wrapper.find('FormField').exists()).toBeFalsy(); expect(wrapper.find('SecretFormField').exists()).toBeFalsy(); diff --git a/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx b/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx index 476787ce38c..2583f948edc 100644 --- a/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx +++ b/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { css } from 'emotion'; import uniqueId from 'lodash/uniqueId'; import { DataSourceSettings } from '@grafana/data'; -import { Button } from '../Button/Button'; +import { Button } from '../Button'; import { FormField } from '../FormField/FormField'; import { SecretFormField } from '../SecretFormFied/SecretFormField'; import { stylesFactory } from '../../themes'; @@ -76,7 +76,7 @@ const CustomHeaderRow: React.FC = ({ header, onBlur, onCha onChange={e => onChange({ ...header, value: e.target.value })} onBlur={onBlur} /> - @@ -202,7 +202,7 @@ export class CustomHeadersSettings extends PureComponent {
- ); -}; diff --git a/packages/grafana-ui/src/components/Forms/Button.tsx b/packages/grafana-ui/src/components/Forms/Button.tsx deleted file mode 100644 index 41253830850..00000000000 --- a/packages/grafana-ui/src/components/Forms/Button.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import React, { AnchorHTMLAttributes, ButtonHTMLAttributes, useContext } from 'react'; -import { css, cx } from 'emotion'; -import tinycolor from 'tinycolor2'; -import { selectThemeVariant, stylesFactory, ThemeContext } from '../../themes'; -import { Button as DefaultButton, LinkButton as DefaultLinkButton } from '../Button/Button'; -import { getFocusStyle, getPropertiesForButtonSize } from './commonStyles'; -import { ComponentSize } from '../../types/size'; -import { StyleDeps } from '../Button/types'; -import { GrafanaTheme } from '@grafana/data'; - -const buttonVariantStyles = (from: string, to: string, textColor: string) => css` - background: linear-gradient(180deg, ${from} 0%, ${to} 100%); - color: ${textColor}; - &:hover { - background: ${from}; - color: ${textColor}; - } - - &:focus { - background: ${from}; - outline: none; - } -`; - -const getPropertiesForVariant = (theme: GrafanaTheme, variant: ButtonVariant) => { - switch (variant) { - case 'secondary': - const from = selectThemeVariant({ light: theme.colors.gray7, dark: theme.colors.gray15 }, theme.type) as string; - const to = selectThemeVariant( - { - light: tinycolor(from) - .darken(5) - .toString(), - dark: tinycolor(from) - .lighten(4) - .toString(), - }, - theme.type - ) as string; - - return { - borderColor: selectThemeVariant({ light: theme.colors.gray85, dark: theme.colors.gray25 }, theme.type), - background: buttonVariantStyles( - from, - to, - selectThemeVariant({ light: theme.colors.gray25, dark: theme.colors.gray4 }, theme.type) as string - ), - }; - - case 'destructive': - return { - borderColor: theme.colors.redShade, - background: buttonVariantStyles(theme.colors.redBase, theme.colors.redShade, theme.colors.white), - }; - - case 'link': - return { - borderColor: 'transparent', - background: buttonVariantStyles('transparent', 'transparent', theme.colors.linkExternal), - variantStyles: css` - &:focus { - outline: none; - box-shadow: none; - } - `, - }; - case 'primary': - default: - return { - borderColor: theme.colors.blueShade, - background: buttonVariantStyles(theme.colors.blueBase, theme.colors.blueShade, theme.colors.white), - }; - } -}; - -// Need to do this because of mismatch between variants in standard buttons and here -type StyleProps = Omit & { variant: ButtonVariant }; - -export const getButtonStyles = stylesFactory(({ theme, size, variant }: StyleProps) => { - const { padding, fontSize, height } = getPropertiesForButtonSize(theme, size); - const { background, borderColor, variantStyles } = getPropertiesForVariant(theme, variant); - - return { - button: cx( - css` - label: button; - display: inline-flex; - align-items: center; - font-weight: ${theme.typography.weight.semibold}; - font-family: ${theme.typography.fontFamily.sansSerif}; - line-height: ${theme.typography.lineHeight.md}; - font-size: ${fontSize}; - padding: ${padding}; - height: ${height}; - vertical-align: middle; - cursor: pointer; - border: 1px solid ${borderColor}; - border-radius: ${theme.border.radius.sm}; - ${background}; - - &[disabled], - &:disabled { - cursor: not-allowed; - opacity: 0.65; - box-shadow: none; - } - `, - getFocusStyle(theme), - css` - ${variantStyles} - ` - ), - buttonWithIcon: css` - padding-left: ${theme.spacing.sm}; - `, - // used for buttons with icon only - iconButton: css` - padding-right: 0; - `, - iconWrap: css` - label: button-icon-wrap; - & + * { - margin-left: ${theme.spacing.sm}; - } - `, - }; -}); - -// These are different from the standard Button where there are more variants. -export type ButtonVariant = 'primary' | 'secondary' | 'destructive' | 'link'; - -// These also needs to be different because the ButtonVariant is different -type CommonProps = { - size?: ComponentSize; - variant?: ButtonVariant; - icon?: string; - className?: string; -}; - -export type ButtonProps = CommonProps & ButtonHTMLAttributes; - -export const Button = React.forwardRef(({ variant, ...otherProps }, ref) => { - const theme = useContext(ThemeContext); - const styles = getButtonStyles({ - theme, - size: otherProps.size || 'md', - variant: variant || 'primary', - }); - return ; -}); - -type ButtonLinkProps = CommonProps & AnchorHTMLAttributes; -export const LinkButton = React.forwardRef(({ variant, ...otherProps }, ref) => { - const theme = useContext(ThemeContext); - const styles = getButtonStyles({ - theme, - size: otherProps.size || 'md', - variant: variant || 'primary', - }); - return ; -}); diff --git a/packages/grafana-ui/src/components/Forms/Form.story.tsx b/packages/grafana-ui/src/components/Forms/Form.story.tsx index 669d1ed4e36..ed0cfb73f52 100644 --- a/packages/grafana-ui/src/components/Forms/Form.story.tsx +++ b/packages/grafana-ui/src/components/Forms/Form.story.tsx @@ -5,7 +5,7 @@ import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { withStoryContainer } from '../../utils/storybook/withStoryContainer'; import { Field } from './Field'; import { Input } from './Input/Input'; -import { Button } from './Button'; +import { Button } from '../Button'; import { Form } from './Form'; import { Switch } from './Switch'; import { Checkbox } from './Checkbox'; diff --git a/packages/grafana-ui/src/components/Forms/Input/Input.story.tsx b/packages/grafana-ui/src/components/Forms/Input/Input.story.tsx index 1d3e5410501..35759d30ea8 100644 --- a/packages/grafana-ui/src/components/Forms/Input/Input.story.tsx +++ b/packages/grafana-ui/src/components/Forms/Input/Input.story.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { boolean, text, select, number } from '@storybook/addon-knobs'; import { withCenteredStory } from '../../../utils/storybook/withCenteredStory'; import { Input } from './Input'; -import { Button } from '../Button'; +import { Button } from '../../Button'; import mdx from './Input.mdx'; import { getAvailableIcons, IconType } from '../../Icon/types'; import { KeyValue } from '@grafana/data'; diff --git a/packages/grafana-ui/src/components/Forms/Select/ButtonSelect.tsx b/packages/grafana-ui/src/components/Forms/Select/ButtonSelect.tsx index a19cc3c1e4e..385ff160b85 100644 --- a/packages/grafana-ui/src/components/Forms/Select/ButtonSelect.tsx +++ b/packages/grafana-ui/src/components/Forms/Select/ButtonSelect.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { css } from 'emotion'; import { GrafanaTheme } from '@grafana/data'; -import { Button, ButtonVariant, ButtonProps } from '../Button'; +import { Button, ButtonVariant, ButtonProps } from '../../Button'; import { ComponentSize } from '../../../types/size'; import { SelectCommonProps, CustomControlProps } from './types'; import { SelectBase } from './SelectBase'; diff --git a/packages/grafana-ui/src/components/Forms/Select/Select.story.tsx b/packages/grafana-ui/src/components/Forms/Select/Select.story.tsx index 91e1eed5157..be65a37e752 100644 --- a/packages/grafana-ui/src/components/Forms/Select/Select.story.tsx +++ b/packages/grafana-ui/src/components/Forms/Select/Select.story.tsx @@ -5,7 +5,7 @@ import { SelectableValue } from '@grafana/data'; import { getAvailableIcons, IconType } from '../../Icon/types'; import { select, boolean } from '@storybook/addon-knobs'; import { Icon } from '../../Icon/Icon'; -import { Button } from '../Button'; +import { Button } from '../../Button'; import { ButtonSelect } from './ButtonSelect'; import { getIconKnob } from '../../../utils/storybook/knobs'; import kebabCase from 'lodash/kebabCase'; diff --git a/packages/grafana-ui/src/components/Forms/getFormStyles.ts b/packages/grafana-ui/src/components/Forms/getFormStyles.ts index bf623427db0..f1521a3910b 100644 --- a/packages/grafana-ui/src/components/Forms/getFormStyles.ts +++ b/packages/grafana-ui/src/components/Forms/getFormStyles.ts @@ -3,7 +3,7 @@ import { GrafanaTheme } from '@grafana/data'; import { getLabelStyles } from './Label'; import { getLegendStyles } from './Legend'; import { getFieldValidationMessageStyles } from './FieldValidationMessage'; -import { getButtonStyles, ButtonVariant } from './Button'; +import { getButtonStyles, ButtonVariant } from '../Button'; import { ComponentSize } from '../../types/size'; import { getInputStyles } from './Input/Input'; import { getSwitchStyles } from './Switch'; diff --git a/packages/grafana-ui/src/components/Forms/index.ts b/packages/grafana-ui/src/components/Forms/index.ts index 55f9b4ff077..40840e4376a 100644 --- a/packages/grafana-ui/src/components/Forms/index.ts +++ b/packages/grafana-ui/src/components/Forms/index.ts @@ -7,21 +7,22 @@ import { RadioButtonGroup } from './RadioButtonGroup/RadioButtonGroup'; import { AsyncSelect, Select } from './Select/Select'; import { Form } from './Form'; import { Field } from './Field'; -import { Button, LinkButton } from './Button'; import { Switch } from './Switch'; import { TextArea } from './TextArea/TextArea'; import { Checkbox } from './Checkbox'; +//Will be removed after Enterprise changes have been merged +import { Button, LinkButton } from '../Button'; const Forms = { RadioButtonGroup, + Button, + LinkButton, Switch, getFormStyles, Label, Input, Form, Field, - Button, - LinkButton, Select, ButtonSelect, InputControl, @@ -30,5 +31,4 @@ const Forms = { Checkbox, }; -export { ButtonVariant } from './Button'; export default Forms; diff --git a/packages/grafana-ui/src/components/Layout/Layout.story.tsx b/packages/grafana-ui/src/components/Layout/Layout.story.tsx index d382ffa3e0c..4f3214e1aae 100644 --- a/packages/grafana-ui/src/components/Layout/Layout.story.tsx +++ b/packages/grafana-ui/src/components/Layout/Layout.story.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory'; import { VerticalGroup, HorizontalGroup, Layout } from './Layout'; -import { Button } from '../Forms/Button'; +import { Button } from '../Button'; import { withStoryContainer } from '../../utils/storybook/withStoryContainer'; import { select } from '@storybook/addon-knobs'; @@ -11,7 +11,7 @@ export default { decorators: [withStoryContainer, withCenteredStory, withHorizontallyCenteredStory], }; -const justifyVariants = ['flex-start', 'flex-end', 'space-between']; +const justifyVariants = ['flex-start', 'flex-end', 'space-betw een']; const spacingVariants = ['xs', 'sm', 'md', 'lg']; diff --git a/packages/grafana-ui/src/components/Logs/LogDetailsRow.tsx b/packages/grafana-ui/src/components/Logs/LogDetailsRow.tsx index b83d46bc8e7..792a48e5ac6 100644 --- a/packages/grafana-ui/src/components/Logs/LogDetailsRow.tsx +++ b/packages/grafana-ui/src/components/Logs/LogDetailsRow.tsx @@ -127,7 +127,7 @@ class UnThemedLogDetailsRow extends PureComponent { <>   { )} > -
diff --git a/packages/grafana-ui/src/components/ThresholdsEditorNew/ThresholdsEditor.tsx b/packages/grafana-ui/src/components/ThresholdsEditorNew/ThresholdsEditor.tsx index c2c36588263..a01130dfbd7 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditorNew/ThresholdsEditor.tsx +++ b/packages/grafana-ui/src/components/ThresholdsEditorNew/ThresholdsEditor.tsx @@ -16,7 +16,7 @@ import { stylesFactory } from '../../themes'; import { Icon } from '../Icon/Icon'; import { RadioButtonGroup } from '../Forms/RadioButtonGroup/RadioButtonGroup'; import { Field } from '../Forms/Field'; -import { Button } from '../Forms/Button'; +import { Button } from '../Button'; import { FullWidthButtonContainer } from '../Button/FullWidthButtonContainer'; const modes: Array> = [ diff --git a/packages/grafana-ui/src/components/TimePicker/TimePickerContent/TimePickerCalendar.tsx b/packages/grafana-ui/src/components/TimePicker/TimePickerContent/TimePickerCalendar.tsx index a374ed8e01c..d78285e8413 100644 --- a/packages/grafana-ui/src/components/TimePicker/TimePickerContent/TimePickerCalendar.tsx +++ b/packages/grafana-ui/src/components/TimePicker/TimePickerContent/TimePickerCalendar.tsx @@ -5,7 +5,7 @@ import { GrafanaTheme, dateTime, TIME_FORMAT } from '@grafana/data'; import { stringToDateTimeType } from '../time'; import { useTheme, stylesFactory } from '../../../themes'; import { TimePickerTitle } from './TimePickerTitle'; -import Forms from '../../Forms'; +import { Button } from '../../Button'; import { Portal } from '../../Portal/Portal'; import { getThemeColors } from './colors'; import { ClickOutsideWrapper } from '../../ClickOutsideWrapper/ClickOutsideWrapper'; @@ -281,12 +281,12 @@ const Footer = memo(({ onClose, onApply }) => { return (
- + +
); }); diff --git a/packages/grafana-ui/src/components/TimePicker/TimePickerContent/TimeRangeForm.tsx b/packages/grafana-ui/src/components/TimePicker/TimePickerContent/TimeRangeForm.tsx index ce64b662dd8..1fa9fb5f592 100644 --- a/packages/grafana-ui/src/components/TimePicker/TimePickerContent/TimeRangeForm.tsx +++ b/packages/grafana-ui/src/components/TimePicker/TimePickerContent/TimeRangeForm.tsx @@ -4,6 +4,7 @@ import { stringToDateTimeType, isValidTimeString } from '../time'; import { mapStringsToTimeRange } from './mapper'; import { TimePickerCalendar } from './TimePickerCalendar'; import Forms from '../../Forms'; +import { Button } from '../../Button'; interface Props { isFullscreen: boolean; @@ -60,7 +61,7 @@ export const TimeRangeForm: React.FC = props => { [timeZone] ); - const icon = isFullscreen ? null : ; + const icon = isFullscreen ? null : {this.renderTransformationEditors()} - diff --git a/packages/grafana-ui/src/components/ValueMappingsEditor/LegacyValueMappingsEditor.tsx b/packages/grafana-ui/src/components/ValueMappingsEditor/LegacyValueMappingsEditor.tsx index 145c75efe78..07a73687858 100644 --- a/packages/grafana-ui/src/components/ValueMappingsEditor/LegacyValueMappingsEditor.tsx +++ b/packages/grafana-ui/src/components/ValueMappingsEditor/LegacyValueMappingsEditor.tsx @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import LegacyMappingRow from './LegacyMappingRow'; import { MappingType, ValueMapping } from '@grafana/data'; -import { Button } from '../Button/Button'; +import { Button } from '../Button'; import { PanelOptionsGroup } from '../PanelOptionsGroup/PanelOptionsGroup'; export interface Props { @@ -98,7 +98,7 @@ export class LegacyValueMappingsEditor extends PureComponent { removeValueMapping={() => this.onRemoveMapping(valueMapping.id)} /> ))} - diff --git a/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx b/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx index 22e453e1413..cfe15eba108 100644 --- a/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx +++ b/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { MappingType, ValueMapping } from '@grafana/data'; -import Forms from '../Forms'; +import { Button } from '../Button/Button'; import { FullWidthButtonContainer } from '../Button/FullWidthButtonContainer'; import { MappingRow } from './MappingRow'; @@ -66,9 +66,9 @@ export const ValueMappingsEditor: React.FC = ({ valueMappings, onChange, )} - + ); diff --git a/packages/grafana-ui/src/components/ValueMappingsEditor/__snapshots__/LegacyValueMappingsEditor.test.tsx.snap b/packages/grafana-ui/src/components/ValueMappingsEditor/__snapshots__/LegacyValueMappingsEditor.test.tsx.snap index 1698145ba54..fd0a8c0835c 100644 --- a/packages/grafana-ui/src/components/ValueMappingsEditor/__snapshots__/LegacyValueMappingsEditor.test.tsx.snap +++ b/packages/grafana-ui/src/components/ValueMappingsEditor/__snapshots__/LegacyValueMappingsEditor.test.tsx.snap @@ -37,7 +37,7 @@ exports[`Render should render component 1`] = ` diff --git a/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx b/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx index 2b6b1ed6943..b620b55cd83 100644 --- a/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx +++ b/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { IconType } from '../Icon/types'; import { SelectableValue } from '@grafana/data'; -import { Button, ButtonVariant } from '../Forms/Button'; +import { Button, ButtonVariant } from '../Button'; import { Select } from '../Forms/Select/Select'; import { FullWidthButtonContainer } from '../Button/FullWidthButtonContainer'; diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index c20c00d092e..2f1e741db56 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -6,7 +6,6 @@ export { Popover } from './Tooltip/Popover'; export { Portal } from './Portal/Portal'; export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar'; -export * from './Button/Button'; export { ClipboardButton } from './ClipboardButton/ClipboardButton'; // Select @@ -99,7 +98,7 @@ export { LogLabels } from './Logs/LogLabels'; export { LogRows } from './Logs/LogRows'; export { getLogRowStyles } from './Logs/getLogRowStyles'; export { ToggleButtonGroup, ToggleButton } from './ToggleButtonGroup/ToggleButtonGroup'; -// Panel editors +// Panel editors./Forms/Legacy/Button/FullWidthButtonContainer export { FullWidthButtonContainer } from './Button/FullWidthButtonContainer'; export { ThresholdsEditor } from './ThresholdsEditor/ThresholdsEditor'; export { ClickOutsideWrapper } from './ClickOutsideWrapper/ClickOutsideWrapper'; @@ -151,7 +150,8 @@ export { export { FieldConfigItemHeaderTitle } from './FieldConfigs/FieldConfigItemHeaderTitle'; // Next-gen forms -export { default as Forms, ButtonVariant } from './Forms'; +export { default as Forms } from './Forms'; +export * from './Button'; export { ValuePicker } from './ValuePicker/ValuePicker'; export { fieldMatchersUI } from './MatchersUI/fieldMatchersUI'; export { getStandardFieldConfigs } from './FieldConfigs/standardFieldConfigEditors'; diff --git a/packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts b/packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts index 27239abc6c3..f58636d1f74 100644 --- a/packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts +++ b/packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts @@ -168,11 +168,11 @@ $table-bg-hover: $dark-6; // Buttons // ------------------------- -$btn-secondary-bg: $blue-base; -$btn-secondary-bg-hl: $blue-shade; +$btn-primary-bg: $blue-base; +$btn-primary-bg-hl: $blue-shade; -$btn-primary-bg: $green-base; -$btn-primary-bg-hl: $green-shade; +$btn-secondary-bg: $dark-6; +$btn-secondary-bg-hl: lighten($dark-6, 4%); $btn-success-bg: $green-base; $btn-success-bg-hl: $green-shade; diff --git a/packages/grafana-ui/src/themes/_variables.light.scss.tmpl.ts b/packages/grafana-ui/src/themes/_variables.light.scss.tmpl.ts index 657a2d84aeb..ae4b96004a9 100644 --- a/packages/grafana-ui/src/themes/_variables.light.scss.tmpl.ts +++ b/packages/grafana-ui/src/themes/_variables.light.scss.tmpl.ts @@ -160,11 +160,11 @@ $table-bg-hover: $gray-5; // Buttons // ------------------------- -$btn-primary-bg: $green-base; -$btn-primary-bg-hl: $green-shade; +$btn-secondary-bg: $gray-5; +$btn-secondary-bg-hl: $gray-4; -$btn-secondary-bg: $blue-base; -$btn-secondary-bg-hl: $blue-shade; +$btn-primary-bg: $blue-base; +$btn-primary-bg-hl: $blue-shade; $btn-success-bg: $green-base; $btn-success-bg-hl: $green-shade; @@ -173,7 +173,6 @@ $btn-danger-bg: $red-base; $btn-danger-bg-hl: $red-shade; $btn-inverse-bg: $gray-5; -$btn-inverse-bg-hl: darken($gray-5, 5%); $btn-inverse-bg-hl: $gray-4; $btn-inverse-text-color: $gray-1; $btn-inverse-text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); diff --git a/public/app/core/angular_wrappers.ts b/public/app/core/angular_wrappers.ts index af2921302bc..fef6935f685 100644 --- a/public/app/core/angular_wrappers.ts +++ b/public/app/core/angular_wrappers.ts @@ -173,7 +173,6 @@ export function registerAngularDirectives() { ]); react2AngularDirective('saveDashboardAsButton', SaveDashboardAsButtonConnected, [ 'variant', - 'useNewForms', ['getDashboard', { watchDepth: 'reference', wrapApply: true }], ['onSaveSuccess', { watchDepth: 'reference', wrapApply: true }], ]); diff --git a/public/app/core/components/OrgSwitcher.tsx b/public/app/core/components/OrgSwitcher.tsx index aa86c5dedb3..39b13958d7a 100644 --- a/public/app/core/components/OrgSwitcher.tsx +++ b/public/app/core/components/OrgSwitcher.tsx @@ -65,7 +65,7 @@ export class OrgSwitcher extends React.PureComponent { {org.orgId === currentOrgId ? ( ) : ( - )} diff --git a/public/app/features/admin/UpgradePage.tsx b/public/app/features/admin/UpgradePage.tsx index 1826578caff..58ca87b6811 100644 --- a/public/app/features/admin/UpgradePage.tsx +++ b/public/app/features/admin/UpgradePage.tsx @@ -3,7 +3,7 @@ import { css } from 'emotion'; import { NavModel } from '@grafana/data'; import Page from '../../core/components/Page/Page'; import { LicenseChrome } from './LicenseChrome'; -import { Forms } from '@grafana/ui'; +import { LinkButton } from '@grafana/ui'; import { hot } from 'react-hot-loader'; import { StoreState } from '../../types'; import { getNavModel } from '../../core/selectors/navModel'; @@ -69,13 +69,13 @@ const GetEnterprise: React.FC = () => { const CallToAction: React.FC = () => { return ( - Contact us and get a free trial - + ); }; diff --git a/public/app/features/admin/UserCreatePage.tsx b/public/app/features/admin/UserCreatePage.tsx index 3ba35eebb86..a721c281346 100644 --- a/public/app/features/admin/UserCreatePage.tsx +++ b/public/app/features/admin/UserCreatePage.tsx @@ -1,7 +1,7 @@ import React, { useCallback } from 'react'; import { hot } from 'react-hot-loader'; import { connect } from 'react-redux'; -import { Forms } from '@grafana/ui'; +import { Forms, Button } from '@grafana/ui'; import { NavModel } from '@grafana/data'; import { getBackendSrv } from '@grafana/runtime'; import { StoreState } from '../../types'; @@ -62,7 +62,7 @@ const UserCreatePage: React.FC = ({ navModel, updateLocatio })} /> - Create user + ); }} diff --git a/public/app/features/admin/UserLdapSyncInfo.tsx b/public/app/features/admin/UserLdapSyncInfo.tsx index f3410de5ef5..38b5fa4aabf 100644 --- a/public/app/features/admin/UserLdapSyncInfo.tsx +++ b/public/app/features/admin/UserLdapSyncInfo.tsx @@ -71,7 +71,7 @@ export class UserLdapSyncInfo extends PureComponent { - + Debug LDAP Mapping diff --git a/public/app/features/admin/UserListAdminPage.tsx b/public/app/features/admin/UserListAdminPage.tsx index f7a6d34bc75..ec25aa6aa70 100644 --- a/public/app/features/admin/UserListAdminPage.tsx +++ b/public/app/features/admin/UserListAdminPage.tsx @@ -3,7 +3,7 @@ import { css, cx } from 'emotion'; import { hot } from 'react-hot-loader'; import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux'; import { NavModel } from '@grafana/data'; -import { Pagination, Forms, Tooltip, HorizontalGroup, stylesFactory } from '@grafana/ui'; +import { Pagination, Forms, Tooltip, HorizontalGroup, stylesFactory, LinkButton } from '@grafana/ui'; import { StoreState, UserDTO } from '../../types'; import Page from 'app/core/components/Page/Page'; import { getNavModel } from '../../core/selectors/navModel'; @@ -53,9 +53,9 @@ const UserListAdminPageUnConnected: React.FC = props => { onChange={event => props.changeQuery(event.currentTarget.value)} prefix={} /> - + New user - + diff --git a/public/app/features/admin/UserOrgs.tsx b/public/app/features/admin/UserOrgs.tsx index 6cd048bfad1..eafffe2c0e5 100644 --- a/public/app/features/admin/UserOrgs.tsx +++ b/public/app/features/admin/UserOrgs.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import { css, cx } from 'emotion'; -import { Modal, Themeable, stylesFactory, withTheme, ConfirmButton, Forms } from '@grafana/ui'; +import { Modal, Themeable, stylesFactory, withTheme, ConfirmButton, Button } from '@grafana/ui'; import { GrafanaTheme } from '@grafana/data'; import { UserOrg, Organization } from 'app/types'; import { OrgPicker, OrgSelectItem } from 'app/core/components/Select/OrgPicker'; @@ -52,9 +52,9 @@ export class UserOrgs extends PureComponent {
- +
@@ -169,7 +169,7 @@ class UnThemedOrgRow extends PureComponent {
- + +
); diff --git a/public/app/features/admin/UserProfile.tsx b/public/app/features/admin/UserProfile.tsx index 78ba46cd355..59de6d26f36 100644 --- a/public/app/features/admin/UserProfile.tsx +++ b/public/app/features/admin/UserProfile.tsx @@ -3,7 +3,7 @@ import { UserDTO } from 'app/types'; import { cx, css } from 'emotion'; import { config } from 'app/core/config'; import { GrafanaTheme } from '@grafana/data'; -import { ConfirmButton, Input, ConfirmModal, InputStatus, Forms, stylesFactory } from '@grafana/ui'; +import { ConfirmButton, Input, ConfirmModal, InputStatus, Button, stylesFactory } from '@grafana/ui'; interface Props { user: UserDTO; @@ -125,9 +125,9 @@ export class UserProfile extends PureComponent {
- + { onDismiss={this.showDeleteUserModal(false)} /> {user.isDisabled ? ( - + ) : ( - + )} {
Force logout @@ -82,9 +82,9 @@ export class UserSessions extends PureComponent {
{sessions.length > 0 && ( - + )}
- +
diff --git a/public/app/features/dashboard/components/Inspector/PanelInspector.tsx b/public/app/features/dashboard/components/Inspector/PanelInspector.tsx index f1fcd5fd536..ad6e7aa097d 100644 --- a/public/app/features/dashboard/components/Inspector/PanelInspector.tsx +++ b/public/app/features/dashboard/components/Inspector/PanelInspector.tsx @@ -6,7 +6,7 @@ import { css } from 'emotion'; import { InspectHeader } from './InspectHeader'; import { DashboardModel, PanelModel } from 'app/features/dashboard/state'; -import { JSONFormatter, Drawer, Select, Table, TabContent, Forms, stylesFactory, CustomScrollbar } from '@grafana/ui'; +import { JSONFormatter, Drawer, Select, Table, TabContent, stylesFactory, CustomScrollbar, Button } from '@grafana/ui'; import { getLocationSrv, getDataSourceSrv } from '@grafana/runtime'; import { DataFrame, @@ -189,9 +189,9 @@ export class PanelInspector extends PureComponent { )}
- this.exportCsv(processed[selected])}> +
diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index d666d42ec73..d000ee3f8ea 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import { FieldConfigSource, GrafanaTheme, PanelData, PanelPlugin, SelectableValue } from '@grafana/data'; -import { Forms, stylesFactory } from '@grafana/ui'; +import { Forms, stylesFactory, Button } from '@grafana/ui'; import { css, cx } from 'emotion'; import config from 'app/core/config'; import AutoSizer from 'react-virtualized-auto-sizer'; @@ -198,9 +198,9 @@ export class PanelEditorUnconnected extends PureComponent {
- +
{
- = ({ getDashboard, useNewForms, }) => { - const ButtonComponent = useNewForms ? Forms.Button : Button; return ( {({ showModal, hideModal }) => { return ( - { showModal(SaveDashboardModalProxy, { // TODO[angular-migrations]: Remove tenary op when we migrate Dashboard Settings view to React @@ -40,46 +38,41 @@ export const SaveDashboardButton: React.FC = ({ }} > Save dashboard - + ); }} ); }; -export const SaveDashboardAsButton: React.FC = ({ +export const SaveDashboardAsButton: React.FC = ({ dashboard, onSaveSuccess, getDashboard, - useNewForms, variant, }) => { - const ButtonComponent = useNewForms ? Forms.Button : Button; return ( {({ showModal, hideModal }) => { return ( - { - showModal(SaveDashboardAsModal, { - // TODO[angular-migrations]: Remove tenary op when we migrate Dashboard Settings view to React - dashboard: getDashboard ? getDashboard() : dashboard, - onSaveSuccess, - onDismiss: hideModal, - }); - }} - // TODO[angular-migrations]: Hacking the different variants for this single button - // In Dashboard Settings in sidebar we need to use new form but with inverse variant to make it look like it should - // Everywhere else we use old button component :( - variant={variant as any} - > - Save As... - + + + ); }} diff --git a/public/app/features/dashboard/components/SaveDashboard/SaveDashboardErrorProxy.tsx b/public/app/features/dashboard/components/SaveDashboard/SaveDashboardErrorProxy.tsx index 40ecccee62a..0ec5cfee301 100644 --- a/public/app/features/dashboard/components/SaveDashboard/SaveDashboardErrorProxy.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/SaveDashboardErrorProxy.tsx @@ -89,7 +89,7 @@ const ConfirmPluginDashboardSaveModal: React.FC = ({ on - diff --git a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.tsx b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.tsx index 7d56b839dfb..5feaa7c5bba 100644 --- a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardAsForm.tsx @@ -101,9 +101,9 @@ export const SaveDashboardAsForm: React.FC Save - + )} diff --git a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.tsx b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.tsx index 4768a8c80d7..0b280feab1a 100644 --- a/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.tsx @@ -62,9 +62,9 @@ export const SaveDashboardForm: React.FC = ({ dashboard, - + )} diff --git a/public/app/features/dashboard/components/SaveDashboard/forms/SaveProvisionedDashboardForm.tsx b/public/app/features/dashboard/components/SaveDashboard/forms/SaveProvisionedDashboardForm.tsx index 6d8d7bd6513..67bca91f0b8 100644 --- a/public/app/features/dashboard/components/SaveDashboard/forms/SaveProvisionedDashboardForm.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/forms/SaveProvisionedDashboardForm.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useMemo } from 'react'; import { css } from 'emotion'; import { saveAs } from 'file-saver'; -import { CustomScrollbar, Forms, Button, HorizontalGroup, JSONFormatter, VerticalGroup } from '@grafana/ui'; +import { CustomScrollbar, Button, HorizontalGroup, JSONFormatter, VerticalGroup } from '@grafana/ui'; import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard'; import { SaveDashboardFormProps } from '../types'; @@ -61,9 +61,9 @@ export const SaveProvisionedDashboardForm: React.FC = ({ Copy JSON to clipboard - + diff --git a/public/app/features/dashboard/components/ShareModal/ShareExport.tsx b/public/app/features/dashboard/components/ShareModal/ShareExport.tsx index 3512a82961d..1d5557627a6 100644 --- a/public/app/features/dashboard/components/ShareModal/ShareExport.tsx +++ b/public/app/features/dashboard/components/ShareModal/ShareExport.tsx @@ -108,7 +108,7 @@ export class ShareExport extends PureComponent { -
diff --git a/public/app/features/dashboard/components/ShareModal/ShareLink.tsx b/public/app/features/dashboard/components/ShareModal/ShareLink.tsx index 5e7c8941f47..2e9ea52c2bd 100644 --- a/public/app/features/dashboard/components/ShareModal/ShareLink.tsx +++ b/public/app/features/dashboard/components/ShareModal/ShareLink.tsx @@ -121,7 +121,7 @@ export class ShareLink extends PureComponent {
- + Copy
diff --git a/public/app/features/dashboard/components/ShareModal/ShareSnapshot.tsx b/public/app/features/dashboard/components/ShareModal/ShareSnapshot.tsx index 13f22fc7d4c..5467bfb8fb4 100644 --- a/public/app/features/dashboard/components/ShareModal/ShareSnapshot.tsx +++ b/public/app/features/dashboard/components/ShareModal/ShareSnapshot.tsx @@ -249,7 +249,7 @@ export class ShareSnapshot extends PureComponent { {sharingButtonText} )} - @@ -268,7 +268,7 @@ export class ShareSnapshot extends PureComponent { {snapshotUrl}
- + Copy Link diff --git a/public/app/features/explore/RichHistory/RichHistoryCard.tsx b/public/app/features/explore/RichHistory/RichHistoryCard.tsx index 663c2612921..0f0f86cbe78 100644 --- a/public/app/features/explore/RichHistory/RichHistoryCard.tsx +++ b/public/app/features/explore/RichHistory/RichHistoryCard.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { connect } from 'react-redux'; import { hot } from 'react-hot-loader'; import { css, cx } from 'emotion'; -import { stylesFactory, useTheme, Forms } from '@grafana/ui'; +import { stylesFactory, useTheme, Forms, Button } from '@grafana/ui'; import { GrafanaTheme, AppEvents, DataSourceApi } from '@grafana/data'; import { RichHistoryQuery, ExploreId } from 'app/types/explore'; import { copyStringToClipboard, createUrlFromRichHistory, createDataQuery } from 'app/core/utils/richHistory'; @@ -202,10 +202,10 @@ export function RichHistoryCard(props: Props) { className={styles.textArea} />
- Save comment - + +
); @@ -257,9 +257,9 @@ export function RichHistoryCard(props: Props) { {!activeUpdateComment && (
- +
)} diff --git a/public/app/features/explore/RichHistory/RichHistorySettings.tsx b/public/app/features/explore/RichHistory/RichHistorySettings.tsx index 1828f7d282e..a3911e91a8b 100644 --- a/public/app/features/explore/RichHistory/RichHistorySettings.tsx +++ b/public/app/features/explore/RichHistory/RichHistorySettings.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { css } from 'emotion'; -import { stylesFactory, useTheme, Forms } from '@grafana/ui'; +import { stylesFactory, useTheme, Forms, Button } from '@grafana/ui'; import { GrafanaTheme, AppEvents } from '@grafana/data'; import appEvents from 'app/core/app_events'; import { CoreEvents } from 'app/types'; @@ -112,9 +112,9 @@ export function RichHistorySettings(props: RichHistorySettingsProps) { > Delete all of your query history, permanently. - + ); } diff --git a/public/app/features/explore/RunButton.tsx b/public/app/features/explore/RunButton.tsx index 681f9735fc4..861e3efd9e1 100644 --- a/public/app/features/explore/RunButton.tsx +++ b/public/app/features/explore/RunButton.tsx @@ -36,7 +36,7 @@ export function RunButton(props: Props) { title={loading ? 'Cancel' : 'Run Query'} onClick={() => onRun(loading)} buttonClassName={classNames({ - 'navbar-button--secondary': !loading, + 'navbar-button--primary': !loading, 'navbar-button--danger': loading, 'btn--radius-right-0': showDropdown, })} @@ -49,7 +49,7 @@ export function RunButton(props: Props) { { })} /> - Create + )} diff --git a/public/app/features/org/NewOrgPage.tsx b/public/app/features/org/NewOrgPage.tsx index 9059ad10b16..34fc9eb28da 100644 --- a/public/app/features/org/NewOrgPage.tsx +++ b/public/app/features/org/NewOrgPage.tsx @@ -1,7 +1,7 @@ import React, { FC } from 'react'; import { getBackendSrv } from '@grafana/runtime'; import Page from 'app/core/components/Page/Page'; -import { Forms } from '@grafana/ui'; +import { Forms, Button } from '@grafana/ui'; import { getConfig } from 'app/core/config'; import { StoreState } from 'app/types'; import { hot } from 'react-hot-loader'; @@ -68,7 +68,7 @@ export const NewOrgPage: FC = ({ navModel }) => { })} /> - Create + ); }} diff --git a/public/app/features/org/UserInviteForm.tsx b/public/app/features/org/UserInviteForm.tsx index 6f18426c4ce..4e3f8e88688 100644 --- a/public/app/features/org/UserInviteForm.tsx +++ b/public/app/features/org/UserInviteForm.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react'; -import { Forms, HorizontalGroup } from '@grafana/ui'; +import { Forms, HorizontalGroup, Button, LinkButton } from '@grafana/ui'; import { getConfig } from 'app/core/config'; import { OrgRole } from 'app/types'; import { getBackendSrv } from '@grafana/runtime'; @@ -71,10 +71,10 @@ export const UserInviteForm: FC = ({ updateLocation }) => { - Submit - + + Back - + ); diff --git a/public/app/features/plugins/wrappers/AppConfigWrapper.tsx b/public/app/features/plugins/wrappers/AppConfigWrapper.tsx index 0e01c60e3f9..44b38735a99 100644 --- a/public/app/features/plugins/wrappers/AppConfigWrapper.tsx +++ b/public/app/features/plugins/wrappers/AppConfigWrapper.tsx @@ -80,7 +80,7 @@ export class AppConfigCtrlWrapper extends PureComponent { )} {model.enabled && ( - )} diff --git a/public/app/features/profile/ChangePasswordForm.tsx b/public/app/features/profile/ChangePasswordForm.tsx index 05d84d04ec2..0aea8b14936 100644 --- a/public/app/features/profile/ChangePasswordForm.tsx +++ b/public/app/features/profile/ChangePasswordForm.tsx @@ -63,7 +63,7 @@ export class ChangePasswordForm extends PureComponent { - + Cancel diff --git a/public/app/features/profile/SignupForm.tsx b/public/app/features/profile/SignupForm.tsx index 94a73836c32..342ef9300b1 100644 --- a/public/app/features/profile/SignupForm.tsx +++ b/public/app/features/profile/SignupForm.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react'; -import { Forms } from '@grafana/ui'; +import { Forms, Button, LinkButton } from '@grafana/ui'; import { css } from 'emotion'; import { getConfig } from 'app/core/config'; @@ -106,11 +106,11 @@ export const SignupForm: FC = props => { /> - Submit + - + Back - +
); diff --git a/public/app/features/profile/UserOrganizations.tsx b/public/app/features/profile/UserOrganizations.tsx index 7c982b1c299..01a2941f3b3 100644 --- a/public/app/features/profile/UserOrganizations.tsx +++ b/public/app/features/profile/UserOrganizations.tsx @@ -48,7 +48,7 @@ export class UserOrganizations extends PureComponent { Current ) : ( )} diff --git a/public/app/plugins/datasource/elasticsearch/configuration/DataLink.tsx b/public/app/plugins/datasource/elasticsearch/configuration/DataLink.tsx index a006e684119..446f4d1ff81 100644 --- a/public/app/plugins/datasource/elasticsearch/configuration/DataLink.tsx +++ b/public/app/plugins/datasource/elasticsearch/configuration/DataLink.tsx @@ -49,7 +49,7 @@ export const DataLink = (props: Props) => { onChange={handleChange('field')} /> {value && value.length > 0 && ( - )} diff --git a/public/app/plugins/panel/news/NewsPanelEditor.tsx b/public/app/plugins/panel/news/NewsPanelEditor.tsx index 0d380122c38..9b7c1d0bd9b 100755 --- a/public/app/plugins/panel/news/NewsPanelEditor.tsx +++ b/public/app/plugins/panel/news/NewsPanelEditor.tsx @@ -58,7 +58,7 @@ export class NewsPanelEditor extends PureComponent

If the feed is unable to connect, consider a CORS proxy
-
diff --git a/public/sass/_variables.dark.generated.scss b/public/sass/_variables.dark.generated.scss index 0e4cfc18fe2..ac18b892a82 100644 --- a/public/sass/_variables.dark.generated.scss +++ b/public/sass/_variables.dark.generated.scss @@ -171,11 +171,11 @@ $table-bg-hover: $dark-6; // Buttons // ------------------------- -$btn-secondary-bg: $blue-base; -$btn-secondary-bg-hl: $blue-shade; +$btn-primary-bg: $blue-base; +$btn-primary-bg-hl: $blue-shade; -$btn-primary-bg: $green-base; -$btn-primary-bg-hl: $green-shade; +$btn-secondary-bg: $dark-6; +$btn-secondary-bg-hl: lighten($dark-6, 4%); $btn-success-bg: $green-base; $btn-success-bg-hl: $green-shade; diff --git a/public/sass/_variables.light.generated.scss b/public/sass/_variables.light.generated.scss index 983ec849e78..c93664deb2e 100644 --- a/public/sass/_variables.light.generated.scss +++ b/public/sass/_variables.light.generated.scss @@ -163,11 +163,11 @@ $table-bg-hover: $gray-5; // Buttons // ------------------------- -$btn-primary-bg: $green-base; -$btn-primary-bg-hl: $green-shade; +$btn-secondary-bg: $gray-5; +$btn-secondary-bg-hl: $gray-4; -$btn-secondary-bg: $blue-base; -$btn-secondary-bg-hl: $blue-shade; +$btn-primary-bg: $blue-base; +$btn-primary-bg-hl: $blue-shade; $btn-success-bg: $green-base; $btn-success-bg-hl: $green-shade; @@ -176,7 +176,6 @@ $btn-danger-bg: $red-base; $btn-danger-bg-hl: $red-shade; $btn-inverse-bg: $gray-5; -$btn-inverse-bg-hl: darken($gray-5, 5%); $btn-inverse-bg-hl: $gray-4; $btn-inverse-text-color: $gray-1; $btn-inverse-text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); diff --git a/public/sass/components/_navbar.scss b/public/sass/components/_navbar.scss index 6402328b8a5..66ace15bd1f 100644 --- a/public/sass/components/_navbar.scss +++ b/public/sass/components/_navbar.scss @@ -171,8 +171,8 @@ i.navbar-page-btn__search { } } - &--secondary { - @include buttonBackground($btn-secondary-bg, $btn-secondary-bg-hl); + &--primary { + @include buttonBackground($btn-primary-bg, $btn-primary-bg-hl); } &:hover {