Repository navigation
CORE-2901: Add an indeterminate state to Checkbox - #163
Merged
Merged
Conversation
RoyEJohnson
force-pushed
the
CORE-2901-checkbox-indeterminate
branch
from
October 2, 2026 13:34
39997cf to
97696d8
Compare
This was referenced Oct 5, 2026
RoyEJohnson
force-pushed
the
CORE-2901-checkbox-indeterminate
branch
from
October 6, 2026 20:17
5f54987 to
d6de68a
Compare
A checkbox that summarises a set of others had no way to report that only some of them are chosen, so assistive tech announced a fully checked box when it was not. Checkbox takes an `indeterminate` prop that sets the input's `indeterminate` property, which browsers expose as the mixed state, and draws a dash in place of the checkmark for each variant. The property is reapplied after every render because the browser clears it on click. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The browser clears `indeterminate` when a checkbox is clicked, and the effect that reapplies it only runs on a render. A mixed Checkbox whose click did not cause a render, such as one with no state behind it, stopped being exposed as mixed even though the prop was still true. While the box is mixed, onClick now puts the property back after the caller's own handler has run. When the parent clears the prop in response to the click, the render that follows still applies it. The Indeterminate story now covers every variant at every size. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The version bump was made with `npm install`, which dropped the `libc` constraints from the six @swc/core-linux-* packages. With them, npm on Linux x64 glibc skips the musl binary; without them it installs both. The lockfile now matches main apart from the two version lines, which `npm version 1.26.0 --no-git-tag-version` changes on its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RoyEJohnson
force-pushed
the
CORE-2901-checkbox-indeterminate
branch
from
October 7, 2026 17:26
d1f7b6c to
48e041f
Compare
RoyEJohnson
marked this pull request as ready for review
October 7, 2026 17:27
Dantemss
approved these changes
Oct 7, 2026
| const inputRef = useRef<HTMLInputElement>(null); | ||
|
|
||
| // `indeterminate` is a DOM property with no attribute, so it is applied after every render. | ||
| useEffect(() => { |
Member
There was a problem hiding this comment.
Apparently this might have to be a useLayoutEffect to prevent the checkbox state flashing.
Contributor
Author
There was a problem hiding this comment.
Done in 4eddd79. The effect is now a layout effect, so the property is set before paint. It falls back to useEffect when there is no window, because React warns about useLayoutEffect during server rendering.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Dantemss
approved these changes
Oct 8, 2026
This branch was successfully 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.
Jira: CORE-2901
This is the first of several small PRs for CORE-2901; the plan is on the ticket. It adds the
Checkboxpiece that the Assignable fix needs. Nothing in assignments changes here.Why
A checkbox that summarises a set of others, like a group's checkbox above its items, can only
be checked or unchecked. When some items are chosen and some are not, assistive tech announces
a fully checked box (WCAG 4.1.2, Name, Role, Value). assignments'
ActivityGrouphas thisproblem: its checkbox is checked as soon as any one item is selected.
What changes
Checkboxtakes a newindeterminateprop.indeterminateproperty, which browsers expose as the "mixed" state.There is no
aria-checkedto keep in sync.--checkbox-indeterminate-bgand--checkbox-indeterminate-iconvariables thatTreeCheckboxalready sets, and the existing dash icon.checked. The parent decides what a click on a mixed box does;selecting everything is what a native checkbox does.
is clicked. The prop stays the source of truth.
The variables are only set when
indeterminateis true, so no existing snapshot changes.Tests
New tests in
Checkbox.spec.tsxcheck that:indeterminateleavescheckedalone,Making the effect run only when the prop changes fails the click test, and removing the dash
variable fails the variant tests. There are also two new stories:
Indeterminatefor everyvariant and size, and
ParentOfOptions, a parent that is mixed while only some options arechosen.
I checked both stories in Chrome. The dash looks right for each variant and size. In
ParentOfOptions, clicking the mixed parent selects all, clicking it again clears all, andpicking one option returns it to mixed.
Before merging
package.jsonis at 1.24.3. This is a new prop, so a minor release.CORE-2871: Make the TooltipGroup trigger a button that does something #161 and CORE-2875: Stop rendering menu popovers as dialogs #162 also bump to 1.25.0, so whichever of the three merges later needs a new number.
Next
The assignments PR that uses this (
ActivityGroupshowing the mixed state) needs a releasethat includes this change.
🤖 Generated with Claude Code