mirror of https://github.com/grafana/grafana.git
Form Migrations: Button (#23019)
* Update legacy exports and fix Type errors * Remove Button and LinkButton from Forms namespace * Fix errors * Update snapshots * Move Legacy button * Migrate more Buttons * Remove legacy button dependency * Move button up * Remove legacy button * Update Snapshots * Fix ComponentSize issues * Switch primary button * Switch primary * Add classNames and fix some angular directive issues * Fix failing build and remove log Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
parent
f63877f247
commit
5cdb8f8e44
|
|
@ -59,5 +59,22 @@ Used for removing or deleting entities.
|
||||||
</div>
|
</div>
|
||||||
</Preview>
|
</Preview>
|
||||||
|
|
||||||
|
## Link
|
||||||
|
|
||||||
|
Used for for hyperlinks.
|
||||||
|
|
||||||
|
<Preview>
|
||||||
|
<div>
|
||||||
|
<Button href="/" variant="link" size="sm" renderAs="button" style={{ margin: '5px' }}>
|
||||||
|
Small
|
||||||
|
</Button>
|
||||||
|
<Button href="/" variant="link" size="md" renderAs="button" style={{ margin: '5px' }}>
|
||||||
|
Medium
|
||||||
|
</Button>
|
||||||
|
<Button href="/" variant="link" size="lg" renderAs="button" style={{ margin: '5px' }}>
|
||||||
|
Large
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Preview>
|
||||||
|
|
||||||
<Props of={Button} />
|
<Props of={Button} />
|
||||||
|
|
@ -1,45 +1,35 @@
|
||||||
import { storiesOf } from '@storybook/react';
|
import React from 'react';
|
||||||
import { Button, LinkButton } from './Button';
|
import { select, text } from '@storybook/addon-knobs';
|
||||||
// @ts-ignore
|
import { Button, ButtonVariant } from './Button';
|
||||||
import withPropsCombinations from 'react-storybook-addon-props-combinations';
|
import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||||
import { action } from '@storybook/addon-actions';
|
|
||||||
import { ThemeableCombinationsRowRenderer } from '../../utils/storybook/CombinationsRowRenderer';
|
|
||||||
import { boolean } from '@storybook/addon-knobs';
|
|
||||||
import { getIconKnob } from '../../utils/storybook/knobs';
|
import { getIconKnob } from '../../utils/storybook/knobs';
|
||||||
|
import mdx from './Button.mdx';
|
||||||
|
import { ComponentSize } from '../../types/size';
|
||||||
|
|
||||||
const ButtonStories = storiesOf('General/Button', module);
|
export default {
|
||||||
|
title: 'Forms/Button',
|
||||||
const defaultProps = {
|
component: Button,
|
||||||
onClick: [action('Button clicked')],
|
decorators: [withCenteredStory, withHorizontallyCenteredStory],
|
||||||
children: ['Click click!'],
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
page: mdx,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const variants = {
|
const variants = ['primary', 'secondary', 'destructive', 'link'];
|
||||||
size: ['xs', 'sm', 'md', 'lg'],
|
|
||||||
variant: ['primary', 'secondary', 'danger', 'inverse', 'transparent', 'link'],
|
|
||||||
};
|
|
||||||
const combinationOptions = {
|
|
||||||
CombinationRenderer: ThemeableCombinationsRowRenderer,
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderButtonStory = (buttonComponent: typeof Button | typeof LinkButton) => {
|
const sizes = ['sm', 'md', 'lg'];
|
||||||
const isDisabled = boolean('Disable button', false);
|
|
||||||
return withPropsCombinations(
|
|
||||||
buttonComponent,
|
|
||||||
{ ...variants, ...defaultProps, disabled: [isDisabled] },
|
|
||||||
combinationOptions
|
|
||||||
)();
|
|
||||||
};
|
|
||||||
|
|
||||||
ButtonStories.add('as button element', () => renderButtonStory(Button));
|
export const simple = () => {
|
||||||
|
const variant = select('Variant', variants, 'primary');
|
||||||
ButtonStories.add('as link element', () => renderButtonStory(LinkButton));
|
const size = select('Size', sizes, 'md');
|
||||||
|
const buttonText = text('text', 'Button');
|
||||||
ButtonStories.add('with icon', () => {
|
|
||||||
const icon = getIconKnob();
|
const icon = getIconKnob();
|
||||||
return withPropsCombinations(
|
|
||||||
Button,
|
return (
|
||||||
{ ...variants, ...defaultProps, icon: [icon && `fa fa-${icon}`] },
|
<Button variant={variant as ButtonVariant} size={size as ComponentSize} icon={icon && `fa fa-${icon}`}>
|
||||||
combinationOptions
|
{buttonText}
|
||||||
)();
|
</Button>
|
||||||
});
|
);
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -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(<Button icon={'fa fa-plus'}>Click me</Button>);
|
|
||||||
expect(wrapper.html()).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('LinkButton', () => {
|
|
||||||
it('renders correct html', () => {
|
|
||||||
const wrapper = mount(<LinkButton icon={'fa fa-plus'}>Click me</LinkButton>);
|
|
||||||
expect(wrapper.html()).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('allows a disable state on link button', () => {
|
|
||||||
const wrapper = mount(
|
|
||||||
<LinkButton disabled icon={'fa fa-plus'}>
|
|
||||||
Click me
|
|
||||||
</LinkButton>
|
|
||||||
);
|
|
||||||
expect(wrapper.find('a[disabled]').length).toBe(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,72 +1,178 @@
|
||||||
import React, { AnchorHTMLAttributes, ButtonHTMLAttributes, useContext } from 'react';
|
import React, { AnchorHTMLAttributes, ButtonHTMLAttributes, useContext } from 'react';
|
||||||
import { ThemeContext } from '../../themes';
|
import { css, cx } from 'emotion';
|
||||||
import { getButtonStyles } from './styles';
|
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 { ButtonContent } from './ButtonContent';
|
||||||
import { ComponentSize } from '../../types/size';
|
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 = {
|
type CommonProps = {
|
||||||
size?: ComponentSize;
|
size?: ComponentSize;
|
||||||
variant?: ButtonVariant;
|
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;
|
icon?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
styles?: ButtonStyles;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ButtonProps = CommonProps & ButtonHTMLAttributes<HTMLButtonElement>;
|
export type ButtonProps = CommonProps & ButtonHTMLAttributes<HTMLButtonElement>;
|
||||||
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>((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.
|
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||||
buttonProps.type = buttonProps.type || 'button';
|
({ variant, icon, children, className, ...otherProps }, ref) => {
|
||||||
|
const theme = useContext(ThemeContext);
|
||||||
const styles: ButtonStyles =
|
const styles = getButtonStyles({
|
||||||
stylesProp ||
|
|
||||||
getButtonStyles({
|
|
||||||
theme,
|
theme,
|
||||||
size: size || 'md',
|
size: otherProps.size || 'md',
|
||||||
variant: variant || 'primary',
|
variant: variant || 'primary',
|
||||||
textAndIcon: !!(children && icon),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className={cx(styles.button, className)} {...buttonProps} ref={ref}>
|
<button className={cx(styles.button, className)} {...otherProps} ref={ref}>
|
||||||
<ButtonContent icon={icon}>{children}</ButtonContent>
|
<ButtonContent icon={icon}>{children}</ButtonContent>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
Button.displayName = 'Button';
|
Button.displayName = 'Button';
|
||||||
|
|
||||||
export type LinkButtonProps = CommonProps &
|
type ButtonLinkProps = CommonProps & AnchorHTMLAttributes<HTMLAnchorElement>;
|
||||||
AnchorHTMLAttributes<HTMLAnchorElement> & {
|
export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
|
||||||
// We allow disabled here even though it is not standard for a link. We use it as a selector to style it as
|
({ variant, icon, children, className, ...otherProps }, ref) => {
|
||||||
// disabled.
|
const theme = useContext(ThemeContext);
|
||||||
disabled?: boolean;
|
const styles = getButtonStyles({
|
||||||
};
|
|
||||||
|
|
||||||
export const LinkButton = React.forwardRef<HTMLAnchorElement, LinkButtonProps>((props, ref) => {
|
|
||||||
const theme = useContext(ThemeContext);
|
|
||||||
const { size, variant, icon, children, className, styles: stylesProp, ...anchorProps } = props;
|
|
||||||
const styles: ButtonStyles =
|
|
||||||
stylesProp ||
|
|
||||||
getButtonStyles({
|
|
||||||
theme,
|
theme,
|
||||||
size: size || 'md',
|
size: otherProps.size || 'md',
|
||||||
variant: variant || 'primary',
|
variant: variant || 'primary',
|
||||||
textAndIcon: !!(children && icon),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a className={cx(styles.button, className)} {...anchorProps} ref={ref}>
|
<a className={cx(styles.button, className)} {...otherProps} ref={ref}>
|
||||||
<ButtonContent icon={icon}>{children}</ButtonContent>
|
<ButtonContent icon={icon}>{children}</ButtonContent>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
LinkButton.displayName = 'LinkButton';
|
LinkButton.displayName = 'LinkButton';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`Button renders correct html 1`] = `"<button class=\\"css-12s5hlm-button\\" type=\\"button\\"><span class=\\"css-1beih13\\"><span class=\\"css-1rgbe4\\"><i class=\\"fa fa-plus\\"></i></span><span>Click me</span></span></button>"`;
|
|
||||||
|
|
||||||
exports[`LinkButton renders correct html 1`] = `"<a class=\\"css-12s5hlm-button\\"><span class=\\"css-1beih13\\"><span class=\\"css-1rgbe4\\"><i class=\\"fa fa-plus\\"></i></span><span>Click me</span></span></a>"`;
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './Button';
|
||||||
|
|
@ -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,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import Clipboard from 'clipboard';
|
import Clipboard from 'clipboard';
|
||||||
import { Button, ButtonProps } from '../Button/Button';
|
import { Button, ButtonProps } from '../Button';
|
||||||
|
|
||||||
interface Props extends ButtonProps {
|
interface Props extends ButtonProps {
|
||||||
getText(): string;
|
getText(): string;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
|
export { ClipboardButton } from '../ClipboardButton/ClipboardButton';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { storiesOf } from '@storybook/react';
|
import { storiesOf } from '@storybook/react';
|
||||||
import { text, boolean, select } from '@storybook/addon-knobs';
|
import { text, boolean, select } from '@storybook/addon-knobs';
|
||||||
import { ConfirmButton } from './ConfirmButton';
|
import { ConfirmButton } from './ConfirmButton';
|
||||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { Button } from '../Button/Button';
|
import { Button } from '../Button';
|
||||||
|
|
||||||
const getKnobs = () => {
|
const getKnobs = () => {
|
||||||
return {
|
return {
|
||||||
|
|
@ -16,9 +17,8 @@ const getKnobs = () => {
|
||||||
{
|
{
|
||||||
primary: 'primary',
|
primary: 'primary',
|
||||||
secondary: 'secondary',
|
secondary: 'secondary',
|
||||||
danger: 'danger',
|
destructive: 'destructive',
|
||||||
inverse: 'inverse',
|
link: 'link',
|
||||||
transparent: 'transparent',
|
|
||||||
},
|
},
|
||||||
'primary'
|
'primary'
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ConfirmButton } from './ConfirmButton';
|
import { ConfirmButton } from './ConfirmButton';
|
||||||
import { mount, ShallowWrapper } from 'enzyme';
|
import { mount, ShallowWrapper } from 'enzyme';
|
||||||
import { Button } from '../Button/Button';
|
import { Button } from '../Button';
|
||||||
|
|
||||||
describe('ConfirmButton', () => {
|
describe('ConfirmButton', () => {
|
||||||
let wrapper: any;
|
let wrapper: any;
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,7 @@ import { stylesFactory, withTheme } from '../../themes';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
import { Themeable } from '../../types';
|
import { Themeable } from '../../types';
|
||||||
import { ComponentSize } from '../../types/size';
|
import { ComponentSize } from '../../types/size';
|
||||||
import { Button } from '../Button/Button';
|
import { Button, ButtonVariant } from '../Button';
|
||||||
import Forms from '../Forms';
|
|
||||||
import { ButtonVariant } from '../Button/types';
|
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||||
return {
|
return {
|
||||||
|
|
@ -135,9 +133,9 @@ class UnThemedConfirmButton extends PureComponent<Props, State> {
|
||||||
<span className={styles.buttonContainer}>
|
<span className={styles.buttonContainer}>
|
||||||
{typeof children === 'string' ? (
|
{typeof children === 'string' ? (
|
||||||
<span className={buttonClass}>
|
<span className={buttonClass}>
|
||||||
<Forms.Button size={size} variant="link" onClick={onClick}>
|
<Button size={size} variant="link" onClick={onClick}>
|
||||||
{children}
|
{children}
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className={buttonClass} onClick={onClick}>
|
<span className={buttonClass} onClick={onClick}>
|
||||||
|
|
@ -146,7 +144,7 @@ class UnThemedConfirmButton extends PureComponent<Props, State> {
|
||||||
)}
|
)}
|
||||||
<span className={styles.confirmButtonContainer}>
|
<span className={styles.confirmButtonContainer}>
|
||||||
<span className={confirmButtonClass}>
|
<span className={confirmButtonClass}>
|
||||||
<Button size={size} variant="transparent" onClick={this.onClickCancel}>
|
<Button size={size} variant="secondary" onClick={this.onClickCancel}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button size={size} variant={confirmButtonVariant} onClick={onConfirm}>
|
<Button size={size} variant={confirmButtonVariant} onClick={onConfirm}>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { ConfirmButton } from './ConfirmButton';
|
import { ConfirmButton } from './ConfirmButton';
|
||||||
import { Button } from '../Button/Button';
|
|
||||||
import { ComponentSize } from '../../types/size';
|
import { ComponentSize } from '../../types/size';
|
||||||
|
import { Button } from '../Button';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
size?: ComponentSize;
|
size?: ComponentSize;
|
||||||
|
|
@ -13,12 +13,12 @@ export const DeleteButton: FC<Props> = ({ size, disabled, onConfirm }) => {
|
||||||
return (
|
return (
|
||||||
<ConfirmButton
|
<ConfirmButton
|
||||||
confirmText="Delete"
|
confirmText="Delete"
|
||||||
confirmVariant="danger"
|
confirmVariant="destructive"
|
||||||
size={size || 'md'}
|
size={size || 'md'}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onConfirm={onConfirm}
|
onConfirm={onConfirm}
|
||||||
>
|
>
|
||||||
<Button variant="danger" icon="fa fa-remove" size={size || 'sm'} />
|
<Button variant="destructive" icon="fa fa-remove" size={size || 'sm'} />
|
||||||
</ConfirmButton>
|
</ConfirmButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, { FC, useContext } from 'react';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { Modal } from '../Modal/Modal';
|
import { Modal } from '../Modal/Modal';
|
||||||
import { IconType } from '../Icon/types';
|
import { IconType } from '../Icon/types';
|
||||||
import { Button } from '../Button/Button';
|
import { Button } from '../Button';
|
||||||
import { stylesFactory, ThemeContext } from '../../themes';
|
import { stylesFactory, ThemeContext } from '../../themes';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
import { HorizontalGroup } from '..';
|
import { HorizontalGroup } from '..';
|
||||||
|
|
@ -53,10 +53,10 @@ export const ConfirmModal: FC<Props> = ({
|
||||||
<div className={styles.modalContent}>
|
<div className={styles.modalContent}>
|
||||||
<div className={styles.modalText}>{body}</div>
|
<div className={styles.modalText}>{body}</div>
|
||||||
<HorizontalGroup justify="center">
|
<HorizontalGroup justify="center">
|
||||||
<Button variant="danger" onClick={onConfirm}>
|
<Button variant="destructive" onClick={onConfirm}>
|
||||||
{confirmText}
|
{confirmText}
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="inverse" onClick={onDismiss}>
|
<Button variant="secondary" onClick={onDismiss}>
|
||||||
{dismissText}
|
{dismissText}
|
||||||
</Button>
|
</Button>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ export const DataLinksEditor: FC<DataLinksEditorProps> = React.memo(
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(!value || (value && value.length < (maxLinks || Infinity))) && (
|
{(!value || (value && value.length < (maxLinks || Infinity))) && (
|
||||||
<Button variant="inverse" icon="fa fa-plus" onClick={() => onAdd()}>
|
<Button variant="secondary" icon="fa fa-plus" onClick={() => onAdd()}>
|
||||||
Add link
|
Add link
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { DataFrame, DataLink, VariableSuggestion } from '@grafana/data';
|
||||||
import React, { FC, useState } from 'react';
|
import React, { FC, useState } from 'react';
|
||||||
import { DataLinkEditor } from '../DataLinkEditor';
|
import { DataLinkEditor } from '../DataLinkEditor';
|
||||||
import { HorizontalGroup } from '../../Layout/Layout';
|
import { HorizontalGroup } from '../../Layout/Layout';
|
||||||
import Forms from '../../Forms';
|
import { Button } from '../../Button';
|
||||||
|
|
||||||
interface DataLinkEditorModalContentProps {
|
interface DataLinkEditorModalContentProps {
|
||||||
link: DataLink;
|
link: DataLink;
|
||||||
|
|
@ -34,17 +34,17 @@ export const DataLinkEditorModalContent: FC<DataLinkEditorModalContentProps> = (
|
||||||
onRemove={() => {}}
|
onRemove={() => {}}
|
||||||
/>
|
/>
|
||||||
<HorizontalGroup>
|
<HorizontalGroup>
|
||||||
<Forms.Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onChange(index, dirtyLink);
|
onChange(index, dirtyLink);
|
||||||
onClose();
|
onClose();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</Forms.Button>
|
</Button>
|
||||||
<Forms.Button variant="secondary" onClick={() => onClose()}>
|
<Button variant="secondary" onClick={() => onClose()}>
|
||||||
Cancel
|
Cancel
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { DataFrame, DataLink, GrafanaTheme, VariableSuggestion } from '@grafana/data';
|
import { DataFrame, DataLink, GrafanaTheme, VariableSuggestion } from '@grafana/data';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import Forms from '../../Forms';
|
import { Button } from '../../Button/Button';
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import { Modal } from '../../Modal/Modal';
|
import { Modal } from '../../Modal/Modal';
|
||||||
import { FullWidthButtonContainer } from '../../Button/FullWidthButtonContainer';
|
import { FullWidthButtonContainer } from '../../Button/FullWidthButtonContainer';
|
||||||
|
|
@ -100,9 +100,9 @@ export const DataLinksInlineEditor: React.FC<DataLinksInlineEditorProps> = ({ li
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<FullWidthButtonContainer>
|
<FullWidthButtonContainer>
|
||||||
<Forms.Button size="sm" icon="fa fa-plus" onClick={onDataLinkAdd}>
|
<Button size="sm" icon="fa fa-plus" onClick={onDataLinkAdd}>
|
||||||
Add link
|
Add link
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</FullWidthButtonContainer>
|
</FullWidthButtonContainer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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: () => {} });
|
removeButton.simulate('click', { preventDefault: () => {} });
|
||||||
expect(wrapper.find('FormField').exists()).toBeFalsy();
|
expect(wrapper.find('FormField').exists()).toBeFalsy();
|
||||||
expect(wrapper.find('SecretFormField').exists()).toBeFalsy();
|
expect(wrapper.find('SecretFormField').exists()).toBeFalsy();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import uniqueId from 'lodash/uniqueId';
|
import uniqueId from 'lodash/uniqueId';
|
||||||
import { DataSourceSettings } from '@grafana/data';
|
import { DataSourceSettings } from '@grafana/data';
|
||||||
import { Button } from '../Button/Button';
|
import { Button } from '../Button';
|
||||||
import { FormField } from '../FormField/FormField';
|
import { FormField } from '../FormField/FormField';
|
||||||
import { SecretFormField } from '../SecretFormFied/SecretFormField';
|
import { SecretFormField } from '../SecretFormFied/SecretFormField';
|
||||||
import { stylesFactory } from '../../themes';
|
import { stylesFactory } from '../../themes';
|
||||||
|
|
@ -76,7 +76,7 @@ const CustomHeaderRow: React.FC<CustomHeaderRowProps> = ({ header, onBlur, onCha
|
||||||
onChange={e => onChange({ ...header, value: e.target.value })}
|
onChange={e => onChange({ ...header, value: e.target.value })}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
/>
|
/>
|
||||||
<Button variant="transparent" size="xs" onClick={_e => onRemove(header.id)}>
|
<Button variant="destructive" size="xs" onClick={_e => onRemove(header.id)}>
|
||||||
<i className="fa fa-trash" />
|
<i className="fa fa-trash" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -202,7 +202,7 @@ export class CustomHeadersSettings extends PureComponent<Props, State> {
|
||||||
</div>
|
</div>
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<Button
|
<Button
|
||||||
variant="inverse"
|
variant="secondary"
|
||||||
size="xs"
|
size="xs"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
this.onHeaderAdd();
|
this.onHeaderAdd();
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
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 { ComponentSize } from '../../types/size';
|
|
||||||
import mdx from './Button.mdx';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: 'Forms/Button',
|
|
||||||
component: Button,
|
|
||||||
decorators: [withCenteredStory, withHorizontallyCenteredStory],
|
|
||||||
parameters: {
|
|
||||||
docs: {
|
|
||||||
page: mdx,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const variants = ['primary', 'secondary', 'destructive', 'link'];
|
|
||||||
|
|
||||||
const sizes = ['sm', 'md', 'lg'];
|
|
||||||
|
|
||||||
export const simple = () => {
|
|
||||||
const variant = select('Variant', variants, 'primary');
|
|
||||||
const size = select('Size', sizes, 'md');
|
|
||||||
const buttonText = text('text', 'Button');
|
|
||||||
const icon = getIconKnob();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Button variant={variant as ButtonVariant} size={size as ComponentSize} icon={icon && `fa fa-${icon}`}>
|
|
||||||
{buttonText}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -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<StyleDeps, 'variant'> & { 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<HTMLButtonElement>;
|
|
||||||
|
|
||||||
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(({ variant, ...otherProps }, ref) => {
|
|
||||||
const theme = useContext(ThemeContext);
|
|
||||||
const styles = getButtonStyles({
|
|
||||||
theme,
|
|
||||||
size: otherProps.size || 'md',
|
|
||||||
variant: variant || 'primary',
|
|
||||||
});
|
|
||||||
return <DefaultButton {...otherProps} variant={variant} styles={styles} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
type ButtonLinkProps = CommonProps & AnchorHTMLAttributes<HTMLAnchorElement>;
|
|
||||||
export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(({ variant, ...otherProps }, ref) => {
|
|
||||||
const theme = useContext(ThemeContext);
|
|
||||||
const styles = getButtonStyles({
|
|
||||||
theme,
|
|
||||||
size: otherProps.size || 'md',
|
|
||||||
variant: variant || 'primary',
|
|
||||||
});
|
|
||||||
return <DefaultLinkButton {...otherProps} variant={variant} styles={styles} ref={ref} />;
|
|
||||||
});
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||||
import { withStoryContainer } from '../../utils/storybook/withStoryContainer';
|
import { withStoryContainer } from '../../utils/storybook/withStoryContainer';
|
||||||
import { Field } from './Field';
|
import { Field } from './Field';
|
||||||
import { Input } from './Input/Input';
|
import { Input } from './Input/Input';
|
||||||
import { Button } from './Button';
|
import { Button } from '../Button';
|
||||||
import { Form } from './Form';
|
import { Form } from './Form';
|
||||||
import { Switch } from './Switch';
|
import { Switch } from './Switch';
|
||||||
import { Checkbox } from './Checkbox';
|
import { Checkbox } from './Checkbox';
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import { boolean, text, select, number } from '@storybook/addon-knobs';
|
import { boolean, text, select, number } from '@storybook/addon-knobs';
|
||||||
import { withCenteredStory } from '../../../utils/storybook/withCenteredStory';
|
import { withCenteredStory } from '../../../utils/storybook/withCenteredStory';
|
||||||
import { Input } from './Input';
|
import { Input } from './Input';
|
||||||
import { Button } from '../Button';
|
import { Button } from '../../Button';
|
||||||
import mdx from './Input.mdx';
|
import mdx from './Input.mdx';
|
||||||
import { getAvailableIcons, IconType } from '../../Icon/types';
|
import { getAvailableIcons, IconType } from '../../Icon/types';
|
||||||
import { KeyValue } from '@grafana/data';
|
import { KeyValue } from '@grafana/data';
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
|
|
||||||
import { Button, ButtonVariant, ButtonProps } from '../Button';
|
import { Button, ButtonVariant, ButtonProps } from '../../Button';
|
||||||
import { ComponentSize } from '../../../types/size';
|
import { ComponentSize } from '../../../types/size';
|
||||||
import { SelectCommonProps, CustomControlProps } from './types';
|
import { SelectCommonProps, CustomControlProps } from './types';
|
||||||
import { SelectBase } from './SelectBase';
|
import { SelectBase } from './SelectBase';
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { SelectableValue } from '@grafana/data';
|
||||||
import { getAvailableIcons, IconType } from '../../Icon/types';
|
import { getAvailableIcons, IconType } from '../../Icon/types';
|
||||||
import { select, boolean } from '@storybook/addon-knobs';
|
import { select, boolean } from '@storybook/addon-knobs';
|
||||||
import { Icon } from '../../Icon/Icon';
|
import { Icon } from '../../Icon/Icon';
|
||||||
import { Button } from '../Button';
|
import { Button } from '../../Button';
|
||||||
import { ButtonSelect } from './ButtonSelect';
|
import { ButtonSelect } from './ButtonSelect';
|
||||||
import { getIconKnob } from '../../../utils/storybook/knobs';
|
import { getIconKnob } from '../../../utils/storybook/knobs';
|
||||||
import kebabCase from 'lodash/kebabCase';
|
import kebabCase from 'lodash/kebabCase';
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { GrafanaTheme } from '@grafana/data';
|
||||||
import { getLabelStyles } from './Label';
|
import { getLabelStyles } from './Label';
|
||||||
import { getLegendStyles } from './Legend';
|
import { getLegendStyles } from './Legend';
|
||||||
import { getFieldValidationMessageStyles } from './FieldValidationMessage';
|
import { getFieldValidationMessageStyles } from './FieldValidationMessage';
|
||||||
import { getButtonStyles, ButtonVariant } from './Button';
|
import { getButtonStyles, ButtonVariant } from '../Button';
|
||||||
import { ComponentSize } from '../../types/size';
|
import { ComponentSize } from '../../types/size';
|
||||||
import { getInputStyles } from './Input/Input';
|
import { getInputStyles } from './Input/Input';
|
||||||
import { getSwitchStyles } from './Switch';
|
import { getSwitchStyles } from './Switch';
|
||||||
|
|
|
||||||
|
|
@ -7,21 +7,22 @@ import { RadioButtonGroup } from './RadioButtonGroup/RadioButtonGroup';
|
||||||
import { AsyncSelect, Select } from './Select/Select';
|
import { AsyncSelect, Select } from './Select/Select';
|
||||||
import { Form } from './Form';
|
import { Form } from './Form';
|
||||||
import { Field } from './Field';
|
import { Field } from './Field';
|
||||||
import { Button, LinkButton } from './Button';
|
|
||||||
import { Switch } from './Switch';
|
import { Switch } from './Switch';
|
||||||
import { TextArea } from './TextArea/TextArea';
|
import { TextArea } from './TextArea/TextArea';
|
||||||
import { Checkbox } from './Checkbox';
|
import { Checkbox } from './Checkbox';
|
||||||
|
//Will be removed after Enterprise changes have been merged
|
||||||
|
import { Button, LinkButton } from '../Button';
|
||||||
|
|
||||||
const Forms = {
|
const Forms = {
|
||||||
RadioButtonGroup,
|
RadioButtonGroup,
|
||||||
|
Button,
|
||||||
|
LinkButton,
|
||||||
Switch,
|
Switch,
|
||||||
getFormStyles,
|
getFormStyles,
|
||||||
Label,
|
Label,
|
||||||
Input,
|
Input,
|
||||||
Form,
|
Form,
|
||||||
Field,
|
Field,
|
||||||
Button,
|
|
||||||
LinkButton,
|
|
||||||
Select,
|
Select,
|
||||||
ButtonSelect,
|
ButtonSelect,
|
||||||
InputControl,
|
InputControl,
|
||||||
|
|
@ -30,5 +31,4 @@ const Forms = {
|
||||||
Checkbox,
|
Checkbox,
|
||||||
};
|
};
|
||||||
|
|
||||||
export { ButtonVariant } from './Button';
|
|
||||||
export default Forms;
|
export default Forms;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory';
|
import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||||
import { VerticalGroup, HorizontalGroup, Layout } from './Layout';
|
import { VerticalGroup, HorizontalGroup, Layout } from './Layout';
|
||||||
import { Button } from '../Forms/Button';
|
import { Button } from '../Button';
|
||||||
import { withStoryContainer } from '../../utils/storybook/withStoryContainer';
|
import { withStoryContainer } from '../../utils/storybook/withStoryContainer';
|
||||||
import { select } from '@storybook/addon-knobs';
|
import { select } from '@storybook/addon-knobs';
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ export default {
|
||||||
decorators: [withStoryContainer, withCenteredStory, withHorizontallyCenteredStory],
|
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'];
|
const spacingVariants = ['xs', 'sm', 'md', 'lg'];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<LinkButton
|
<LinkButton
|
||||||
variant={'transparent'}
|
variant="link"
|
||||||
size={'sm'}
|
size={'sm'}
|
||||||
icon={cx('fa', link.onClick ? 'fa-list' : 'fa-external-link')}
|
icon={cx('fa', link.onClick ? 'fa-list' : 'fa-external-link')}
|
||||||
href={link.href}
|
href={link.href}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { stylesFactory } from '../../themes';
|
import { stylesFactory } from '../../themes';
|
||||||
import { Button, ButtonVariant } from '../Forms/Button';
|
import { Button, ButtonVariant } from '../Button';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
currentPage: number;
|
currentPage: number;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { ChangeEvent, KeyboardEvent, PureComponent } from 'react';
|
import React, { ChangeEvent, KeyboardEvent, PureComponent } from 'react';
|
||||||
import { css, cx } from 'emotion';
|
import { css, cx } from 'emotion';
|
||||||
import { stylesFactory } from '../../themes/stylesFactory';
|
import { stylesFactory } from '../../themes/stylesFactory';
|
||||||
import { Button } from '../Button/Button';
|
import { Button } from '../Button';
|
||||||
import { Input } from '../Input/Input';
|
import { Input } from '../Input/Input';
|
||||||
import { TagItem } from './TagItem';
|
import { TagItem } from './TagItem';
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ export class TagsInput extends PureComponent<Props, State> {
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Input placeholder="Add Name" onChange={this.onNameChange} value={newTag} onKeyUp={this.onKeyboardAdd} />
|
<Input placeholder="Add Name" onChange={this.onNameChange} value={newTag} onKeyUp={this.onKeyboardAdd} />
|
||||||
<Button className={getStyles().addButtonStyle} onClick={this.onAdd} variant="secondary" size="md">
|
<Button className={getStyles().addButtonStyle} onClick={this.onAdd} variant="primary" size="md">
|
||||||
Add
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import { stylesFactory } from '../../themes';
|
||||||
import { Icon } from '../Icon/Icon';
|
import { Icon } from '../Icon/Icon';
|
||||||
import { RadioButtonGroup } from '../Forms/RadioButtonGroup/RadioButtonGroup';
|
import { RadioButtonGroup } from '../Forms/RadioButtonGroup/RadioButtonGroup';
|
||||||
import { Field } from '../Forms/Field';
|
import { Field } from '../Forms/Field';
|
||||||
import { Button } from '../Forms/Button';
|
import { Button } from '../Button';
|
||||||
import { FullWidthButtonContainer } from '../Button/FullWidthButtonContainer';
|
import { FullWidthButtonContainer } from '../Button/FullWidthButtonContainer';
|
||||||
|
|
||||||
const modes: Array<SelectableValue<ThresholdsMode>> = [
|
const modes: Array<SelectableValue<ThresholdsMode>> = [
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { GrafanaTheme, dateTime, TIME_FORMAT } from '@grafana/data';
|
||||||
import { stringToDateTimeType } from '../time';
|
import { stringToDateTimeType } from '../time';
|
||||||
import { useTheme, stylesFactory } from '../../../themes';
|
import { useTheme, stylesFactory } from '../../../themes';
|
||||||
import { TimePickerTitle } from './TimePickerTitle';
|
import { TimePickerTitle } from './TimePickerTitle';
|
||||||
import Forms from '../../Forms';
|
import { Button } from '../../Button';
|
||||||
import { Portal } from '../../Portal/Portal';
|
import { Portal } from '../../Portal/Portal';
|
||||||
import { getThemeColors } from './colors';
|
import { getThemeColors } from './colors';
|
||||||
import { ClickOutsideWrapper } from '../../ClickOutsideWrapper/ClickOutsideWrapper';
|
import { ClickOutsideWrapper } from '../../ClickOutsideWrapper/ClickOutsideWrapper';
|
||||||
|
|
@ -281,12 +281,12 @@ const Footer = memo<Props>(({ onClose, onApply }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<Forms.Button className={styles.apply} onClick={onApply}>
|
<Button className={styles.apply} onClick={onApply}>
|
||||||
Apply time range
|
Apply time range
|
||||||
</Forms.Button>
|
</Button>
|
||||||
<Forms.Button variant="secondary" onClick={onClose}>
|
<Button variant="secondary" onClick={onClose}>
|
||||||
Cancel
|
Cancel
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { stringToDateTimeType, isValidTimeString } from '../time';
|
||||||
import { mapStringsToTimeRange } from './mapper';
|
import { mapStringsToTimeRange } from './mapper';
|
||||||
import { TimePickerCalendar } from './TimePickerCalendar';
|
import { TimePickerCalendar } from './TimePickerCalendar';
|
||||||
import Forms from '../../Forms';
|
import Forms from '../../Forms';
|
||||||
|
import { Button } from '../../Button';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isFullscreen: boolean;
|
isFullscreen: boolean;
|
||||||
|
|
@ -60,7 +61,7 @@ export const TimeRangeForm: React.FC<Props> = props => {
|
||||||
[timeZone]
|
[timeZone]
|
||||||
);
|
);
|
||||||
|
|
||||||
const icon = isFullscreen ? null : <Forms.Button icon="fa fa-calendar" variant="secondary" onClick={onOpen} />;
|
const icon = isFullscreen ? null : <Button icon="fa fa-calendar" variant="secondary" onClick={onOpen} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -82,7 +83,7 @@ export const TimeRangeForm: React.FC<Props> = props => {
|
||||||
value={to.value}
|
value={to.value}
|
||||||
/>
|
/>
|
||||||
</Forms.Field>
|
</Forms.Field>
|
||||||
<Forms.Button onClick={onApply}>Apply time range</Forms.Button>
|
<Button onClick={onApply}>Apply time range</Button>
|
||||||
|
|
||||||
<TimePickerCalendar
|
<TimePickerCalendar
|
||||||
isFullscreen={isFullscreen}
|
isFullscreen={isFullscreen}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { Select } from '../Select/Select';
|
||||||
import { transformersUIRegistry } from './transformers';
|
import { transformersUIRegistry } from './transformers';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { TransformationRow } from './TransformationRow';
|
import { TransformationRow } from './TransformationRow';
|
||||||
import { Button } from '../Button/Button';
|
import { Button } from '../Button';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
|
|
||||||
interface TransformationsEditorState {
|
interface TransformationsEditorState {
|
||||||
|
|
@ -118,7 +118,7 @@ export class TransformationsEditor extends React.PureComponent<TransformationsEd
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{this.renderTransformationEditors()}
|
{this.renderTransformationEditors()}
|
||||||
<Button variant="inverse" icon="fa fa-plus" onClick={this.onTransformationAdd}>
|
<Button variant="secondary" icon="fa fa-plus" onClick={this.onTransformationAdd}>
|
||||||
Add transformation
|
Add transformation
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import LegacyMappingRow from './LegacyMappingRow';
|
import LegacyMappingRow from './LegacyMappingRow';
|
||||||
import { MappingType, ValueMapping } from '@grafana/data';
|
import { MappingType, ValueMapping } from '@grafana/data';
|
||||||
import { Button } from '../Button/Button';
|
import { Button } from '../Button';
|
||||||
import { PanelOptionsGroup } from '../PanelOptionsGroup/PanelOptionsGroup';
|
import { PanelOptionsGroup } from '../PanelOptionsGroup/PanelOptionsGroup';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
|
@ -98,7 +98,7 @@ export class LegacyValueMappingsEditor extends PureComponent<Props, State> {
|
||||||
removeValueMapping={() => this.onRemoveMapping(valueMapping.id)}
|
removeValueMapping={() => this.onRemoveMapping(valueMapping.id)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<Button variant="inverse" icon="fa fa-plus" onClick={this.onAddMapping}>
|
<Button variant="primary" icon="fa fa-plus" onClick={this.onAddMapping}>
|
||||||
Add mapping
|
Add mapping
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { MappingType, ValueMapping } from '@grafana/data';
|
import { MappingType, ValueMapping } from '@grafana/data';
|
||||||
import Forms from '../Forms';
|
import { Button } from '../Button/Button';
|
||||||
import { FullWidthButtonContainer } from '../Button/FullWidthButtonContainer';
|
import { FullWidthButtonContainer } from '../Button/FullWidthButtonContainer';
|
||||||
import { MappingRow } from './MappingRow';
|
import { MappingRow } from './MappingRow';
|
||||||
|
|
||||||
|
|
@ -66,9 +66,9 @@ export const ValueMappingsEditor: React.FC<Props> = ({ valueMappings, onChange,
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<FullWidthButtonContainer>
|
<FullWidthButtonContainer>
|
||||||
<Forms.Button size="sm" icon="fa fa-plus" onClick={onAdd} aria-label="ValueMappingsEditor add mapping button">
|
<Button size="sm" icon="fa fa-plus" onClick={onAdd} aria-label="ValueMappingsEditor add mapping button">
|
||||||
Add mapping
|
Add mapping
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</FullWidthButtonContainer>
|
</FullWidthButtonContainer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ exports[`Render should render component 1`] = `
|
||||||
<Button
|
<Button
|
||||||
icon="fa fa-plus"
|
icon="fa fa-plus"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
variant="inverse"
|
variant="primary"
|
||||||
>
|
>
|
||||||
Add mapping
|
Add mapping
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { IconType } from '../Icon/types';
|
import { IconType } from '../Icon/types';
|
||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { Button, ButtonVariant } from '../Forms/Button';
|
import { Button, ButtonVariant } from '../Button';
|
||||||
import { Select } from '../Forms/Select/Select';
|
import { Select } from '../Forms/Select/Select';
|
||||||
import { FullWidthButtonContainer } from '../Button/FullWidthButtonContainer';
|
import { FullWidthButtonContainer } from '../Button/FullWidthButtonContainer';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ export { Popover } from './Tooltip/Popover';
|
||||||
export { Portal } from './Portal/Portal';
|
export { Portal } from './Portal/Portal';
|
||||||
export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar';
|
export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar';
|
||||||
|
|
||||||
export * from './Button/Button';
|
|
||||||
export { ClipboardButton } from './ClipboardButton/ClipboardButton';
|
export { ClipboardButton } from './ClipboardButton/ClipboardButton';
|
||||||
|
|
||||||
// Select
|
// Select
|
||||||
|
|
@ -99,7 +98,7 @@ export { LogLabels } from './Logs/LogLabels';
|
||||||
export { LogRows } from './Logs/LogRows';
|
export { LogRows } from './Logs/LogRows';
|
||||||
export { getLogRowStyles } from './Logs/getLogRowStyles';
|
export { getLogRowStyles } from './Logs/getLogRowStyles';
|
||||||
export { ToggleButtonGroup, ToggleButton } from './ToggleButtonGroup/ToggleButtonGroup';
|
export { ToggleButtonGroup, ToggleButton } from './ToggleButtonGroup/ToggleButtonGroup';
|
||||||
// Panel editors
|
// Panel editors./Forms/Legacy/Button/FullWidthButtonContainer
|
||||||
export { FullWidthButtonContainer } from './Button/FullWidthButtonContainer';
|
export { FullWidthButtonContainer } from './Button/FullWidthButtonContainer';
|
||||||
export { ThresholdsEditor } from './ThresholdsEditor/ThresholdsEditor';
|
export { ThresholdsEditor } from './ThresholdsEditor/ThresholdsEditor';
|
||||||
export { ClickOutsideWrapper } from './ClickOutsideWrapper/ClickOutsideWrapper';
|
export { ClickOutsideWrapper } from './ClickOutsideWrapper/ClickOutsideWrapper';
|
||||||
|
|
@ -151,7 +150,8 @@ export {
|
||||||
export { FieldConfigItemHeaderTitle } from './FieldConfigs/FieldConfigItemHeaderTitle';
|
export { FieldConfigItemHeaderTitle } from './FieldConfigs/FieldConfigItemHeaderTitle';
|
||||||
|
|
||||||
// Next-gen forms
|
// 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 { ValuePicker } from './ValuePicker/ValuePicker';
|
||||||
export { fieldMatchersUI } from './MatchersUI/fieldMatchersUI';
|
export { fieldMatchersUI } from './MatchersUI/fieldMatchersUI';
|
||||||
export { getStandardFieldConfigs } from './FieldConfigs/standardFieldConfigEditors';
|
export { getStandardFieldConfigs } from './FieldConfigs/standardFieldConfigEditors';
|
||||||
|
|
|
||||||
|
|
@ -168,11 +168,11 @@ $table-bg-hover: $dark-6;
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
// -------------------------
|
// -------------------------
|
||||||
$btn-secondary-bg: $blue-base;
|
$btn-primary-bg: $blue-base;
|
||||||
$btn-secondary-bg-hl: $blue-shade;
|
$btn-primary-bg-hl: $blue-shade;
|
||||||
|
|
||||||
$btn-primary-bg: $green-base;
|
$btn-secondary-bg: $dark-6;
|
||||||
$btn-primary-bg-hl: $green-shade;
|
$btn-secondary-bg-hl: lighten($dark-6, 4%);
|
||||||
|
|
||||||
$btn-success-bg: $green-base;
|
$btn-success-bg: $green-base;
|
||||||
$btn-success-bg-hl: $green-shade;
|
$btn-success-bg-hl: $green-shade;
|
||||||
|
|
|
||||||
|
|
@ -160,11 +160,11 @@ $table-bg-hover: $gray-5;
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
// -------------------------
|
// -------------------------
|
||||||
$btn-primary-bg: $green-base;
|
$btn-secondary-bg: $gray-5;
|
||||||
$btn-primary-bg-hl: $green-shade;
|
$btn-secondary-bg-hl: $gray-4;
|
||||||
|
|
||||||
$btn-secondary-bg: $blue-base;
|
$btn-primary-bg: $blue-base;
|
||||||
$btn-secondary-bg-hl: $blue-shade;
|
$btn-primary-bg-hl: $blue-shade;
|
||||||
|
|
||||||
$btn-success-bg: $green-base;
|
$btn-success-bg: $green-base;
|
||||||
$btn-success-bg-hl: $green-shade;
|
$btn-success-bg-hl: $green-shade;
|
||||||
|
|
@ -173,7 +173,6 @@ $btn-danger-bg: $red-base;
|
||||||
$btn-danger-bg-hl: $red-shade;
|
$btn-danger-bg-hl: $red-shade;
|
||||||
|
|
||||||
$btn-inverse-bg: $gray-5;
|
$btn-inverse-bg: $gray-5;
|
||||||
$btn-inverse-bg-hl: darken($gray-5, 5%);
|
|
||||||
$btn-inverse-bg-hl: $gray-4;
|
$btn-inverse-bg-hl: $gray-4;
|
||||||
$btn-inverse-text-color: $gray-1;
|
$btn-inverse-text-color: $gray-1;
|
||||||
$btn-inverse-text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
|
$btn-inverse-text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,6 @@ export function registerAngularDirectives() {
|
||||||
]);
|
]);
|
||||||
react2AngularDirective('saveDashboardAsButton', SaveDashboardAsButtonConnected, [
|
react2AngularDirective('saveDashboardAsButton', SaveDashboardAsButtonConnected, [
|
||||||
'variant',
|
'variant',
|
||||||
'useNewForms',
|
|
||||||
['getDashboard', { watchDepth: 'reference', wrapApply: true }],
|
['getDashboard', { watchDepth: 'reference', wrapApply: true }],
|
||||||
['onSaveSuccess', { watchDepth: 'reference', wrapApply: true }],
|
['onSaveSuccess', { watchDepth: 'reference', wrapApply: true }],
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ export class OrgSwitcher extends React.PureComponent<Props, State> {
|
||||||
{org.orgId === currentOrgId ? (
|
{org.orgId === currentOrgId ? (
|
||||||
<Button size="sm">Current</Button>
|
<Button size="sm">Current</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button variant="inverse" size="sm" onClick={() => this.setCurrentOrg(org)}>
|
<Button variant="secondary" size="sm" onClick={() => this.setCurrentOrg(org)}>
|
||||||
Switch to
|
Switch to
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { css } from 'emotion';
|
||||||
import { NavModel } from '@grafana/data';
|
import { NavModel } from '@grafana/data';
|
||||||
import Page from '../../core/components/Page/Page';
|
import Page from '../../core/components/Page/Page';
|
||||||
import { LicenseChrome } from './LicenseChrome';
|
import { LicenseChrome } from './LicenseChrome';
|
||||||
import { Forms } from '@grafana/ui';
|
import { LinkButton } from '@grafana/ui';
|
||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
import { StoreState } from '../../types';
|
import { StoreState } from '../../types';
|
||||||
import { getNavModel } from '../../core/selectors/navModel';
|
import { getNavModel } from '../../core/selectors/navModel';
|
||||||
|
|
@ -69,13 +69,13 @@ const GetEnterprise: React.FC = () => {
|
||||||
|
|
||||||
const CallToAction: React.FC = () => {
|
const CallToAction: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<Forms.LinkButton
|
<LinkButton
|
||||||
variant="primary"
|
variant="primary"
|
||||||
size="lg"
|
size="lg"
|
||||||
href="https://grafana.com/contact?about=grafana-enterprise&utm_source=grafana-upgrade-page"
|
href="https://grafana.com/contact?about=grafana-enterprise&utm_source=grafana-upgrade-page"
|
||||||
>
|
>
|
||||||
Contact us and get a free trial
|
Contact us and get a free trial
|
||||||
</Forms.LinkButton>
|
</LinkButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Forms } from '@grafana/ui';
|
import { Forms, Button } from '@grafana/ui';
|
||||||
import { NavModel } from '@grafana/data';
|
import { NavModel } from '@grafana/data';
|
||||||
import { getBackendSrv } from '@grafana/runtime';
|
import { getBackendSrv } from '@grafana/runtime';
|
||||||
import { StoreState } from '../../types';
|
import { StoreState } from '../../types';
|
||||||
|
|
@ -62,7 +62,7 @@ const UserCreatePage: React.FC<UserCreatePageProps> = ({ navModel, updateLocatio
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Forms.Field>
|
</Forms.Field>
|
||||||
<Forms.Button type="submit">Create user</Forms.Button>
|
<Button type="submit">Create user</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ export class UserLdapSyncInfo extends PureComponent<Props, State> {
|
||||||
<Button variant="secondary" onClick={this.onUserSync}>
|
<Button variant="secondary" onClick={this.onUserSync}>
|
||||||
Sync user
|
Sync user
|
||||||
</Button>
|
</Button>
|
||||||
<LinkButton variant="inverse" href={debugLDAPMappingURL}>
|
<LinkButton variant="secondary" href={debugLDAPMappingURL}>
|
||||||
Debug LDAP Mapping
|
Debug LDAP Mapping
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { css, cx } from 'emotion';
|
||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
||||||
import { NavModel } from '@grafana/data';
|
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 { StoreState, UserDTO } from '../../types';
|
||||||
import Page from 'app/core/components/Page/Page';
|
import Page from 'app/core/components/Page/Page';
|
||||||
import { getNavModel } from '../../core/selectors/navModel';
|
import { getNavModel } from '../../core/selectors/navModel';
|
||||||
|
|
@ -53,9 +53,9 @@ const UserListAdminPageUnConnected: React.FC<Props> = props => {
|
||||||
onChange={event => props.changeQuery(event.currentTarget.value)}
|
onChange={event => props.changeQuery(event.currentTarget.value)}
|
||||||
prefix={<i className="fa fa-search" />}
|
prefix={<i className="fa fa-search" />}
|
||||||
/>
|
/>
|
||||||
<Forms.LinkButton href="admin/users/create" variant="primary">
|
<LinkButton href="admin/users/create" variant="primary">
|
||||||
New user
|
New user
|
||||||
</Forms.LinkButton>
|
</LinkButton>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { css, cx } from 'emotion';
|
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 { GrafanaTheme } from '@grafana/data';
|
||||||
import { UserOrg, Organization } from 'app/types';
|
import { UserOrg, Organization } from 'app/types';
|
||||||
import { OrgPicker, OrgSelectItem } from 'app/core/components/Select/OrgPicker';
|
import { OrgPicker, OrgSelectItem } from 'app/core/components/Select/OrgPicker';
|
||||||
|
|
@ -52,9 +52,9 @@ export class UserOrgs extends PureComponent<Props, State> {
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div className={addToOrgContainerClass}>
|
<div className={addToOrgContainerClass}>
|
||||||
<Forms.Button variant="secondary" onClick={this.showOrgAddModal(true)}>
|
<Button variant="secondary" onClick={this.showOrgAddModal(true)}>
|
||||||
Add user to organization
|
Add user to organization
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<AddToOrgModal isOpen={showAddOrgModal} onOrgAdd={onOrgAdd} onDismiss={this.showOrgAddModal(false)} />
|
<AddToOrgModal isOpen={showAddOrgModal} onOrgAdd={onOrgAdd} onDismiss={this.showOrgAddModal(false)} />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -169,7 +169,7 @@ class UnThemedOrgRow extends PureComponent<OrgRowProps, OrgRowState> {
|
||||||
<div className="pull-right">
|
<div className="pull-right">
|
||||||
<ConfirmButton
|
<ConfirmButton
|
||||||
confirmText="Confirm removal"
|
confirmText="Confirm removal"
|
||||||
confirmVariant="danger"
|
confirmVariant="destructive"
|
||||||
onClick={this.onOrgRemoveClick}
|
onClick={this.onOrgRemoveClick}
|
||||||
onCancel={this.onCancelClick}
|
onCancel={this.onCancelClick}
|
||||||
onConfirm={this.onOrgRemove}
|
onConfirm={this.onOrgRemove}
|
||||||
|
|
@ -258,12 +258,12 @@ export class AddToOrgModal extends PureComponent<AddToOrgModalProps, AddToOrgMod
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={buttonRowClass}>
|
<div className={buttonRowClass}>
|
||||||
<Forms.Button variant="primary" onClick={this.onAddUserToOrg}>
|
<Button variant="primary" onClick={this.onAddUserToOrg}>
|
||||||
Add to organization
|
Add to organization
|
||||||
</Forms.Button>
|
</Button>
|
||||||
<Forms.Button variant="secondary" onClick={this.onCancel}>
|
<Button variant="secondary" onClick={this.onCancel}>
|
||||||
Cancel
|
Cancel
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { UserDTO } from 'app/types';
|
||||||
import { cx, css } from 'emotion';
|
import { cx, css } from 'emotion';
|
||||||
import { config } from 'app/core/config';
|
import { config } from 'app/core/config';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
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 {
|
interface Props {
|
||||||
user: UserDTO;
|
user: UserDTO;
|
||||||
|
|
@ -125,9 +125,9 @@ export class UserProfile extends PureComponent<Props, State> {
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.buttonRow}>
|
<div className={styles.buttonRow}>
|
||||||
<Forms.Button variant="destructive" onClick={this.showDeleteUserModal(true)}>
|
<Button variant="destructive" onClick={this.showDeleteUserModal(true)}>
|
||||||
Delete User
|
Delete User
|
||||||
</Forms.Button>
|
</Button>
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
isOpen={showDeleteModal}
|
isOpen={showDeleteModal}
|
||||||
title="Delete user"
|
title="Delete user"
|
||||||
|
|
@ -137,13 +137,13 @@ export class UserProfile extends PureComponent<Props, State> {
|
||||||
onDismiss={this.showDeleteUserModal(false)}
|
onDismiss={this.showDeleteUserModal(false)}
|
||||||
/>
|
/>
|
||||||
{user.isDisabled ? (
|
{user.isDisabled ? (
|
||||||
<Forms.Button variant="secondary" onClick={this.onUserEnable}>
|
<Button variant="secondary" onClick={this.onUserEnable}>
|
||||||
Enable User
|
Enable User
|
||||||
</Forms.Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Forms.Button variant="secondary" onClick={this.showDisableUserModal(true)}>
|
<Button variant="secondary" onClick={this.showDisableUserModal(true)}>
|
||||||
Disable User
|
Disable User
|
||||||
</Forms.Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
isOpen={showDisableModal}
|
isOpen={showDisableModal}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { ConfirmButton, ConfirmModal, Forms } from '@grafana/ui';
|
import { ConfirmButton, ConfirmModal, Button } from '@grafana/ui';
|
||||||
import { UserSession } from 'app/types';
|
import { UserSession } from 'app/types';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -68,7 +68,7 @@ export class UserSessions extends PureComponent<Props, State> {
|
||||||
<div className="pull-right">
|
<div className="pull-right">
|
||||||
<ConfirmButton
|
<ConfirmButton
|
||||||
confirmText="Confirm logout"
|
confirmText="Confirm logout"
|
||||||
confirmVariant="danger"
|
confirmVariant="destructive"
|
||||||
onConfirm={this.onSessionRevoke(session.id)}
|
onConfirm={this.onSessionRevoke(session.id)}
|
||||||
>
|
>
|
||||||
Force logout
|
Force logout
|
||||||
|
|
@ -82,9 +82,9 @@ export class UserSessions extends PureComponent<Props, State> {
|
||||||
</div>
|
</div>
|
||||||
<div className={logoutFromAllDevicesClass}>
|
<div className={logoutFromAllDevicesClass}>
|
||||||
{sessions.length > 0 && (
|
{sessions.length > 0 && (
|
||||||
<Forms.Button variant="secondary" onClick={this.showLogoutConfirmationModal(true)}>
|
<Button variant="secondary" onClick={this.showLogoutConfirmationModal(true)}>
|
||||||
Force logout from all devices
|
Force logout from all devices
|
||||||
</Forms.Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
isOpen={showLogoutModal}
|
isOpen={showLogoutModal}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
<save-dashboard-button getDashboard="ctrl.getDashboard" aria-label="Dashboard settings aside actions Save button" />
|
<save-dashboard-button getDashboard="ctrl.getDashboard" aria-label="Dashboard settings aside actions Save button" />
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="ctrl.canSaveAs">
|
<div ng-show="ctrl.canSaveAs">
|
||||||
<save-dashboard-as-button getDashboard="ctrl.getDashboard" aria-label="Dashboard settings aside actions Save as button" variant="'secondary'" useNewForms="true"/>
|
<save-dashboard-as-button getDashboard="ctrl.getDashboard" aria-label="Dashboard settings aside actions Save as button" variant="'secondary'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { css } from 'emotion';
|
||||||
import { InspectHeader } from './InspectHeader';
|
import { InspectHeader } from './InspectHeader';
|
||||||
|
|
||||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
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 { getLocationSrv, getDataSourceSrv } from '@grafana/runtime';
|
||||||
import {
|
import {
|
||||||
DataFrame,
|
DataFrame,
|
||||||
|
|
@ -189,9 +189,9 @@ export class PanelInspector extends PureComponent<Props, State> {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={styles.downloadCsv}>
|
<div className={styles.downloadCsv}>
|
||||||
<Forms.Button variant="primary" onClick={() => this.exportCsv(processed[selected])}>
|
<Button variant="primary" onClick={() => this.exportCsv(processed[selected])}>
|
||||||
Download CSV
|
Download CSV
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flexGrow: 1 }}>
|
<div style={{ flexGrow: 1 }}>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { FieldConfigSource, GrafanaTheme, PanelData, PanelPlugin, SelectableValue } from '@grafana/data';
|
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 { css, cx } from 'emotion';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
|
|
@ -198,9 +198,9 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.toolbarLeft}>
|
<div className={styles.toolbarLeft}>
|
||||||
<div className={styles.toolbarItem}>
|
<div className={styles.toolbarItem}>
|
||||||
<Forms.Button className={styles.toolbarItem} variant="secondary" onClick={this.onDiscard}>
|
<Button className={styles.toolbarItem} variant="secondary" onClick={this.onDiscard}>
|
||||||
Discard changes
|
Discard changes
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.toolbarItem}>
|
<div className={styles.toolbarItem}>
|
||||||
<Forms.Select
|
<Forms.Select
|
||||||
|
|
@ -213,7 +213,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
||||||
<DashNavTimeControls dashboard={dashboard} location={location} updateLocation={updateLocation} />
|
<DashNavTimeControls dashboard={dashboard} location={location} updateLocation={updateLocation} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.toolbarItem}>
|
<div className={styles.toolbarItem}>
|
||||||
<Forms.Button
|
<Button
|
||||||
className={styles.toolbarItem}
|
className={styles.toolbarItem}
|
||||||
icon="fa fa-sliders"
|
icon="fa fa-sliders"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { css } from 'emotion';
|
import { Button, ButtonVariant, ModalsController, FullWidthButtonContainer } from '@grafana/ui';
|
||||||
import { Button, Forms, ModalsController } from '@grafana/ui';
|
|
||||||
import { DashboardModel } from 'app/features/dashboard/state';
|
import { DashboardModel } from 'app/features/dashboard/state';
|
||||||
import { connectWithProvider } from 'app/core/utils/connectWithReduxStore';
|
import { connectWithProvider } from 'app/core/utils/connectWithReduxStore';
|
||||||
import { provideModalsContext } from 'app/routes/ReactContainer';
|
import { provideModalsContext } from 'app/routes/ReactContainer';
|
||||||
|
|
@ -24,12 +23,11 @@ export const SaveDashboardButton: React.FC<SaveDashboardButtonProps> = ({
|
||||||
getDashboard,
|
getDashboard,
|
||||||
useNewForms,
|
useNewForms,
|
||||||
}) => {
|
}) => {
|
||||||
const ButtonComponent = useNewForms ? Forms.Button : Button;
|
|
||||||
return (
|
return (
|
||||||
<ModalsController>
|
<ModalsController>
|
||||||
{({ showModal, hideModal }) => {
|
{({ showModal, hideModal }) => {
|
||||||
return (
|
return (
|
||||||
<ButtonComponent
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
showModal(SaveDashboardModalProxy, {
|
showModal(SaveDashboardModalProxy, {
|
||||||
// TODO[angular-migrations]: Remove tenary op when we migrate Dashboard Settings view to React
|
// TODO[angular-migrations]: Remove tenary op when we migrate Dashboard Settings view to React
|
||||||
|
|
@ -40,46 +38,41 @@ export const SaveDashboardButton: React.FC<SaveDashboardButtonProps> = ({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Save dashboard
|
Save dashboard
|
||||||
</ButtonComponent>
|
</Button>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</ModalsController>
|
</ModalsController>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SaveDashboardAsButton: React.FC<SaveDashboardButtonProps & { variant?: string }> = ({
|
export const SaveDashboardAsButton: React.FC<SaveDashboardButtonProps & { variant?: ButtonVariant }> = ({
|
||||||
dashboard,
|
dashboard,
|
||||||
onSaveSuccess,
|
onSaveSuccess,
|
||||||
getDashboard,
|
getDashboard,
|
||||||
useNewForms,
|
|
||||||
variant,
|
variant,
|
||||||
}) => {
|
}) => {
|
||||||
const ButtonComponent = useNewForms ? Forms.Button : Button;
|
|
||||||
return (
|
return (
|
||||||
<ModalsController>
|
<ModalsController>
|
||||||
{({ showModal, hideModal }) => {
|
{({ showModal, hideModal }) => {
|
||||||
return (
|
return (
|
||||||
<ButtonComponent
|
<FullWidthButtonContainer>
|
||||||
/* Styles applied here are specific to dashboard settings view */
|
<Button
|
||||||
className={css`
|
onClick={() => {
|
||||||
width: 100%;
|
showModal(SaveDashboardAsModal, {
|
||||||
justify-content: center;
|
// TODO[angular-migrations]: Remove tenary op when we migrate Dashboard Settings view to React
|
||||||
`}
|
dashboard: getDashboard ? getDashboard() : dashboard,
|
||||||
onClick={() => {
|
onSaveSuccess,
|
||||||
showModal(SaveDashboardAsModal, {
|
onDismiss: hideModal,
|
||||||
// TODO[angular-migrations]: Remove tenary op when we migrate Dashboard Settings view to React
|
});
|
||||||
dashboard: getDashboard ? getDashboard() : dashboard,
|
}}
|
||||||
onSaveSuccess,
|
// TODO[angular-migrations]: Hacking the different variants for this single button
|
||||||
onDismiss: hideModal,
|
// 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 ButtonVariant}
|
||||||
// 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
|
Save As...
|
||||||
// Everywhere else we use old button component :(
|
</Button>
|
||||||
variant={variant as any}
|
</FullWidthButtonContainer>
|
||||||
>
|
|
||||||
Save As...
|
|
||||||
</ButtonComponent>
|
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</ModalsController>
|
</ModalsController>
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ const ConfirmPluginDashboardSaveModal: React.FC<SaveDashboardModalProps> = ({ on
|
||||||
<HorizontalGroup justify="center">
|
<HorizontalGroup justify="center">
|
||||||
<SaveDashboardAsButton dashboard={dashboard} onSaveSuccess={onDismiss} />
|
<SaveDashboardAsButton dashboard={dashboard} onSaveSuccess={onDismiss} />
|
||||||
<Button
|
<Button
|
||||||
variant="danger"
|
variant="destructive"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await onDashboardSave(dashboard.getSaveModelClone(), { overwrite: true }, dashboard);
|
await onDashboardSave(dashboard.getSaveModelClone(), { overwrite: true }, dashboard);
|
||||||
onDismiss();
|
onDismiss();
|
||||||
|
|
@ -97,7 +97,7 @@ const ConfirmPluginDashboardSaveModal: React.FC<SaveDashboardModalProps> = ({ on
|
||||||
>
|
>
|
||||||
Overwrite
|
Overwrite
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="inverse" onClick={onDismiss}>
|
<Button variant="secondary" onClick={onDismiss}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
|
|
|
||||||
|
|
@ -101,9 +101,9 @@ export const SaveDashboardAsForm: React.FC<SaveDashboardFormProps & { isNew?: bo
|
||||||
<Button type="submit" aria-label="Save dashboard button">
|
<Button type="submit" aria-label="Save dashboard button">
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
<Forms.Button variant="secondary" onClick={onCancel}>
|
<Button variant="secondary" onClick={onCancel}>
|
||||||
Cancel
|
Cancel
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,9 @@ export const SaveDashboardForm: React.FC<SaveDashboardFormProps> = ({ dashboard,
|
||||||
<Button type="submit" aria-label={e2e.pages.SaveDashboardModal.selectors.save}>
|
<Button type="submit" aria-label={e2e.pages.SaveDashboardModal.selectors.save}>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
<Forms.Button variant="secondary" onClick={onCancel}>
|
<Button variant="secondary" onClick={onCancel}>
|
||||||
Cancel
|
Cancel
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { saveAs } from 'file-saver';
|
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 { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard';
|
||||||
import { SaveDashboardFormProps } from '../types';
|
import { SaveDashboardFormProps } from '../types';
|
||||||
|
|
||||||
|
|
@ -61,9 +61,9 @@ export const SaveProvisionedDashboardForm: React.FC<SaveDashboardFormProps> = ({
|
||||||
Copy JSON to clipboard
|
Copy JSON to clipboard
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
<Button onClick={saveToFile}>Save JSON to file</Button>
|
<Button onClick={saveToFile}>Save JSON to file</Button>
|
||||||
<Forms.Button variant="secondary" onClick={onCancel}>
|
<Button variant="secondary" onClick={onCancel}>
|
||||||
Cancel
|
Cancel
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
</VerticalGroup>
|
</VerticalGroup>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ export class ShareExport extends PureComponent<Props, State> {
|
||||||
<Button variant="secondary" onClick={this.onViewJson}>
|
<Button variant="secondary" onClick={this.onViewJson}>
|
||||||
View JSON
|
View JSON
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="inverse" onClick={onDismiss}>
|
<Button variant="secondary" onClick={onDismiss}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ export class ShareLink extends PureComponent<Props, State> {
|
||||||
<input type="text" className="gf-form-input" defaultValue={shareUrl} />
|
<input type="text" className="gf-form-input" defaultValue={shareUrl} />
|
||||||
</div>
|
</div>
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<ClipboardButton variant="inverse" getText={this.getShareUrl} onClipboardCopy={this.onShareUrlCopy}>
|
<ClipboardButton variant="primary" getText={this.getShareUrl} onClipboardCopy={this.onShareUrlCopy}>
|
||||||
Copy
|
Copy
|
||||||
</ClipboardButton>
|
</ClipboardButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ export class ShareSnapshot extends PureComponent<Props, State> {
|
||||||
{sharingButtonText}
|
{sharingButtonText}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<Button variant="inverse" onClick={onDismiss}>
|
<Button variant="secondary" onClick={onDismiss}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -268,7 +268,7 @@ export class ShareSnapshot extends PureComponent<Props, State> {
|
||||||
<i className="fa fa-external-link-square"></i> {snapshotUrl}
|
<i className="fa fa-external-link-square"></i> {snapshotUrl}
|
||||||
</a>
|
</a>
|
||||||
<br />
|
<br />
|
||||||
<ClipboardButton variant="inverse" getText={this.getSnapshotUrl} onClipboardCopy={this.onSnapshotUrlCopy}>
|
<ClipboardButton variant="secondary" getText={this.getSnapshotUrl} onClipboardCopy={this.onSnapshotUrlCopy}>
|
||||||
Copy Link
|
Copy Link
|
||||||
</ClipboardButton>
|
</ClipboardButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
import { css, cx } from 'emotion';
|
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 { GrafanaTheme, AppEvents, DataSourceApi } from '@grafana/data';
|
||||||
import { RichHistoryQuery, ExploreId } from 'app/types/explore';
|
import { RichHistoryQuery, ExploreId } from 'app/types/explore';
|
||||||
import { copyStringToClipboard, createUrlFromRichHistory, createDataQuery } from 'app/core/utils/richHistory';
|
import { copyStringToClipboard, createUrlFromRichHistory, createDataQuery } from 'app/core/utils/richHistory';
|
||||||
|
|
@ -202,10 +202,10 @@ export function RichHistoryCard(props: Props) {
|
||||||
className={styles.textArea}
|
className={styles.textArea}
|
||||||
/>
|
/>
|
||||||
<div className={styles.commentButtonRow}>
|
<div className={styles.commentButtonRow}>
|
||||||
<Forms.Button onClick={onUpdateComment}>Save comment</Forms.Button>
|
<Button onClick={onUpdateComment}>Save comment</Button>
|
||||||
<Forms.Button variant="secondary" onClick={onCancelUpdateComment}>
|
<Button variant="secondary" onClick={onCancelUpdateComment}>
|
||||||
Cancel
|
Cancel
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -257,9 +257,9 @@ export function RichHistoryCard(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
{!activeUpdateComment && (
|
{!activeUpdateComment && (
|
||||||
<div className={styles.runButton}>
|
<div className={styles.runButton}>
|
||||||
<Forms.Button variant="secondary" onClick={onRunQuery} disabled={isRemoved}>
|
<Button variant="secondary" onClick={onRunQuery} disabled={isRemoved}>
|
||||||
{datasourceInstance?.name === query.datasourceName ? 'Run query' : 'Switch data source and run query'}
|
{datasourceInstance?.name === query.datasourceName ? 'Run query' : 'Switch data source and run query'}
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { css } from 'emotion';
|
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 { GrafanaTheme, AppEvents } from '@grafana/data';
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
import { CoreEvents } from 'app/types';
|
import { CoreEvents } from 'app/types';
|
||||||
|
|
@ -112,9 +112,9 @@ export function RichHistorySettings(props: RichHistorySettingsProps) {
|
||||||
>
|
>
|
||||||
Delete all of your query history, permanently.
|
Delete all of your query history, permanently.
|
||||||
</div>
|
</div>
|
||||||
<Forms.Button variant="destructive" onClick={onDelete}>
|
<Button variant="destructive" onClick={onDelete}>
|
||||||
Clear query history
|
Clear query history
|
||||||
</Forms.Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ export function RunButton(props: Props) {
|
||||||
title={loading ? 'Cancel' : 'Run Query'}
|
title={loading ? 'Cancel' : 'Run Query'}
|
||||||
onClick={() => onRun(loading)}
|
onClick={() => onRun(loading)}
|
||||||
buttonClassName={classNames({
|
buttonClassName={classNames({
|
||||||
'navbar-button--secondary': !loading,
|
'navbar-button--primary': !loading,
|
||||||
'navbar-button--danger': loading,
|
'navbar-button--danger': loading,
|
||||||
'btn--radius-right-0': showDropdown,
|
'btn--radius-right-0': showDropdown,
|
||||||
})}
|
})}
|
||||||
|
|
@ -49,7 +49,7 @@ export function RunButton(props: Props) {
|
||||||
<RefreshPicker
|
<RefreshPicker
|
||||||
onIntervalChanged={onChangeRefreshInterval}
|
onIntervalChanged={onChangeRefreshInterval}
|
||||||
value={refreshInterval}
|
value={refreshInterval}
|
||||||
buttonSelectClassName={`${loading ? 'navbar-button--danger' : 'navbar-button--secondary'} ${
|
buttonSelectClassName={`${loading ? 'navbar-button--danger' : 'navbar-button--primary'} ${
|
||||||
styles.selectButtonOverride
|
styles.selectButtonOverride
|
||||||
}`}
|
}`}
|
||||||
refreshButton={runButton}
|
refreshButton={runButton}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
||||||
import { NavModel } from '@grafana/data';
|
import { NavModel } from '@grafana/data';
|
||||||
import { Forms } from '@grafana/ui';
|
import { Forms, Button } from '@grafana/ui';
|
||||||
import Page from 'app/core/components/Page/Page';
|
import Page from 'app/core/components/Page/Page';
|
||||||
import { createNewFolder } from '../state/actions';
|
import { createNewFolder } from '../state/actions';
|
||||||
import { getNavModel } from 'app/core/selectors/navModel';
|
import { getNavModel } from 'app/core/selectors/navModel';
|
||||||
|
|
@ -63,7 +63,7 @@ export class NewDashboardsFolder extends PureComponent<Props> {
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Forms.Field>
|
</Forms.Field>
|
||||||
<Forms.Button type="submit">Create</Forms.Button>
|
<Button type="submit">Create</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Forms.Form>
|
</Forms.Form>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { getBackendSrv } from '@grafana/runtime';
|
import { getBackendSrv } from '@grafana/runtime';
|
||||||
import Page from 'app/core/components/Page/Page';
|
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 { getConfig } from 'app/core/config';
|
||||||
import { StoreState } from 'app/types';
|
import { StoreState } from 'app/types';
|
||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
|
|
@ -68,7 +68,7 @@ export const NewOrgPage: FC<PropsWithState> = ({ navModel }) => {
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Forms.Field>
|
</Forms.Field>
|
||||||
<Forms.Button type="submit">Create</Forms.Button>
|
<Button type="submit">Create</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { FC } from 'react';
|
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 { getConfig } from 'app/core/config';
|
||||||
import { OrgRole } from 'app/types';
|
import { OrgRole } from 'app/types';
|
||||||
import { getBackendSrv } from '@grafana/runtime';
|
import { getBackendSrv } from '@grafana/runtime';
|
||||||
|
|
@ -71,10 +71,10 @@ export const UserInviteForm: FC<Props> = ({ updateLocation }) => {
|
||||||
<Forms.Switch name="sendEmail" ref={register} />
|
<Forms.Switch name="sendEmail" ref={register} />
|
||||||
</Forms.Field>
|
</Forms.Field>
|
||||||
<HorizontalGroup>
|
<HorizontalGroup>
|
||||||
<Forms.Button type="submit">Submit</Forms.Button>
|
<Button type="submit">Submit</Button>
|
||||||
<Forms.LinkButton href={assureBaseUrl(getConfig().appSubUrl + '/org/users')} variant="secondary">
|
<LinkButton href={assureBaseUrl(getConfig().appSubUrl + '/org/users')} variant="secondary">
|
||||||
Back
|
Back
|
||||||
</Forms.LinkButton>
|
</LinkButton>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ export class AppConfigCtrlWrapper extends PureComponent<Props, State> {
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{model.enabled && (
|
{model.enabled && (
|
||||||
<Button variant="danger" onClick={this.disable} className={withRightMargin}>
|
<Button variant="destructive" onClick={this.disable} className={withRightMargin}>
|
||||||
Disable
|
Disable
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ export class ChangePasswordForm extends PureComponent<Props, State> {
|
||||||
<Button variant="primary" onClick={this.onSubmitChangePassword} disabled={isSaving}>
|
<Button variant="primary" onClick={this.onSubmitChangePassword} disabled={isSaving}>
|
||||||
Change Password
|
Change Password
|
||||||
</Button>
|
</Button>
|
||||||
<LinkButton variant="transparent" href={`${config.appSubUrl}/profile`}>
|
<LinkButton variant="secondary" href={`${config.appSubUrl}/profile`}>
|
||||||
Cancel
|
Cancel
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { Forms } from '@grafana/ui';
|
import { Forms, Button, LinkButton } from '@grafana/ui';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
|
|
||||||
import { getConfig } from 'app/core/config';
|
import { getConfig } from 'app/core/config';
|
||||||
|
|
@ -106,11 +106,11 @@ export const SignupForm: FC<Props> = props => {
|
||||||
/>
|
/>
|
||||||
</Forms.Field>
|
</Forms.Field>
|
||||||
|
|
||||||
<Forms.Button type="submit">Submit</Forms.Button>
|
<Button type="submit">Submit</Button>
|
||||||
<span className={buttonSpacing}>
|
<span className={buttonSpacing}>
|
||||||
<Forms.LinkButton href={getConfig().appSubUrl + '/login'} variant="secondary">
|
<LinkButton href={getConfig().appSubUrl + '/login'} variant="secondary">
|
||||||
Back
|
Back
|
||||||
</Forms.LinkButton>
|
</LinkButton>
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ export class UserOrganizations extends PureComponent<Props> {
|
||||||
<span className="btn btn-primary btn-small">Current</span>
|
<span className="btn btn-primary btn-small">Current</span>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
variant="inverse"
|
variant="secondary"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.props.setUserOrg(org);
|
this.props.setUserOrg(org);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { connect, MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||||
import { StoreState } from 'app/types';
|
import { StoreState } from 'app/types';
|
||||||
import { updateLocation } from 'app/core/actions';
|
import { updateLocation } from 'app/core/actions';
|
||||||
import { UrlQueryValue, getBackendSrv } from '@grafana/runtime';
|
import { UrlQueryValue, getBackendSrv } from '@grafana/runtime';
|
||||||
import { Forms } from '@grafana/ui';
|
import { Forms, Button } from '@grafana/ui';
|
||||||
import { useAsync } from 'react-use';
|
import { useAsync } from 'react-use';
|
||||||
import Page from 'app/core/components/Page/Page';
|
import Page from 'app/core/components/Page/Page';
|
||||||
import { contextSrv } from 'app/core/core';
|
import { contextSrv } from 'app/core/core';
|
||||||
|
|
@ -115,7 +115,7 @@ const SingupInvitedPageUnconnected: FC<DispatchProps & ConnectedProps> = ({ code
|
||||||
/>
|
/>
|
||||||
</Forms.Field>
|
</Forms.Field>
|
||||||
|
|
||||||
<Forms.Button type="submit">Sign Up</Forms.Button>
|
<Button type="submit">Sign Up</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Forms.Form>
|
</Forms.Form>
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ export const DataLink = (props: Props) => {
|
||||||
onChange={handleChange('field')}
|
onChange={handleChange('field')}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
variant={'inverse'}
|
variant={'destructive'}
|
||||||
title="Remove field"
|
title="Remove field"
|
||||||
icon={'fa fa-times'}
|
icon={'fa fa-times'}
|
||||||
onClick={event => {
|
onClick={event => {
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ export const DataLinks = (props: Props) => {
|
||||||
})}
|
})}
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
variant={'inverse'}
|
variant={'secondary'}
|
||||||
className={css`
|
className={css`
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
`}
|
`}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ export const DerivedField = (props: Props) => {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
variant={'inverse'}
|
variant="destructive"
|
||||||
title="Remove field"
|
title="Remove field"
|
||||||
icon={'fa fa-times'}
|
icon={'fa fa-times'}
|
||||||
onClick={event => {
|
onClick={event => {
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ export const DerivedFields = (props: Props) => {
|
||||||
})}
|
})}
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
variant={'inverse'}
|
variant="primary"
|
||||||
className={css`
|
className={css`
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
`}
|
`}
|
||||||
|
|
@ -81,7 +81,7 @@ export const DerivedFields = (props: Props) => {
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{value && value.length > 0 && (
|
{value && value.length > 0 && (
|
||||||
<Button variant="inverse" onClick={() => setShowDebug(!showDebug)}>
|
<Button variant="secondary" onClick={() => setShowDebug(!showDebug)}>
|
||||||
{showDebug ? 'Hide example log message' : 'Show example log message'}
|
{showDebug ? 'Hide example log message' : 'Show example log message'}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ export class NewsPanelEditor extends PureComponent<PanelEditorProps<NewsOptions>
|
||||||
<div>
|
<div>
|
||||||
<br />
|
<br />
|
||||||
<div>If the feed is unable to connect, consider a CORS proxy</div>
|
<div>If the feed is unable to connect, consider a CORS proxy</div>
|
||||||
<Button variant="inverse" onClick={this.onSetProxyPrefix}>
|
<Button variant="secondary" onClick={this.onSetProxyPrefix}>
|
||||||
Use Proxy
|
Use Proxy
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -171,11 +171,11 @@ $table-bg-hover: $dark-6;
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
// -------------------------
|
// -------------------------
|
||||||
$btn-secondary-bg: $blue-base;
|
$btn-primary-bg: $blue-base;
|
||||||
$btn-secondary-bg-hl: $blue-shade;
|
$btn-primary-bg-hl: $blue-shade;
|
||||||
|
|
||||||
$btn-primary-bg: $green-base;
|
$btn-secondary-bg: $dark-6;
|
||||||
$btn-primary-bg-hl: $green-shade;
|
$btn-secondary-bg-hl: lighten($dark-6, 4%);
|
||||||
|
|
||||||
$btn-success-bg: $green-base;
|
$btn-success-bg: $green-base;
|
||||||
$btn-success-bg-hl: $green-shade;
|
$btn-success-bg-hl: $green-shade;
|
||||||
|
|
|
||||||
|
|
@ -163,11 +163,11 @@ $table-bg-hover: $gray-5;
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
// -------------------------
|
// -------------------------
|
||||||
$btn-primary-bg: $green-base;
|
$btn-secondary-bg: $gray-5;
|
||||||
$btn-primary-bg-hl: $green-shade;
|
$btn-secondary-bg-hl: $gray-4;
|
||||||
|
|
||||||
$btn-secondary-bg: $blue-base;
|
$btn-primary-bg: $blue-base;
|
||||||
$btn-secondary-bg-hl: $blue-shade;
|
$btn-primary-bg-hl: $blue-shade;
|
||||||
|
|
||||||
$btn-success-bg: $green-base;
|
$btn-success-bg: $green-base;
|
||||||
$btn-success-bg-hl: $green-shade;
|
$btn-success-bg-hl: $green-shade;
|
||||||
|
|
@ -176,7 +176,6 @@ $btn-danger-bg: $red-base;
|
||||||
$btn-danger-bg-hl: $red-shade;
|
$btn-danger-bg-hl: $red-shade;
|
||||||
|
|
||||||
$btn-inverse-bg: $gray-5;
|
$btn-inverse-bg: $gray-5;
|
||||||
$btn-inverse-bg-hl: darken($gray-5, 5%);
|
|
||||||
$btn-inverse-bg-hl: $gray-4;
|
$btn-inverse-bg-hl: $gray-4;
|
||||||
$btn-inverse-text-color: $gray-1;
|
$btn-inverse-text-color: $gray-1;
|
||||||
$btn-inverse-text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
|
$btn-inverse-text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
|
||||||
|
|
|
||||||
|
|
@ -171,8 +171,8 @@ i.navbar-page-btn__search {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&--secondary {
|
&--primary {
|
||||||
@include buttonBackground($btn-secondary-bg, $btn-secondary-bg-hl);
|
@include buttonBackground($btn-primary-bg, $btn-primary-bg-hl);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue