Repository navigation
Conversation
The menu half was a div (Dropdown.Trigger wraps its children in one), so Tab skipped it, it had no role, and its only name was the icon's "chevron-down". Render it as a button with the Radix trigger: it is in the tab order, opens with Enter, Space or ArrowDown, is named "More options" (menuAriaLabel overrides it), and is disabled with the split button. Its focus ring is drawn inside, since the split button clips its overflow. Closes ClickHouse#1272
🦋 Changeset detectedLatest commit: d991f24 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
This branch has not been deployed
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The menu half of
SplitButtoncould only be used with a pointer (#1272).Dropdown.Triggerwraps its children in adivand slots the Radix trigger onto it, so the menu half had no role, was not in the tab order, and its only name was the icon'saria-label="chevron-down".BaseButton(type="button") passed toDropdownMenu.TriggerwithasChild, following the WAI-ARIA APG Menu Button pattern. Radix gives itaria-haspopup="menu",aria-expandedand the Enter / Space / ArrowDown handling.SplitButtonalready rendersDropdown(the Radix root), so it uses the Radix trigger directly rather than changingDropdown.Triggerfor every consumer.menuAriaLabelprop sets another name (same convention asariaLabelonCodeBlockandTabs). The chevron icon isaria-hidden.disabled, the menu half getsdisabledandaria-disabled="true"and is out of the tab order..split-buttonhasoverflow: hidden, which clipped the outside focus ring to a sliver. The menu half draws its ring inside (outline-offset: -2px) with an inner ring in--click-global-color-background-default, because in the dark theme the outline color is the same yellow as the primary button.Links and tickets
Closes #1272
Good to know
mainand from this branch and compared screenshots of the Primary, Secondary, both Disabled, PrimaryWithIcon and FillWidth stories in the same browser; they are pixel-identical. The focus snapshot intests/buttons/splitbutton.spec.tsfocuses the first button (the main half), which this does not change. I did not run the Docker visual tests.overflow: hidden. I left it as it is to keep this PR to the menu half and the existing focus snapshot unchanged; happy to follow up.yarn testlocally has 9 failures inIcon,TextTruncateandInitCUIThemeScript; the same 9 fail onmainwith my Node 26 (CI uses Node 24). All SplitButton tests pass.Checklist
Contribution
buildandbuild-storybookwork locallymain), aFocusVisiblestory and aKeyboardNavigationstory with aplayfunction.Accessibility
disabled, Tab skips both halves.menuAriaLabel); the icon isaria-hidden.Checked: WCAG 2.2 2.1.1 Keyboard, 2.4.3 Focus Order, 2.4.7 Focus Visible, 2.5.8 Target Size (Minimum), 4.1.2 Name, Role, Value. axe-core (from the installed
@storybook/addon-a11ydependency) reports 0 violations on the Primary, Secondary, PrimaryDisabled, PrimaryWithIcon and FocusVisible stories. Not tested: screen readers.Screenshots
Keyboard focus on the menu half, light and dark, primary and secondary: the ring is inside the menu half; before this change the menu half could not receive keyboard focus. Unfocused states are pixel-identical to
main.Note
Low Risk
Scoped a11y and trigger implementation change on
SplitButtonwith an optional prop and no breaking API; only behavioral change is improved keyboard/focus handling and a visible focus ring on the menu half.Overview
Makes the menu (chevron) half of
SplitButtona real, keyboard-focusable menu button instead of a pointer-only trigger, closing the accessibility gap whereDropdown.Triggerwrapped a non-focusablediv.The secondary control is now a
BaseButtonwired through RadixDropdownMenu.Trigger(asChild), so Tab order is main action → menu button, Enter / Space / ArrowDown open the menu, and assistive tech getsaria-haspopup="menu",aria-expanded, and the default name "More options" (overridable via newmenuAriaLabel). The chevron isaria-hidden; whendisabled, the menu half is disabled and skipped in the tab order.:focus-visiblestyling adds an inset focus ring on the menu half so it stays visible inside the clippedoverflow: hiddencontainer.Adds unit tests, a
FocusVisiblestory, and aKeyboardNavigationstory with a play function. Unfocused appearance is unchanged aside from the menu-half focus ring.Reviewed by Cursor Bugbot for commit d991f24. Bugbot is set up for automated code reviews on this repo. Configure here.