Commit 6de75de7 by Tobias Skarhed Committed by GitHub

Refactor buttons (#17611)

parent 8192fa53
......@@ -4,21 +4,9 @@ import { css, cx } from 'emotion';
import { Themeable, GrafanaTheme } from '../../types';
import { selectThemeVariant } from '../../themes/selectThemeVariant';
export enum ButtonVariant {
Primary = 'primary',
Secondary = 'secondary',
Danger = 'danger',
Inverse = 'inverse',
Transparent = 'transparent',
}
export type ButtonVariant = 'primary' | 'secondary' | 'danger' | 'inverse' | 'transparent';
export enum ButtonSize {
ExtraSmall = 'xs',
Small = 'sm',
Medium = 'md',
Large = 'lg',
ExtraLarge = 'xl',
}
export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
export interface CommonButtonProps {
size?: ButtonSize;
......@@ -69,19 +57,19 @@ const getButtonStyles = (theme: GrafanaTheme, size: ButtonSize, variant: ButtonV
fontWeight = theme.typography.weight.semibold;
switch (size) {
case ButtonSize.Small:
case 'sm':
padding = `${theme.spacing.xs} ${theme.spacing.sm}`;
fontSize = theme.typography.size.sm;
iconDistance = theme.spacing.xs;
height = theme.height.sm;
break;
case ButtonSize.Medium:
case 'md':
padding = `${theme.spacing.sm} ${theme.spacing.md}`;
fontSize = theme.typography.size.md;
iconDistance = theme.spacing.sm;
height = theme.height.md;
break;
case ButtonSize.Large:
case 'lg':
padding = `${theme.spacing.md} ${theme.spacing.lg}`;
fontSize = theme.typography.size.lg;
fontWeight = theme.typography.weight.regular;
......@@ -96,16 +84,16 @@ const getButtonStyles = (theme: GrafanaTheme, size: ButtonSize, variant: ButtonV
}
switch (variant) {
case ButtonVariant.Primary:
case 'primary':
background = buttonVariantStyles(theme.colors.greenBase, theme.colors.greenShade, theme.colors.white);
break;
case ButtonVariant.Secondary:
case 'secondary':
background = buttonVariantStyles(theme.colors.blueBase, theme.colors.blueShade, theme.colors.white);
break;
case ButtonVariant.Danger:
case 'danger':
background = buttonVariantStyles(theme.colors.redBase, theme.colors.redShade, theme.colors.white);
break;
case ButtonVariant.Inverse:
case 'inverse':
const from = selectThemeVariant({ light: theme.colors.gray5, dark: theme.colors.dark6 }, theme.type) as string;
const to = selectThemeVariant(
{
......@@ -121,7 +109,7 @@ const getButtonStyles = (theme: GrafanaTheme, size: ButtonSize, variant: ButtonV
background = buttonVariantStyles(from, to, theme.colors.link, 'rgba(0, 0, 0, 0.1)', true);
break;
case ButtonVariant.Transparent:
case 'transparent':
background = css`
${buttonVariantStyles('', '', theme.colors.link, 'rgba(0, 0, 0, 0.1)', true)};
background: transparent;
......@@ -170,8 +158,8 @@ const getButtonStyles = (theme: GrafanaTheme, size: ButtonSize, variant: ButtonV
export const AbstractButton: React.FunctionComponent<AbstractButtonProps> = ({
renderAs,
theme,
size = ButtonSize.Medium,
variant = ButtonVariant.Primary,
size = 'md',
variant = 'primary',
className,
icon,
children,
......
import { storiesOf } from '@storybook/react';
import { Button, LinkButton } from './Button';
import { ButtonSize, ButtonVariant, CommonButtonProps } from './AbstractButton';
import { CommonButtonProps } from './AbstractButton';
// @ts-ignore
import withPropsCombinations from 'react-storybook-addon-props-combinations';
import { action } from '@storybook/addon-actions';
......@@ -15,14 +15,8 @@ const defaultProps = {
};
const variants = {
size: [ButtonSize.ExtraSmall, ButtonSize.Small, ButtonSize.Medium, ButtonSize.Large, ButtonSize.ExtraLarge],
variant: [
ButtonVariant.Primary,
ButtonVariant.Secondary,
ButtonVariant.Danger,
ButtonVariant.Inverse,
ButtonVariant.Transparent,
],
size: ['xs', 'sm', 'md', 'lg', 'xl'],
variant: ['primary', 'secondary', 'danger', 'inverse', 'transparent'],
};
const combinationOptions = {
CombinationRenderer: ThemeableCombinationsRowRenderer,
......
import React, { useContext } from 'react';
import { AbstractButton, ButtonProps, ButtonSize, LinkButtonProps } from './AbstractButton';
import { AbstractButton, ButtonProps, LinkButtonProps } from './AbstractButton';
import { ThemeContext } from '../../themes';
const getSizeNameComponentSegment = (size: ButtonSize) => {
switch (size) {
case ButtonSize.ExtraSmall:
return 'ExtraSmall';
case ButtonSize.Small:
return 'Small';
case ButtonSize.Large:
return 'Large';
case ButtonSize.ExtraLarge:
return 'ExtraLarge';
default:
return 'Medium';
}
};
const buttonFactory: <T>(renderAs: string, size: ButtonSize, displayName: string) => React.ComponentType<T> = (
renderAs,
size,
displayName
) => {
const ButtonComponent: React.FunctionComponent<any> = props => {
const theme = useContext(ThemeContext);
return <AbstractButton {...props} size={size} renderAs={renderAs} theme={theme} />;
};
ButtonComponent.displayName = displayName;
return ButtonComponent;
};
export const Button: React.FunctionComponent<ButtonProps> = props => {
const theme = useContext(ThemeContext);
return <AbstractButton {...props} renderAs="button" theme={theme} />;
......@@ -42,45 +13,3 @@ export const LinkButton: React.FunctionComponent<LinkButtonProps> = props => {
return <AbstractButton {...props} renderAs="a" theme={theme} />;
};
LinkButton.displayName = 'LinkButton';
export const ExtraSmallButton = buttonFactory<ButtonProps>(
'button',
ButtonSize.ExtraSmall,
`${getSizeNameComponentSegment(ButtonSize.ExtraSmall)}Button`
);
export const SmallButton = buttonFactory<ButtonProps>(
'button',
ButtonSize.Small,
`${getSizeNameComponentSegment(ButtonSize.Small)}Button`
);
export const LargeButton = buttonFactory<ButtonProps>(
'button',
ButtonSize.Large,
`${getSizeNameComponentSegment(ButtonSize.Large)}Button`
);
export const ExtraLargeButton = buttonFactory<ButtonProps>(
'button',
ButtonSize.ExtraLarge,
`${getSizeNameComponentSegment(ButtonSize.ExtraLarge)}Button`
);
export const ExtraSmallLinkButton = buttonFactory<LinkButtonProps>(
'a',
ButtonSize.ExtraSmall,
`${getSizeNameComponentSegment(ButtonSize.ExtraSmall)}LinkButton`
);
export const SmallLinkButton = buttonFactory<LinkButtonProps>(
'a',
ButtonSize.Small,
`${getSizeNameComponentSegment(ButtonSize.Small)}LinkButton`
);
export const LargeLinkButton = buttonFactory<LinkButtonProps>(
'a',
ButtonSize.Large,
`${getSizeNameComponentSegment(ButtonSize.Large)}LinkButton`
);
export const ExtraLargeLinkButton = buttonFactory<LinkButtonProps>(
'a',
ButtonSize.ExtraLarge,
`${getSizeNameComponentSegment(ButtonSize.ExtraLarge)}LinkButton`
);
......@@ -3,7 +3,7 @@ import { storiesOf } from '@storybook/react';
import { renderComponentWithTheme } from '../../utils/storybook/withTheme';
import { CallToActionCard } from './CallToActionCard';
import { select, text } from '@storybook/addon-knobs';
import { LargeButton } from '../Button/Button';
import { Button } from '../Button/Button';
import { action } from '@storybook/addon-actions';
const CallToActionCardStories = storiesOf('UI/CallToActionCard', module);
......@@ -12,9 +12,9 @@ CallToActionCardStories.add('default', () => {
const ctaElements: { [key: string]: JSX.Element } = {
custom: <h1>This is just H1 tag, you can any component as CTA element</h1>,
button: (
<LargeButton icon="fa fa-plus" onClick={action('cta button clicked')}>
<Button size="lg" icon="fa fa-plus" onClick={action('cta button clicked')}>
Add datasource
</LargeButton>
</Button>
),
};
const ctaElement = select(
......
import React, { useContext } from 'react';
import { CallToActionCard, LargeLinkButton, ThemeContext } from '@grafana/ui';
import { CallToActionCard, LinkButton, ThemeContext } from '@grafana/ui';
import { css } from 'emotion';
export interface Props {
model: any;
......@@ -37,9 +37,9 @@ const EmptyListCTA: React.FunctionComponent<Props> = props => {
: '';
const ctaElement = (
<LargeLinkButton onClick={onClick} href={buttonLink} icon={buttonIcon} className={ctaElementClassName}>
<LinkButton size="lg" onClick={onClick} href={buttonLink} icon={buttonIcon} className={ctaElementClassName}>
{buttonTitle}
</LargeLinkButton>
</LinkButton>
);
return <CallToActionCard message={title} footer={footer} callToActionElement={ctaElement} theme={theme} />;
......
......@@ -11,7 +11,6 @@ import {
} from '@grafana/ui';
import ElapsedTime from './ElapsedTime';
import { ButtonSize, ButtonVariant } from '@grafana/ui/src/components/Button/AbstractButton';
const getStyles = (theme: GrafanaTheme) => ({
logsRowsLive: css`
......@@ -110,8 +109,8 @@ class LiveLogs extends PureComponent<Props, State> {
</span>
<LinkButton
onClick={this.props.stopLive}
size={ButtonSize.Medium}
variant={ButtonVariant.Transparent}
size="md"
variant="transparent"
style={{ color: theme.colors.orange }}
>
Stop Live
......
import React, { useContext } from 'react';
import { css } from 'emotion';
import { ThemeContext, LargeLinkButton, CallToActionCard } from '@grafana/ui';
import { ThemeContext, LinkButton, CallToActionCard } from '@grafana/ui';
export const NoDataSourceCallToAction = () => {
const theme = useContext(ThemeContext);
......@@ -22,9 +22,9 @@ export const NoDataSourceCallToAction = () => {
);
const ctaElement = (
<LargeLinkButton href="/datasources/new" icon="gicon gicon-datasources">
<LinkButton size="lg" href="/datasources/new" icon="gicon gicon-datasources">
Add data source
</LargeLinkButton>
</LinkButton>
);
const cardClassName = css`
......
......@@ -7,7 +7,6 @@ import { PluginMeta, AppPlugin, Button } from '@grafana/ui';
import { AngularComponent, getAngularLoader } from '@grafana/runtime';
import { getBackendSrv } from 'app/core/services/backend_srv';
import { ButtonVariant } from '@grafana/ui/src/components/Button/AbstractButton';
import { css } from 'emotion';
interface Props {
......@@ -71,17 +70,17 @@ export class AppConfigCtrlWrapper extends PureComponent<Props, State> {
{model && (
<div className="gf-form">
{!model.enabled && (
<Button variant={ButtonVariant.Primary} onClick={this.enable} className={withRightMargin}>
<Button variant="primary" onClick={this.enable} className={withRightMargin}>
Enable
</Button>
)}
{model.enabled && (
<Button variant={ButtonVariant.Primary} onClick={this.update} className={withRightMargin}>
<Button variant="primary" onClick={this.update} className={withRightMargin}>
Update
</Button>
)}
{model.enabled && (
<Button variant={ButtonVariant.Danger} onClick={this.disable} className={withRightMargin}>
<Button variant="danger" onClick={this.disable} className={withRightMargin}>
Disable
</Button>
)}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment