Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a45f5d5
adds inactive state to button components
mperrotti Oct 12, 2023
557b012
update snapshots
mperrotti Oct 12, 2023
f3f0f40
adds changeset
mperrotti Oct 12, 2023
749e57a
Merge branch 'main' into mp/inactive-button
mperrotti Oct 12, 2023
16f34a0
test(vrt): update snapshots
mperrotti Oct 12, 2023
032dc7b
Merge branch 'main' into mp/inactive-button
mperrotti Oct 12, 2023
78d638e
Merge branch 'main' into mp/inactive-button
mperrotti Oct 13, 2023
4f64d94
Merge branch 'main' into mp/inactive-button
mperrotti Oct 13, 2023
38e9cae
Update src/Button/ButtonBase.tsx
mperrotti Oct 16, 2023
a6395a9
Merge branch 'main' of github.com:primer/react into mp/inactive-button
mperrotti Nov 9, 2023
e9f368d
follow-up on resolving merge conflicts
mperrotti Nov 9, 2023
7ee2525
adds new button style for inactive buttons
mperrotti Nov 9, 2023
fd935c0
refactors inactive styles, lets disabled style override inactive style
mperrotti Nov 9, 2023
5814f73
adds docs for 'inactive' prop
mperrotti Nov 9, 2023
d17ff65
Merge branch 'main' into mp/inactive-button
mperrotti Nov 9, 2023
e76533d
Merge branch 'main' into mp/inactive-button
mperrotti Nov 13, 2023
2d40c6a
Merge branch 'main' into mp/inactive-button
mperrotti Nov 14, 2023
466b029
upgrades styled components, fixes hover and active style bugs on inac…
mperrotti Nov 14, 2023
e51226a
Merge branch 'mp/inactive-button' of github.com:primer/react into mp/…
mperrotti Nov 14, 2023
83c424b
Merge branch 'main' of github.com:primer/react into mp/inactive-button
mperrotti Nov 14, 2023
2f515f9
fix drafts/Button2 inactive implementation
mperrotti Nov 14, 2023
48d08d7
cursor style tweak, update snapshots, update package-lock.json
mperrotti Nov 14, 2023
36b2c53
test(vrt): update snapshots
mperrotti Nov 14, 2023
7820947
Merge branch 'main' of github.com:primer/react into mp/inactive-button
mperrotti Nov 16, 2023
1f04313
upgrades @primer/primitives
mperrotti Nov 16, 2023
ab5cc5d
Merge branch 'mp/inactive-button' of github.com:primer/react into mp/…
mperrotti Nov 16, 2023
63928f5
Merge branch 'main' into mp/inactive-button
mperrotti Nov 20, 2023
772d196
Merge branch 'main' into mp/inactive-button
mperrotti Nov 21, 2023
c019d0e
test next primitives release
mperrotti Nov 21, 2023
d48a3e2
upgrades @primer/primitives to 7.15.3
mperrotti Nov 21, 2023
bfa9133
updates jest snaps
mperrotti Nov 21, 2023
7c0acc2
test(vrt): update snapshots
mperrotti Nov 21, 2023
80a85da
Merge branch 'main' into mp/inactive-button
mperrotti Nov 22, 2023
5c9ab5a
Merge branch 'main' into mp/inactive-button
ericwbailey Nov 27, 2023
2758520
Merge branch 'main' of github.com:primer/react into mp/inactive-button
mperrotti Nov 27, 2023
5e4cba9
Merge branch 'mp/inactive-button' of github.com:primer/react into mp/…
mperrotti Nov 27, 2023
5650687
Merge branch 'main' into mp/inactive-button
mperrotti Nov 28, 2023
d4117fa
Merge branch 'main' into mp/inactive-button
mperrotti Nov 29, 2023
6ad028f
Add stories
pksjce Nov 30, 2023
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
7 changes: 7 additions & 0 deletions .changeset/soft-pans-punch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@primer/react': minor
---

Adds an 'inactive' state to buttons. An inactive button looks disabled and has aria-disabled, but it can still be clicked and focused. This was added to support buttons that are broken due to availability issues, but can't be removed from the page.

<!-- Changed components: Button, Button2, IconButton -->
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions e2e/components/Button.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,40 @@ test.describe('Button', () => {
}
})

test.describe('Inactive', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-button-features--inactive',
globals: {
colorScheme: theme,
},
})

// Default state
expect(await page.screenshot()).toMatchSnapshot(`Button.Inactive.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-button-features--inactive',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations({
rules: {
'color-contrast': {
enabled: theme !== 'dark_dimmed',
},
},
})
})
})
}
})

test.describe('Dev: Invisible Variants', () => {
for (const theme of themes) {
test.describe(theme, () => {
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
"@oddbird/popover-polyfill": "^0.3.1",
"@primer/behaviors": "^1.5.1",
"@primer/octicons-react": "^19.8.0",
"@primer/primitives": "^7.11.11",
"@primer/primitives": "7.15.3",
"@react-aria/ssr": "^3.5.0",
"@styled-system/css": "^5.1.5",
"@styled-system/props": "^5.1.5",
Expand Down
5 changes: 5 additions & 0 deletions src/Button/Button.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
"type": "React.ElementType",
"description": "A visual to display after the button text."
},
{
"name": "inactive",
"type": "boolean",
"description": "Whether the button looks visually disabled, but can still accept all the same interactions as an enabled button.\n This is intended to be used when a system error such as an outage prevents the button from performing its usual action.\n Inactive styles are slightly different from disabled styles because inactive buttons need to have an accessible color contrast ratio. This is because inactive buttons can have tooltips or perform an action such as opening a dialog explaining why it's inactive.\n If both `disabled` and `inactive` are true, `disabled` takes precedence."
},
{
"name": "as",
"type": "React.ElementType",
Expand Down
55 changes: 55 additions & 0 deletions src/Button/Button.features.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {EyeIcon, TriangleDownIcon, HeartIcon} from '@primer/octicons-react'
import React, {useState} from 'react'
import {Button} from '.'
import {Tooltip} from '../drafts'
import {ToggleSwitch, Text, Box, Dialog} from '../'

export default {
title: 'Components/Button/Features',
Expand Down Expand Up @@ -63,8 +65,61 @@ export const Block = () => <Button block>Default</Button>

export const Disabled = () => <Button disabled>Default</Button>

export const Inactive = () => (
<Button variant="primary" inactive>
Default
</Button>
)

export const Small = () => <Button size="small">Default</Button>

export const Medium = () => <Button size="medium">Default</Button>

export const Large = () => <Button size="large">Default</Button>

const InactiveButtonHover = () => <Button inactive>Hover over me during outage</Button>

export const InactiveButtonWithTooltip = () => {
const [isOn, setIsOn] = React.useState(false)
const onClick = React.useCallback(() => {
setIsOn(!isOn)
}, [setIsOn, isOn])

return (
<Box>
<Text id="toggle" fontWeight={'bold'} fontSize={2}>
Simulate outage
</Text>
<ToggleSwitch aria-labelledby="toggle" onClick={onClick} />
{isOn ? (
<Tooltip text="This button is inactive due to an outage!">
<InactiveButtonHover />
</Tooltip>
) : (
<InactiveButtonHover />
)}
</Box>
)
}

export const InactiveButtonShowsDialog = () => {
const [isOpen, setIsOpen] = React.useState(false)
const onDialogClose = React.useCallback(() => {
setIsOpen(false)
}, [setIsOpen])
const onAnchorClick = React.useCallback(() => {
setIsOpen(true)
}, [setIsOpen])
return (
<Box>
<Button inactive onClick={onAnchorClick}>
Click on me during outage
</Button>
{isOpen && (
<Dialog title="My Dialog" subtitle="This is a subtitle!" onClose={onDialogClose}>
There is an outage so you cant read whats supposed to be here
</Dialog>
)}
</Box>
)
}
6 changes: 6 additions & 0 deletions src/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ Playground.argTypes = {
type: 'boolean',
},
},
inactive: {
control: {
type: 'boolean',
},
},
variant: {
control: {
type: 'radio',
Expand All @@ -51,6 +56,7 @@ Playground.args = {
block: false,
size: 'medium',
disabled: false,
inactive: false,
variant: 'default',
alignContent: 'center',
trailingVisual: null,
Expand Down
2 changes: 2 additions & 0 deletions src/Button/ButtonBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ButtonBase = forwardRef(
size = 'medium',
alignContent = 'center',
block = false,
inactive,
...rest
} = props

Expand Down Expand Up @@ -68,6 +69,7 @@ const ButtonBase = forwardRef(
data-block={block ? 'block' : null}
data-size={size === 'small' || size === 'large' ? size : undefined}
data-no-visuals={!LeadingVisual && !TrailingVisual && !TrailingAction ? true : undefined}
data-inactive={inactive ? true : undefined}
>
{Icon ? (
<Icon />
Expand Down
5 changes: 5 additions & 0 deletions src/Button/IconButton.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
"defaultValue": "",
"description": "Changes the size of the icon button component"
},
{
"name": "inactive",
"type": "boolean",
"description": "Whether the button looks visually disabled, but can still accept all the same interactions as an enabled button."
},
{
"name": "icon",
"type": "Component",
Expand Down
6 changes: 6 additions & 0 deletions src/Button/IconButton.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ Playground.argTypes = {
type: 'boolean',
},
},
inactive: {
control: {
type: 'boolean',
},
},
variant: {
control: {
type: 'radio',
Expand All @@ -34,6 +39,7 @@ Playground.argTypes = {
Playground.args = {
size: 'medium',
disabled: false,
inactive: false,
variant: 'default',
'aria-label': 'Icon button description',
icon: XIcon,
Expand Down
Loading