Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report📚 Storybook Preview🧪 Sandbox PreviewComponent Size
Sizes are gzip. Import counts the JavaScript the import loads eagerly; CSS counts the package stylesheet rules referenced by the modules it can load from its own package, lazily loaded ones included. Bundle Size SummaryGzip figures measure each package's entry file, not the code an import pulls in.
Accessibility AuditStatus: No accessibility violations detected. Visual Regression55 of 502 shot(s) changed. A change here is a question, not a failure: check whether the after is the
and 35 more. Generated by PR Enrichment workflow | Storybook | Sandbox | View full report |
There was a problem hiding this comment.
Thanks for the tile form for menu radios; it can't be approved yet because FR24 and DEC-16 are new requirements in the draft component:DropdownMenu record, so an engineering owner needs to approve or amend them, including the no-target intentional: theming entry and ArrowLeft/ArrowRight keeping their sub-menu meanings inside a grid. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and as an engineering owner the author may do so. Whatever that decision, two fixes are needed:
- The cell's focus ring follows the browser's
:focus-visible, so after a mouse open, hovering a cell paints the keyboard ring, which in the default theme looks the same as the checked border; draw it only under keyboard modality, as the menu surfaces do (DropdownMenuRadioItem.tsx:261). children != nullturns afalseor''child into an empty cell that can still be focused and selected;isRenderable(children)avoids it (DropdownMenuRadioItem.tsx:238).
[Automated review]
66e41bb to
7ce5ad9
Compare
There was a problem hiding this comment.
Thanks for the tile form of DropdownMenuRadioItem; both earlier findings are fixed on this head, but it can't be approved yet because FR9, AR5 and DEC-1 are new requirements in the draft component:DropdownMenuRadioItem record, together with the intentional: no-target "Radio cell" entry in component:DropdownMenu. An engineering owner needs to approve or amend them (the cell with no radio mark named by its label, the reserved 2px accent border, the keyboard-only ring, and arrow keys in DOM order with ArrowLeft and ArrowRight keeping their sub-menu meanings) by commenting /approve-spec <full head SHA> on this pull request, and as an engineering owner the author may do so. Whatever that decision, one fix is needed:
isRenderable(children)is shallow, so children that render nothing through an array ({a && <A />}{b && <B />}with both false, or an empty.map()) still make an invisible cell that keyboard focus lands on and Enter selects; checkChildren.toArray(children).some(isRenderable)or narrow the documented rule (DropdownMenuRadioItem.tsx:276).
[Automated review]
|
|
||
| // Children that render make the option a cell; `false`, `''` and the like | ||
| // leave it a row. | ||
| if (isRenderable(children)) { |
There was a problem hiding this comment.
isRenderable is shallow, so children that render nothing through an array still make a cell: {a && <A />}{b && <B />} with both false, an empty .map() or [false] each render an 8px cell holding only the hidden label, which ArrowDown lands on and Enter selects. The docs and FR9 promise that children that render nothing leave the row. Children.toArray(children).some(isRenderable) drops empty nodes inside arrays; a fragment or a component returning null still can't be detected, so the docs should say so.
7ce5ad9 to
3db817d
Compare
There was a problem hiding this comment.
Thanks for the tile form of DropdownMenuRadioItem; it can't be approved yet because FR9, AR5 and DEC-1 are new requirements in the draft component:DropdownMenuRadioItem record, together with the intentional: no-target "Radio cell" entry in component:DropdownMenu, and no engineering owner has approved them on this revision. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and as an engineering owner the author may do so. Whatever that decision, two fixes are needed:
isRenderable(children)is shallow, so children that render nothing through an array ({a && <A />}{b && <B />}with both false, or an empty.map()) still make an invisible 8px cell that the arrow keys land on and Enter selects; checkChildren.toArray(children).some(isRenderable)and say in FR9 and the docs that a fragment or a component returningnullstill makes a cell (DropdownMenuRadioItem.tsx:276).- AR5 says focus a pointer moved there paints no ring, but after a key press the ring follows mouse-moved focus, as
architecture:interaction-modalityINV1 requires, so narrow AR5 to focus moved after pointer input, as DEC-1 already words it (DropdownMenuRadioItem.spec.md:192-194).
[Automated review]
| colors. The shared focus ring paints outside it only for focus the keyboard | ||
| moved there; focus a pointer moved there paints none, the browser's ring | ||
| included (`architecture:interaction-modality` INV1). |
There was a problem hiding this comment.
After a key press, hover moves focus with the last input, so a cell the mouse moves to keeps the ring (:focus-visible matches, outline solid in Chromium), as architecture:interaction-modality INV1 requires ("after keyboard input it does"). "Focus a pointer moved there paints none" is only true after a pointer press; DEC-1 already says "after a pointer open". Narrowing this sentence to focus moved after pointer input keeps AR5 consistent with INV1 and with the code.
3db817d to
97057c8
Compare
There was a problem hiding this comment.
Thanks for the tile form of DropdownMenuRadioItem; it can't be approved yet because FR9, AR5 and DEC-1 are new requirements in the draft component:DropdownMenuRadioItem record, together with the relaxed PR1, the row-scoped FR6, FR7 and AR1, and the intentional: "Radio cell" entry in component:DropdownMenu, and no engineering owner has approved them on this revision. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and as an engineering owner the author may do so. Whatever that decision, two fixes are needed:
isRenderable(children)is shallow, so children that render nothing through an array ({a && <A />}{b && <B />}with both false, or an empty.map()) still make an empty 8px cell that the arrow keys focus and Enter selects;Children.toArray(children).some(isRenderable)and a test for those shapes would match FR9 and the docs.- AR5 says focus a pointer moved there paints no ring, but after a key press the ring correctly shows on the cell the mouse moves to, as
architecture:interaction-modalityINV1 requires and the code does; AR5 and the component docblock should say "after pointer input", as DEC-1 already does.
[Automated review]
A one-of choice drawn as tiles in a menu (colour swatches, icons, numbered slots) had no Astryx form: DropdownMenuRadioItem always draws a full-width row with a radio mark, and its group context is not exported, so a caller's tile could not join the selection. Given children that render, the item now draws them as a cell instead of its row: one menuitemradio element with aria-checked, no radio mark and no row slots, named by its label through a visually hidden element it references with aria-labelledby, so the name stays the label when the tile shows text of its own. Children that render nothing (false, '') leave the row. The checked cell carries a 2px accent border that every cell reserves (transparent when unchecked; Highlight against Canvas under forced colors, which drop shadows). The shared focus ring paints outside it only for focus the keyboard moved there: focus the menu moves to the cell under the mouse after a pointer open paints none, not even the browser's ring, as the menu surfaces gate theirs on the last input. Cells keep the row's selection, close policy, handler order (caller onClick and onPointerMove run after the row's own), hover focus, press model, DOM-order arrow keys and typeahead; the caller lays them out with a grid on the group or on a wrapper inside it. icon, description and endContent are not shown in a cell and warn in development there. The cell is its own internal component, so the row keeps no state or Effect. ContextMenuRadioItem and BreadcrumbMenuRadioItem are the same component. Proposed FR9, AR5 and DEC-1 of component:DropdownMenuRadioItem record it, with a Presentation concept, a Cell state and design row, and the record's row-only facts (FR6, FR7, PR1, AR1) scoped to rows; component:DropdownMenu, which owns the target inventory, lists the Radio cell anatomy part with no target. A RadioCells story and a Chromium spec check the names in Chromium's accessibility tree, the accent and forced-colors paint, no ring for a cell hovered after a pointer open and the ring after ArrowDown, the arrow keys and Enter, and axe on the menu and on a sub-menu whose tiles sit in a wrapper grid; jsdom cases cover drawing, non-rendering children, selection, keys, typeahead, the keyboard-only ring, a wrapper, a disabled cell and the warning.
97057c8 to
582007e
Compare
There was a problem hiding this comment.
Thanks for the tile form of DropdownMenuRadioItem; it can't be approved yet because FR9, AR5 and DEC-1 are new requirements in the draft component:DropdownMenuRadioItem record, together with the relaxed PR1, the row-scoped FR6, FR7 and AR1, and the intentional: "Radio cell" entry in component:DropdownMenu, and no engineering owner has approved them on this revision. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and as an engineering owner the author may do so. Whatever that decision, these need fixing:
isRenderable(children)is shallow, so children that render nothing through an array ({a && <A />}{b && <B />}with both false, or an empty.map()) still make an empty 8px cell that the arrow keys focus and Enter selects;Children.toArray(children).some(isRenderable)with a test for those shapes, and docs that say a fragment or a component returningnullstill makes a cell, would match FR9.- AR5 says focus a pointer moved there paints no ring, but after a key press the ring correctly shows on the cell the mouse moves to, as
architecture:interaction-modalityINV1 requires and the code does; AR5, its verification row and the component docblock should say "after pointer input", as DEC-1 does. - Under forced colors the story's swatches disappear (each is a background colour and an unchecked cell's border is
Canvas), leaving only the checked and focused cells visible;forcedColorAdjust: 'none'on the swatch and a docs note for background-colour tiles would fix the example.
[Automated review]
| borderRadius: '50%', | ||
| }, | ||
| swatchColor: (color: string) => ({ | ||
| backgroundColor: color, |
There was a problem hiding this comment.
Under forced colors this background is replaced, and an unchecked cell's border is Canvas, so every unchecked swatch disappears: in Chromium with forced-colors emulation only the checked cell's Highlight border and the focused cell's ring are visible. forcedColorAdjust: 'none' here keeps the swatch colours, and a docs line could tell callers that a tile drawn as a background colour needs it.
There was a problem hiding this comment.
In 0e93926 the story's swatches take forcedColorAdjust: 'none', the children docs tell callers that a tile drawn as a background colour needs it, and the forced-colors Chromium case checks that an unchecked swatch keeps its colour (it reads white Canvas on the previous story).
…ve a row, AR5 says after pointer input, and the story's swatches keep their colour under forced colors Three points from the review on 582007e. isRenderable(children) was shallow, so an array that renders nothing ({a && <A />}{b && <B />} with both false, or an empty .map()) made an empty cell the arrow keys reached; a local rendersContent now counts an array only through an item that renders (React.Children is banned by no-react-introspection, so it walks the array itself), and an element always counts. The row case gains both array shapes (it fails on the previous head), a new case pins that a fragment or a component returning null is still a cell, and the docs (en, zh, dense) say so. AR5, its verification row, the docblock and the RadioCell comment now say focus after keyboard input paints the ring, also where the mouse then moves it, and focus after pointer input none; the keyboard-ring case adds that hover-moved step. The story's background-colour swatches take forcedColorAdjust: 'none', the children docs tell callers so, and the Chromium forced-colors case checks a swatch keeps its colour (white Canvas without it).
There was a problem hiding this comment.
Thanks for the tile form of DropdownMenuRadioItem; the three fixes from the last round hold on this revision and no code change is needed. Approval now waits only on the spec decision: FR9, AR5 and DEC-1 are new requirements in the draft component:DropdownMenuRadioItem record, together with the relaxed PR1, the row-scoped FR6, FR7 and AR1, and the intentional: "Radio cell" entry in component:DropdownMenu, and an engineering owner needs to approve or amend them. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and as an engineering owner the author may do so.
[Automated review]
|
Posted by Cindy's agent on her behalf: closed and reopened only to restart this PR's CI on the current workflow after tonight's queue-wide cancel; nothing in the PR changed. |
|
I'm pausing this work for now to reduce contention on the repo. Thank you for the reviews and the spec guidance. |
User need
What led to it: this comes from moving every menu and picker in our app onto Astryx, which began with a press, slide and lift bug in its phone menus. Some of those menus set one choice from tiles, such as a colour from swatches.
Why:
DropdownMenuRadioItemonly draws a row with a radio mark, and its group context isn't exported, so an app that wants tiles rebuilds the radio item itself: roles, focus and painting.Problem and solution fit
Given children,
DropdownMenuRadioItemdraws them as a cell instead of its row: no radio mark, named bylabel, with a 2px accent border when checked; only keyboard focus shows a ring. Selection, arrows and typeahead work as for rows. Two-dimensional arrows and data-modeitemsare out of scope.Current specification
component:DropdownMenuRadioItemis a draft. This PR proposes a Presentation concept, FR9, AR5 and DEC-1, pending owner review, and scopes FR6, FR7, PR1 and AR1 to rows. #7319 also amends FR6.Public delta and caller burden
children; without them nothing changes. The caller draws, names (label) and lays out the cells.Design and alternatives
Evidence
New cases in
DropdownMenuRadioCell.test.tsxfail onmainand pass here;RadioCell.a11y.chromium.spec.tschecks names, checked state, the border, the focus-ring rules, forced colors and axe in Chromium.Writing rubric results
R1 narration: FR9, AR5, DEC-1 and the new rows are present tense.
R2 research: none.
R3 evidence: FR9 cites DEC-1; its verification row names the tests.
R4 rejected alternatives: two
Rejected:lines in DEC-1.R5 change references: none.
R6 open questions: none.
Scope
Testing
In Storybook, open Core/DropdownMenu → Radio Cells and open "Customize".