Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
81d5b63
adds Switch component and stories
mperrotti Mar 7, 2022
f02595e
adds tests and more ARIA markup
mperrotti Mar 8, 2022
872bdb4
adds component docs and fixes transition
mperrotti Mar 8, 2022
0316ed3
adds changeset
mperrotti Mar 8, 2022
27dccc7
Merge branch 'main' into mp/switch-component
mperrotti Mar 8, 2022
ca8950c
update snapshots
mperrotti Mar 8, 2022
108b40f
Merge branch 'mp/switch-component' of github.com:primer/react into mp…
mperrotti Mar 8, 2022
40ff806
Merge branch 'main' of github.com:primer/react into mp/switch-component
mperrotti Mar 8, 2022
cebfa1b
addresses component design feedback
mperrotti Mar 9, 2022
176b5b8
improves docs and storybook examples
mperrotti Mar 10, 2022
d653469
Merge branch 'main' of github.com:primer/react into mp/switch-component
mperrotti Mar 10, 2022
30612f9
updates snaps
mperrotti Mar 10, 2022
b475d8a
Merge branch 'main' into mp/switch-component
mperrotti Mar 11, 2022
1d52067
Update src/Switch.tsx
mperrotti Mar 11, 2022
37ed9ae
Update docs/content/Switch.mdx
mperrotti Mar 11, 2022
1971e6f
Update src/Switch.tsx
mperrotti Mar 11, 2022
3b8d444
Update src/Switch.tsx
mperrotti Mar 11, 2022
55817f2
addresses PR feedback
mperrotti Mar 15, 2022
22c19ae
Merge branch 'mp/switch-component' of github.com:primer/react into mp…
mperrotti Mar 15, 2022
f43c423
Merge branch 'main' of github.com:primer/react into mp/switch-component
mperrotti Mar 15, 2022
3ce5352
increases contrast of control to meet WCAG guidelines
mperrotti Mar 16, 2022
301e05a
CSS cleanup and revert to light off button
mperrotti Mar 17, 2022
8c32664
Merge branch 'main' of github.com:primer/react into mp/switch-component
mperrotti Mar 17, 2022
650a89f
updates snapshots
mperrotti Mar 17, 2022
1bd2e3f
addresses PR feedback
mperrotti Mar 17, 2022
5516bee
rename switch docs
mperrotti Mar 17, 2022
16a3c9c
Merge branch 'main' of github.com:primer/react into mp/switch-component
mperrotti Mar 18, 2022
f79f4a3
use component primitives for toggle switch colors
mperrotti Mar 21, 2022
b9558bb
Merge branch 'main' of github.com:primer/react into mp/switch-component
mperrotti Mar 21, 2022
bbadab8
fixes documentation mistakes
mperrotti Mar 21, 2022
ce275cd
updates snapshots
mperrotti Mar 21, 2022
d3022e4
Update docs/content/ToggleSwitch.mdx
mperrotti Mar 21, 2022
97cea00
Update docs/content/ToggleSwitch.mdx
mperrotti Mar 21, 2022
09b735e
Merge branch 'main' of github.com:primer/react into mp/switch-component
mperrotti Mar 21, 2022
7afe8e3
updates themePreval snapshot
mperrotti Mar 21, 2022
2871849
Merge branch 'main' of github.com:primer/react into mp/switch-component
mperrotti Mar 22, 2022
5aee49d
upgrades primitives, updates snapshots
mperrotti Mar 23, 2022
fa9ff75
Update snapshot
simurai Mar 24, 2022
bb78093
Merge branch 'main' into mp/switch-component
mperrotti Mar 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/stupid-carrots-jam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

Adds a toggle switch component
225 changes: 225 additions & 0 deletions docs/content/Switch.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
---
componentId: switch
title: Switch
description: Toggles a setting on or off, and immediately saves the change
status: Alpha
source: https://github.com/primer/react/blob/main/src/Switch.tsx
storybook: '/react/storybook?path=/story/switch-examples--default'
---

## Examples

### Basic

```jsx live
<Box display="flex" maxWidth="300px">
<Box flexGrow={1} fontSize={2} fontWeight="bold" id="switchLabel">
Notifications
</Box>
<Switch aria-labelledby="switchLabel" />
</Box>
```

### Uncontrolled (on)

```jsx live
<Box display="flex" maxWidth="300px">
<Box flexGrow={1} fontSize={2} fontWeight="bold" id="switchLabel">
Notifications
</Box>
<Switch defaultOn 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>
<Switch onClick={onClick} onChange={handleSwitchChange} on={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>
<Switch aria-labelledby="switchLabel" size="small" />
</Box>
```

### Delayed toggle with loading state

```javascript noinline live
const LoadingToggle = () => {
const [isLoading, setIsLoading] = 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() {
setIsLoading(!isLoading)
const newSwitchState = await switchSlowly(isOn)
setIsOn(newSwitchState)
}

const handleSwitchChange = React.useCallback(
on => {
setIsLoading(false)
},
[setIsLoading]
)

return (
<>
<Box display="flex" maxWidth="300px">
<Box flexGrow={1} fontSize={2} fontWeight="bold" id="switchLabel">
Notifications
</Box>
<Switch
aria-labelledby="switchLabel"
isLoading={isLoading}
on={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>
<Switch 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>
<Switch 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>
<Switch statusLabelPosition="end" aria-labelledby="switchLabel" />
</>
```

## Props

/\*\* Whether the "on" and "off" labels should appear before or after the switch.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI

Screenshot 2022-03-17 at 09 49 19


- **This should only be changed when the switch's alignment needs to be adjusted.** For example: It needs to be left-aligned because the label appears above it and the caption appears below it.
\*/
statusLabelPosition?: 'start' | 'end'

<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="defaultOn" 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="isLoading" type="boolean" description="Whether the switch is ready for user input" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we change this to loading?

Suggested change
<PropsTableRow name="isLoading" type="boolean" description="Whether the switch is ready for user input" />
<PropsTableRow name="loading" type="boolean" description="Whether the switch is ready for user input" />

Also, is it intentional that the description is the same as the disabled prop?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not intentional. Thanks for flagging that.

<PropsTableRow name="on" type="boolean" description="Whether the switch is turned on" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we call this prop checked instead of on to align with the <input type="checkbox"> API?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm good with that.

<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'" description="Size of the switch" />
<PropsTableRow
name="statusLabelPosition"
type="'start' | 'end'"
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
}}
/>
2 changes: 2 additions & 0 deletions docs/src/@primer/gatsby-theme-doctocat/nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@
url: /StyledOcticon
- title: SubNav
url: /SubNav
- title: Switch
url: /Switch
- title: TabNav
url: /TabNav
- title: Textarea
Expand Down
Loading