mirror of
https://github.com/grafana/grafana.git
synced 2025-02-15 10:03:33 -06:00
Forms: Introduce new Switch component (#20470)
* Introduce new Switch component * Experiment with different focus style * Review update * Update on/off swtch colors
This commit is contained in:
parent
2c2ed8371d
commit
17362b4180
@ -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;
|
||||
|
20
packages/grafana-ui/src/components/Forms/Switch.mdx
Normal file
20
packages/grafana-ui/src/components/Forms/Switch.mdx
Normal file
@ -0,0 +1,20 @@
|
||||
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} />
|
||||
|
31
packages/grafana-ui/src/components/Forms/Switch.story.tsx
Normal file
31
packages/grafana-ui/src/components/Forms/Switch.story.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
79
packages/grafana-ui/src/components/Forms/Switch.tsx
Normal file
79
packages/grafana-ui/src/components/Forms/Switch.tsx
Normal file
@ -0,0 +1,79 @@
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user