diff --git a/packages/grafana-data/src/types/theme.ts b/packages/grafana-data/src/types/theme.ts index 8efa746a7f6..fced5a9b0c5 100644 --- a/packages/grafana-data/src/types/theme.ts +++ b/packages/grafana-data/src/types/theme.ts @@ -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; diff --git a/packages/grafana-ui/src/components/Forms/Switch.mdx b/packages/grafana-ui/src/components/Forms/Switch.mdx new file mode 100644 index 00000000000..5a8cf5e3d46 --- /dev/null +++ b/packages/grafana-ui/src/components/Forms/Switch.mdx @@ -0,0 +1,20 @@ +import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks'; +import { Switch } from './Switch'; + + + +# Switch + +Used to represent binary values + +### Usage + +```jsx +import { Forms } from '@grafana/ui'; + + +``` + +### Props + + diff --git a/packages/grafana-ui/src/components/Forms/Switch.story.tsx b/packages/grafana-ui/src/components/Forms/Switch.story.tsx new file mode 100644 index 00000000000..c9cab1879b4 --- /dev/null +++ b/packages/grafana-ui/src/components/Forms/Switch.story.tsx @@ -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 ( + { + setChecked(checked); + }} + /> + ); +}; diff --git a/packages/grafana-ui/src/components/Forms/Switch.tsx b/packages/grafana-ui/src/components/Forms/Switch.tsx new file mode 100644 index 00000000000..e809fffce05 --- /dev/null +++ b/packages/grafana-ui/src/components/Forms/Switch.tsx @@ -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, 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 = ({ checked = false, disabled = false, onChange }) => { + const theme = useTheme(); + const styles = getSwitchStyles(theme); + + return ( +