Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ui): create <ToggleSwitch /> components
- Loading branch information
1 parent
03ec3f6
commit cd4fae9
Showing
11 changed files
with
490 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { ToggleSwitch as Filled } from './toggle-switch.component'; |
52 changes: 52 additions & 0 deletions
52
packages/ui/src/design-system/toggle-switch/toggle-switch.component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import type { HTMLAttributes, ReactNode } from 'react'; | ||
import React from 'react'; | ||
|
||
import * as Switch from '@radix-ui/react-switch'; | ||
|
||
import { Box } from '../box'; | ||
import { Flex } from '../flex'; | ||
import * as Typography from '../typography'; | ||
|
||
import * as cx from './toggle-switch.css'; | ||
|
||
type Props = Omit< | ||
HTMLAttributes<HTMLButtonElement>, | ||
'children' | 'className' | ||
> & { | ||
icon?: ReactNode; | ||
label?: string; | ||
onCheckedChange?: (checked: boolean) => void; | ||
disabled?: boolean; | ||
checked?: boolean; | ||
defaultChecked?: boolean; | ||
required?: boolean; | ||
id?: string; | ||
}; | ||
|
||
export const ToggleSwitch = ({ | ||
label, | ||
id, | ||
icon, | ||
disabled, | ||
...props | ||
}: Readonly<Props>): JSX.Element => { | ||
return ( | ||
<Flex | ||
alignItems="center" | ||
className={disabled === true ? cx.disabled : undefined} | ||
> | ||
<label className={cx.label} htmlFor={id}> | ||
<Typography.Body.Normal>{label}</Typography.Body.Normal> | ||
</label> | ||
{icon !== undefined && <Box className={cx.iconContainer}>{icon}</Box>} | ||
<Switch.Root | ||
{...props} | ||
disabled={disabled} | ||
className={cx.toogleSwitch} | ||
id={id} | ||
> | ||
<Switch.Thumb className={cx.thumb} /> | ||
</Switch.Root> | ||
</Flex> | ||
); | ||
}; |
90 changes: 90 additions & 0 deletions
90
packages/ui/src/design-system/toggle-switch/toggle-switch.css.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { sx, vars, style, createVar } from '../../design-tokens'; | ||
|
||
const boxShadow = createVar(); | ||
|
||
export const disabled = sx({ | ||
opacity: '$0_24', | ||
}); | ||
|
||
export const root = style({}); | ||
|
||
export const toogleSwitch = style([ | ||
sx({ | ||
width: '$44', | ||
height: '$24', | ||
background: '$toggle_switch_container_bgColor_off', | ||
borderRadius: '$small', | ||
}), | ||
{ | ||
padding: '0', | ||
border: 'none', | ||
position: 'relative', | ||
WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)', | ||
|
||
':disabled': { | ||
background: vars.colors.$toggle_switch_container_bgColor_disabled, | ||
}, | ||
|
||
selectors: { | ||
'&[data-state="checked"]:not(:disabled)': { | ||
background: vars.colors.$toggle_switch_container_bgColor_on, | ||
}, | ||
'&:active': { | ||
outline: 'none', | ||
}, | ||
'&:focus:not(:active)': { | ||
outlineColor: `${vars.colors.$buttons_cta_container_outlineColor}`, | ||
outlineWidth: vars.spacing.$4, | ||
outlineStyle: 'solid', | ||
}, | ||
}, | ||
}, | ||
]); | ||
|
||
export const thumb = style([ | ||
sx({ | ||
width: '$20', | ||
height: '$20', | ||
borderRadius: '$circle', | ||
}), | ||
{ | ||
display: 'block', | ||
backgroundColor: 'white', | ||
boxShadow: boxShadow, | ||
transition: 'transform 100ms', | ||
transform: 'translateX(2px)', | ||
willChange: 'transform', | ||
|
||
vars: { | ||
[boxShadow]: | ||
'0px 1px 3px rgba(0, 0, 0, 0.1), 0px 1px 2px rgba(0, 0, 0, 0.06)', | ||
}, | ||
|
||
selectors: { | ||
'&[data-state="checked"]': { | ||
transform: 'translateX(22px)', | ||
}, | ||
}, | ||
}, | ||
]); | ||
|
||
export const label = sx({ | ||
color: '$toggle_switch_label_color', | ||
mr: '$8', | ||
}); | ||
|
||
export const iconContainer = style([ | ||
sx({ | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
mr: '$8', | ||
width: '$24', | ||
height: '$24', | ||
color: '$toggle_switch_label_color', | ||
fontSize: '$25', | ||
}), | ||
{ | ||
overflow: 'hidden', | ||
}, | ||
]); |
229 changes: 229 additions & 0 deletions
229
packages/ui/src/design-system/toggle-switch/toggle-switch.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
import React from 'react'; | ||
|
||
import type { Meta } from '@storybook/react'; | ||
|
||
import { ReactComponent as InfoIcon } from '../../assets/icons/info.component.svg'; | ||
import { ThemeColorScheme, ThemeProvider } from '../../design-tokens'; | ||
import { Page, Variants, Section } from '../decorators'; | ||
import { Divider } from '../divider'; | ||
import { Grid } from '../grid'; | ||
import { Cell } from '../grid/cell.component'; | ||
|
||
import { ToggleSwitch } from './toggle-switch.component'; | ||
|
||
const subtitle = `The toggle switch represents a physical switch that allows users to turn things on or off. Use toggle switch controls to present users with two mutually exclusive options (such as on/off), where choosing an option provides immediate results.`; | ||
|
||
export default { | ||
title: 'Basic Input/Toggle switch', | ||
component: ToggleSwitch, | ||
decorators: [ | ||
(Story): JSX.Element => ( | ||
<Page title="Toggle switch" subtitle={subtitle}> | ||
<Story /> | ||
</Page> | ||
), | ||
], | ||
} as Meta; | ||
|
||
const ToggleSwitchPreview = (): JSX.Element => ( | ||
<> | ||
<Variants.Row> | ||
<Variants.Cell> | ||
<ToggleSwitch | ||
label="Label" | ||
id="rest" | ||
defaultChecked | ||
icon={<InfoIcon />} | ||
/> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch | ||
label="Label" | ||
id="hover" | ||
defaultChecked | ||
icon={<InfoIcon />} | ||
/> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch | ||
label="Label" | ||
id="pressed" | ||
defaultChecked | ||
icon={<InfoIcon />} | ||
/> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch | ||
label="Label" | ||
disabled | ||
defaultChecked | ||
icon={<InfoIcon />} | ||
/> | ||
</Variants.Cell> | ||
</Variants.Row> | ||
<Variants.Row> | ||
<Variants.Cell> | ||
<ToggleSwitch label="Label" id="rest" icon={<InfoIcon />} /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch label="Label" id="hover" icon={<InfoIcon />} /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch label="Label" id="pressed" icon={<InfoIcon />} /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch label="Label" disabled icon={<InfoIcon />} /> | ||
</Variants.Cell> | ||
</Variants.Row> | ||
<Variants.Row> | ||
<Variants.Cell> | ||
<ToggleSwitch label="Label" id="rest" /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch label="Label" id="hover" /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch label="Label" id="pressed" /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch label="Label" disabled /> | ||
</Variants.Cell> | ||
</Variants.Row> | ||
<Variants.Row> | ||
<Variants.Cell> | ||
<ToggleSwitch id="rest" defaultChecked /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch id="hover" defaultChecked /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch id="pressed" defaultChecked /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch disabled defaultChecked /> | ||
</Variants.Cell> | ||
</Variants.Row> | ||
<Variants.Row> | ||
<Variants.Cell> | ||
<ToggleSwitch id="rest" /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch id="hover" /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch id="pressed" /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch disabled /> | ||
</Variants.Cell> | ||
</Variants.Row> | ||
</> | ||
); | ||
|
||
const SwitchPreview = (): JSX.Element => ( | ||
<> | ||
<Variants.Row> | ||
<Variants.Cell> | ||
<ToggleSwitch id="rest" defaultChecked /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch id="hover" defaultChecked /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch id="pressed" defaultChecked /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch disabled defaultChecked /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch id="focused" defaultChecked /> | ||
</Variants.Cell> | ||
</Variants.Row> | ||
<Variants.Row> | ||
<Variants.Cell> | ||
<ToggleSwitch id="rest" /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch id="hover" /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch id="pressed" /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch disabled /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch id="focused" /> | ||
</Variants.Cell> | ||
</Variants.Row> | ||
</> | ||
); | ||
|
||
export const Overview = (): JSX.Element => ( | ||
<Grid columns="$1"> | ||
<Cell> | ||
<Section title="Variants"> | ||
<Variants.Table | ||
headers={[ | ||
'Base control with label and icon', | ||
'Base control with label', | ||
'Simple base control', | ||
]} | ||
> | ||
<Variants.Row> | ||
<Variants.Cell> | ||
<ToggleSwitch | ||
label="Label" | ||
id="toggle" | ||
defaultChecked | ||
icon={<InfoIcon />} | ||
/> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch label="Label" defaultChecked /> | ||
</Variants.Cell> | ||
<Variants.Cell> | ||
<ToggleSwitch defaultChecked /> | ||
</Variants.Cell> | ||
</Variants.Row> | ||
</Variants.Table> | ||
<Divider my="$64" /> | ||
</Section> | ||
<Section title="Main components"> | ||
<Variants.Table | ||
headers={['Rest', 'Hover', 'Active / pressed', 'Disabled']} | ||
> | ||
<ToggleSwitchPreview /> | ||
</Variants.Table> | ||
|
||
<ThemeProvider colorScheme={ThemeColorScheme.Dark}> | ||
<Variants.Table> | ||
<ToggleSwitchPreview /> | ||
</Variants.Table> | ||
</ThemeProvider> | ||
</Section> | ||
<Divider my="$64" /> | ||
<Section title="Toggle switch items 🔒"> | ||
<Variants.Table | ||
headers={['Rest', 'Hover', 'Active / pressed', 'Disabled', 'Focused']} | ||
> | ||
<SwitchPreview /> | ||
</Variants.Table> | ||
|
||
<ThemeProvider colorScheme={ThemeColorScheme.Dark}> | ||
<Variants.Table> | ||
<SwitchPreview /> | ||
</Variants.Table> | ||
</ThemeProvider> | ||
</Section> | ||
</Cell> | ||
</Grid> | ||
); | ||
|
||
Overview.parameters = { | ||
pseudo: { | ||
hover: '#hover', | ||
focus: '#focused', | ||
active: '#pressed', | ||
}, | ||
}; |
Oops, something went wrong.