Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds 'inactive' state to buttons #3812

Merged
merged 46 commits into from
Dec 5, 2023
Merged

Adds 'inactive' state to buttons #3812

merged 46 commits into from
Dec 5, 2023

Conversation

mperrotti
Copy link
Contributor

@mperrotti mperrotti commented Oct 12, 2023

Relates to https://github.com/github/primer/issues/2676

This came from the work we did on graceful degradation patterns: https://primer.style/design/ui-patterns/degraded-experiences#indicating-a-button-is-non-functional-without-disabling-it

Mock of inactive button states

Changelog

New

Adds inactive prop to buttons

Changed

No changes

Removed

No removals

Rollout strategy

  • Patch release
  • Minor release
  • Major release; if selected, include a written rollout or migration plan

Testing & Reviewing

Just confirm that the "inactive" button visually looks the same as a "disabled" button.

I've already reviewed this with a11y designers.

Merge checklist

  • Added/updated tests
  • Added/updated documentation
  • Added/updated previews (Storybook)
  • Changes are SSR compatible
  • Tested in Chrome
  • Tested in Firefox
  • Tested in Safari
  • Tested in Edge

Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

@mperrotti mperrotti requested review from a team and siddharthkp October 12, 2023 17:30
@changeset-bot
Copy link

changeset-bot bot commented Oct 12, 2023

🦋 Changeset detected

Latest commit: cdfaebe

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/react Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Oct 12, 2023

size-limit report 📦

Path Size
dist/browser.esm.js 104.33 KB (+0.1% 🔺)
dist/browser.umd.js 104.85 KB (+0.1% 🔺)

@primer primer bot temporarily deployed to github-pages October 12, 2023 17:56 Inactive
@github-actions github-actions bot temporarily deployed to storybook-preview-3812 October 12, 2023 17:56 Inactive
@@ -21,6 +21,7 @@ const ButtonBase = forwardRef(
size = 'medium',
alignContent = 'center',
block = false,
inactive,
Copy link
Contributor

Choose a reason for hiding this comment

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

Curious, what if we just continue to use disabled as a prop but change it to use aria-disabled instead of disabled across the board?

Is this primarily used for the loading state? So it looked disabled but it can be focused.. can it also still be clicked and follow through with the on click action?

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 think there are still rare cases where we want a real disabled button.

The loading state is one way we can use this pattern, but it's mostly to support "degraded" buttons: https://primer.style/design/ui-patterns/degraded-experiences#indicating-a-button-is-non-functional-without-disabling-it

Copy link
Member

Choose a reason for hiding this comment

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

Curious, what if we just continue to use disabled as a prop but change it to use aria-disabled instead of disabled across the board?

I like the general idea of that, but it should come with handling click events with a useful message, which I'm not confident would happen :(

I think there are still rare cases where we want a real disabled button.

Also fair!

@mperrotti mperrotti temporarily deployed to github-pages October 12, 2023 18:29 — with GitHub Actions Inactive
@github-actions github-actions bot temporarily deployed to storybook-preview-3812 October 12, 2023 18:29 Inactive
@mperrotti
Copy link
Contributor Author

The a11y tests are failing because the inactive button doesn't meet the contrast requirements.

However, I don't think this needs to meet the contrast requirements because it's treated like a disabled control. Is there a way to explicitly skip the color contrast check for this test?

@mperrotti mperrotti temporarily deployed to github-pages October 13, 2023 15:04 — with GitHub Actions Inactive
@github-actions github-actions bot temporarily deployed to storybook-preview-3812 October 13, 2023 15:04 Inactive
@joshblack
Copy link
Member

@mperrotti if we're intending for inactive buttons to convey information/receive interactions, would it fall under this scenario for color contrast even if it's considered disabled? https://github.com/github/primer/discussions/652#discussioncomment-7084814

Also wanted to ask, if it's still allowing for interaction is aria-disabled appropriate? If I understand right, aria-disabled="true" would indicate that the control is not operable

@mperrotti
Copy link
Contributor Author

@joshblack - when I brought this idea to the a11y team last quarter, they recommended aria-disabled. The experience would be pretty much the same for AT and keyboard users - the main difference being the aria-disabled attribute.

I double-checked my approach with @ericwbailey this afternoon, and he thinks it's ok if "inactive" buttons don't meet the contrast minimum as long as there's some other indication on the page (such as a global banner) that informs the users that things are broken.

Also, I'm not sure if this falls into the same category as the loading state button because the button itself isn't conveying any information. If somebody with low vision hits a submit button and it "disappears" for them when it goes into the loading state, they might think they broke something.

Copy link
Collaborator

@pksjce pksjce left a comment

Choose a reason for hiding this comment

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

aria-disabled can itself be a state or it can have value true/false. If we choose to add the value, then we must use style selectors that include the value. If we choose to remove the attribute when not inactive, then the current style selectors will suffice.

This can be seen in the storybooks esp Playground where all variants of the Button are inactive.

src/Button/ButtonBase.tsx Outdated Show resolved Hide resolved
@@ -7,15 +7,15 @@ export const getVariantStyles = (variant: VariantType = 'default', theme?: Theme
color: 'btn.text',
backgroundColor: 'btn.bg',
boxShadow: `${theme?.shadows.btn.shadow}, ${theme?.shadows.btn.insetShadow}`,
'&:hover:not([disabled])': {
'&:hover:not([disabled]):not([aria-disabled])': {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Or these selectors should be [aria-disabled="true"]?

@mperrotti
Copy link
Contributor Author

aria-disabled were leftover from an earlier iteration of the design, but now I've removed them.

@mperrotti mperrotti added this pull request to the merge queue Dec 5, 2023
Merged via the queue into main with commit 3f82a1c Dec 5, 2023
29 checks passed
@mperrotti mperrotti deleted the mp/inactive-button branch December 5, 2023 18:58
@primer primer bot mentioned this pull request Dec 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants