Commit 17362b41 by Dominik Prokop Committed by GitHub

Forms: Introduce new Switch component (#20470)

* Introduce new Switch component

* Experiment with different focus style

* Review update

* Update on/off swtch colors
parent 2c2ed837
......@@ -223,13 +223,19 @@ export interface GrafanaTheme extends GrafanaThemeCommons {
formInputBorderHover: string;
formInputBorderActive: string;
formInputBorderInvalid: string;
formInputFocusOutline: string;
formFocusOutline: string;
formInputText: string;
formInputDisabledText: string;
formInputTextStrong: string;
formInputTextWhite: string;
formValidationMessageText: string;
formValidationMessageBg: string;
formSwitchBg: string;
formSwitchBgActive: string;
formSwitchBgActiveHover: string;
formSwitchBgHover: string;
formSwitchBgDisabled: string;
formSwitchDot: string;
};
shadow: {
pageHeader: string;
......
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
import { Switch } from './Switch';
<Meta title="MDX|Switch" component={Switch} />
# Switch
Used to represent binary values
### Usage
```jsx
import { Forms } from '@grafana/ui';
<Forms.Switch disabled={...} checked={...} onChange={...} />
```
### Props
<Props of={Switch} />
import React, { useState } from 'react';
import { boolean } from '@storybook/addon-knobs';
import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory';
import { Switch } from './Switch';
import mdx from './Switch.mdx';
export default {
title: 'UI/Forms/Switch',
component: Switch,
decorators: [withCenteredStory, withHorizontallyCenteredStory],
parameters: {
docs: {
page: mdx,
},
},
};
export const simple = () => {
const [checked, setChecked] = useState(false);
const BEHAVIOUR_GROUP = 'Behaviour props';
const disabled = boolean('Disabled', false, BEHAVIOUR_GROUP);
return (
<Switch
checked={checked}
disabled={disabled}
onChange={(e, checked) => {
setChecked(checked);
}}
/>
);
};
import React from 'react';
import { stylesFactory, useTheme } from '../../themes';
import { GrafanaTheme } from '@grafana/data';
import { css, cx } from 'emotion';
import { getFocusStyle } from './commonStyles';
export interface SwitchProps {
checked?: boolean;
disabled?: boolean;
onChange?: (e: React.SyntheticEvent<HTMLButtonElement>, checked: boolean) => void;
}
export const getSwitchStyles = stylesFactory((theme: GrafanaTheme) => {
return {
slider: cx(
css`
width: 32px;
height: 16px;
background: ${theme.colors.formSwitchBg};
transition: all 0.30s ease;
border-radius: 50px;
position: relative;
border: none;
display: block;
padding: 0;
&:hover {
background: ${theme.colors.formSwitchBgHover};
}
&:after {
content: '';
transition: transform 0.2s cubic-bezier(0.19, 1, 0.22, 1);
position: absolute;
top: 50%;
display: block;
width: 12px;
height: 12px;
background: ${theme.colors.formSwitchDot};
border-radius: 6px;
transform: translate3d(2px, -50%, 0);
}
&:focus {
/* border: 1px solid ${theme.colors.formSwitchDot}; */
}
&[disabled] {
background: ${theme.colors.formSwitchBgDisabled};
}
`,
getFocusStyle(theme)
),
sliderActive: css`
background: ${theme.colors.formSwitchBgActive};
&:hover {
background: ${theme.colors.formSwitchBgActiveHover};
}
&:after {
transform: translate3d(16px, -50%, 0);
}
`,
};
});
export const Switch: React.FC<SwitchProps> = ({ checked = false, disabled = false, onChange }) => {
const theme = useTheme();
const styles = getSwitchStyles(theme);
return (
<button
type="button"
role="switch"
aria-checked={!!checked}
disabled={disabled}
className={cx(styles.slider, checked && styles.sliderActive)}
onClick={e => {
if (onChange) {
onChange(e, !!!checked);
}
}}
/>
);
};
......@@ -3,7 +3,9 @@ import { GrafanaTheme } from '@grafana/data';
export const getFocusStyle = (theme: GrafanaTheme) => css`
&:focus {
outline: none;
box-shadow: 0 0 0 2px ${theme.colors.blueLight};
outline: 2px dotted transparent;
outline-offset: 2px;
box-shadow: 0 0 0 2px ${theme.colors.pageBg}, 0 0 0px 4px ${theme.colors.formFocusOutline};
transition: all 0.2s cubic-bezier(0.19, 1, 0.22, 1);
}
`;
......@@ -6,6 +6,7 @@ import { getFieldValidationMessageStyles } from './FieldValidationMessage';
import { getButtonStyles, ButtonVariant } from './Button';
import { ButtonSize } from '../Button/types';
import { getInputStyles } from './Input/Input';
import { getSwitchStyles } from './Switch';
export const getFormStyles = stylesFactory(
(theme: GrafanaTheme, options: { variant: ButtonVariant; size: ButtonSize; invalid: boolean }) => {
......@@ -19,6 +20,7 @@ export const getFormStyles = stylesFactory(
size: options.size,
}),
...getInputStyles({ theme, invalid: options.invalid }),
...getSwitchStyles(theme),
};
}
);
......@@ -86,13 +86,19 @@ const darkTheme: GrafanaTheme = {
formInputBorderHover: basicColors.gray33,
formInputBorderActive: basicColors.blue95,
formInputBorderInvalid: basicColors.red88,
formInputFocusOutline: basicColors.blue77,
formInputText: basicColors.gray85,
formInputDisabledText: basicColors.gray70,
formInputTextStrong: basicColors.gray85,
formInputTextWhite: basicColors.white,
formFocusOutline: basicColors.blueShade,
formValidationMessageText: basicColors.white,
formValidationMessageBg: basicColors.red88,
formSwitchBg: basicColors.gray25,
formSwitchBgActive: basicColors.blueLight,
formSwitchBgHover: basicColors.gray33,
formSwitchBgActiveHover: basicColors.blueBase,
formSwitchBgDisabled: basicColors.gray25,
formSwitchDot: basicColors.gray15,
},
background: {
dropdown: basicColors.dark3,
......
......@@ -87,13 +87,19 @@ const lightTheme: GrafanaTheme = {
formInputBorderHover: basicColors.gray70,
formInputBorderActive: basicColors.blue77,
formInputBorderInvalid: basicColors.red88,
formInputFocusOutline: basicColors.blue95,
formInputText: basicColors.gray25,
formInputDisabledText: basicColors.gray33,
formInputTextStrong: basicColors.gray25,
formInputTextWhite: basicColors.white,
formFocusOutline: basicColors.blueLight,
formValidationMessageText: basicColors.white,
formValidationMessageBg: basicColors.red88,
formSwitchBg: basicColors.gray85,
formSwitchBgActive: basicColors.blueShade,
formSwitchBgHover: basicColors.gray3,
formSwitchBgActiveHover: basicColors.blueBase,
formSwitchBgDisabled: basicColors.gray4,
formSwitchDot: basicColors.white,
},
background: {
dropdown: basicColors.white,
......
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