-
Notifications
You must be signed in to change notification settings - Fork 535
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* adds Switch component and stories * adds tests and more ARIA markup * adds component docs and fixes transition * adds changeset * update snapshots * addresses component design feedback * improves docs and storybook examples * updates snaps * Update src/Switch.tsx Co-authored-by: Cole Bemis <colebemis@github.com> * Update docs/content/Switch.mdx Co-authored-by: Cole Bemis <colebemis@github.com> * Update src/Switch.tsx Co-authored-by: Cole Bemis <colebemis@github.com> * Update src/Switch.tsx Co-authored-by: Cole Bemis <colebemis@github.com> * addresses PR feedback * increases contrast of control to meet WCAG guidelines * CSS cleanup and revert to light off button * updates snapshots * addresses PR feedback * rename switch docs * use component primitives for toggle switch colors * fixes documentation mistakes * updates snapshots * Update docs/content/ToggleSwitch.mdx Co-authored-by: Cole Bemis <colebemis@github.com> * Update docs/content/ToggleSwitch.mdx Co-authored-by: Cole Bemis <colebemis@github.com> * updates themePreval snapshot * upgrades primitives, updates snapshots * Update snapshot Co-authored-by: Cole Bemis <colebemis@github.com> Co-authored-by: simurai <simulus@gmail.com>
- Loading branch information
1 parent
adbcd3b
commit ae7650f
Showing
15 changed files
with
1,342 additions
and
47 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@primer/react': minor | ||
--- | ||
|
||
Adds a toggle switch component |
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,220 @@ | ||
--- | ||
componentId: toggle_switch | ||
title: ToggleSwitch | ||
description: Toggles a setting on or off, and immediately saves the change | ||
status: Alpha | ||
source: https://github.com/primer/react/blob/main/src/ToggleSwitch.tsx | ||
storybook: '/react/storybook?path=/story/toggleswitch-examples--default' | ||
--- | ||
|
||
## Examples | ||
|
||
### Basic | ||
|
||
```jsx live | ||
<Box display="flex" maxWidth="300px"> | ||
<Box flexGrow={1} fontSize={2} fontWeight="bold" id="switchLabel"> | ||
Notifications | ||
</Box> | ||
<ToggleSwitch aria-labelledby="switchLabel" /> | ||
</Box> | ||
``` | ||
|
||
### Uncontrolled with default value | ||
|
||
```jsx live | ||
<Box display="flex" maxWidth="300px"> | ||
<Box flexGrow={1} fontSize={2} fontWeight="bold" id="switchLabel"> | ||
Notifications | ||
</Box> | ||
<ToggleSwitch defaultChecked aria-labelledby="switchLabel" /> | ||
</Box> | ||
``` | ||
|
||
### Controlled | ||
|
||
```javascript noinline live | ||
const Controlled = () => { | ||
const [isOn, setIsOn] = React.useState(false) | ||
|
||
const onClick = () => { | ||
setIsOn(!isOn) | ||
} | ||
|
||
const handleSwitchChange = on => { | ||
console.log(`new switch "on" state: ${on}`) | ||
} | ||
|
||
return ( | ||
<> | ||
<Box display="flex" maxWidth="300px"> | ||
<Box flexGrow={1} fontSize={2} fontWeight="bold" id="switchLabel"> | ||
Notifications | ||
</Box> | ||
<ToggleSwitch onClick={onClick} onChange={handleSwitchChange} checked={isOn} aria-labelledby="switchLabel" /> | ||
</Box> | ||
<p>The switch is {isOn ? 'on' : 'off'}</p> | ||
</> | ||
) | ||
} | ||
|
||
render(Controlled) | ||
``` | ||
|
||
### Small | ||
|
||
```jsx live | ||
<Box display="flex" maxWidth="300px"> | ||
<Box flexGrow={1} fontSize={1} fontWeight="bold" id="switchLabel"> | ||
Notifications | ||
</Box> | ||
<ToggleSwitch aria-labelledby="switchLabel" size="small" /> | ||
</Box> | ||
``` | ||
|
||
### Delayed toggle with loading state | ||
|
||
```javascript noinline live | ||
const LoadingToggle = () => { | ||
const [loading, setLoading] = React.useState(false) | ||
const [isOn, setIsOn] = React.useState(false) | ||
|
||
async function switchSlowly(currentOn) { | ||
await new Promise(resolve => setTimeout(resolve, 1500)) | ||
return await !currentOn | ||
} | ||
|
||
async function onClick() { | ||
setLoading(!loading) | ||
const newSwitchState = await switchSlowly(isOn) | ||
setIsOn(newSwitchState) | ||
} | ||
|
||
const handleSwitchChange = React.useCallback( | ||
on => { | ||
setLoading(false) | ||
}, | ||
[setLoading] | ||
) | ||
|
||
return ( | ||
<> | ||
<Box display="flex" maxWidth="300px"> | ||
<Box flexGrow={1} fontSize={2} fontWeight="bold" id="switchLabel"> | ||
Notifications | ||
</Box> | ||
<ToggleSwitch | ||
aria-labelledby="switchLabel" | ||
loading={loading} | ||
checked={isOn} | ||
onClick={onClick} | ||
onChange={handleSwitchChange} | ||
/> | ||
</Box> | ||
<p>The switch is {isOn ? 'on' : 'off'}</p> | ||
</> | ||
) | ||
} | ||
|
||
render(LoadingToggle) | ||
``` | ||
|
||
### Disabled | ||
|
||
```jsx live | ||
<Box display="flex" maxWidth="300px"> | ||
<Box flexGrow={1} fontSize={2} fontWeight="bold" id="switchLabel"> | ||
Notifications | ||
</Box> | ||
<ToggleSwitch aria-labelledby="switchLabel" disabled /> | ||
</Box> | ||
``` | ||
|
||
### With associated caption text | ||
|
||
```jsx live | ||
<Box display="flex"> | ||
<Box flexGrow={1}> | ||
<Text fontSize={2} fontWeight="bold" id="switchLabel" display="block"> | ||
Notifications | ||
</Text> | ||
<Text color="fg.subtle" fontSize={1} id="switchCaption" display="block"> | ||
Notifications will be delivered via email and the GitHub notification center | ||
</Text> | ||
</Box> | ||
<ToggleSwitch aria-labelledby="switchLabel" aria-describedby="switchCaption" /> | ||
</Box> | ||
``` | ||
|
||
### Left-aligned with label | ||
|
||
```jsx live | ||
<> | ||
<Text fontSize={2} fontWeight="bold" id="switchLabel" display="block" mb={1}> | ||
Notifications | ||
</Text> | ||
<ToggleSwitch statusLabelPosition="end" aria-labelledby="switchLabel" /> | ||
</> | ||
``` | ||
|
||
## Props | ||
|
||
<PropsTable> | ||
<PropsTableRow name="aria-describedby" type="string" description="The id of the DOM node that describes the switch" /> | ||
<PropsTableRow | ||
name="aria-labelledby" | ||
type="string" | ||
required | ||
description="The id of the DOM node that labels the switch" | ||
/> | ||
<PropsTableRow name="defaultChecked" type="boolean" description="Uncontrolled - whether the switch is turned on" /> | ||
<PropsTableRow name="disabled" type="boolean" description="Whether the switch is ready for user input" /> | ||
<PropsTableRow name="loading" type="boolean" description="Whether the switch's value is being calculated" /> | ||
<PropsTableRow name="checked" type="boolean" description="Whether the switch is turned on" /> | ||
<PropsTableRow | ||
name="onChange" | ||
type="(on: boolean) => void" | ||
description="The callback that is called when the switch is toggled on or off" | ||
/> | ||
<PropsTableRow | ||
name="onClick" | ||
type="(e: MouseEvent) => void" | ||
description="The callback that is called when the switch is clicked" | ||
/> | ||
<PropsTableRow name="size" type="'small' | 'medium'" defaultValue="'medium'" description="Size of the switch" /> | ||
<PropsTableRow | ||
name="statusLabelPosition" | ||
type="'start' | 'end'" | ||
defaultValue="'start'" | ||
description={ | ||
<> | ||
<div>Whether the "on" and "off" labels should appear before or after the switch.</div> | ||
<div> | ||
<Text fontWeight="bold">This should only be changed when the switch's alignment needs to be adjusted.</Text>{' '} | ||
For example: It needs to be left-aligned because the label appears above it and the caption appears below it. | ||
</div> | ||
</> | ||
} | ||
/> | ||
</PropsTable> | ||
|
||
## Status | ||
|
||
<ComponentChecklist | ||
items={{ | ||
propsDocumented: true, | ||
noUnnecessaryDeps: true, | ||
adaptsToThemes: true, | ||
adaptsToScreenSizes: true, | ||
fullTestCoverage: true, | ||
usedInProduction: false, | ||
usageExamplesDocumented: true, | ||
hasStorybookStories: true, | ||
designReviewed: false, | ||
a11yReviewed: false, | ||
stableApi: false, | ||
addressedApiFeedback: false, | ||
hasDesignGuidelines: false, | ||
hasFigmaComponent: false | ||
}} | ||
/> |
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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
Oops, something went wrong.