Skip to content

feat(core): a checkbox and a radio option reach a 44 pt target under a finger without growing - #8241

Draft
vjeux wants to merge 1788 commits into
meta:mainfrom
vjeux:uikit/c06-touch-targets
Draft

vjeux wants to merge 1788 commits into
meta:mainfrom
vjeux:uikit/c06-touch-targets

Conversation

@vjeux

@vjeux vjeux commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Depends on #8085. Review only this PR's change: vjeux/astryx@ecc8779...49c8e40. Implements spec:AST-094 FR42 (decision) and List FR10 (#8571) for the maintainers' target size decision.

User need

On a phone, a standalone CheckboxInput's target is its 24 px row, and RadioList rows are 24 px with 8 px dead strips; iOS controls are 44 × 44 pt, so fingers miss.

Why: targets are the drawn sizes, and the look must not grow (FR42).

Evidence

iOS 26.2 Mobile Safari: a tap 5 px above a CheckboxInput's 24 px box toggled it, and a tap 2 px above the second RadioList row, in its half of the 8 px gap, selected that row. Page-measured: rows stay 24 px; the hit areas reach 10 px past the outer edges and 4 px into each gap. At rest nothing moved:

A CheckboxInput and a RadioList at rest in iOS Safari under a finger, at their drawn sizes

Problem and solution fit

Under a coarse pointer each control keeps its size and takes #8085's shared invisible hit area: it grows toward the new --size-touch-target (44 px, never lower) and stops at half the gap to each neighbour, so targets never overlap; a middle RadioList option reaches 32 px.

Current specification

  • spec:AST-094 FR42: no size increase for touch in the default look; 44 px through an invisible hit area clamped to half the gap.
  • List FR10: every ListItem row gets that hit area.
  • Maintainer decision: touch only; standalone CheckboxInput, RadioList and CheckboxList; Markdown task items keep their pitch; a theme metric; hit area over look.

Public delta and caller burden

New theme token --size-touch-target (44px). Coarse pointer only; nothing changes size, and a mouse sees no change.

Touch-only JavaScript (INV6): CheckboxInput's import grows 2,943 B gzip and RadioListItem's 2,986 B, all in the shared hit-area modules (utils/hitArea, utils/touchHitArea, utils/touchQueries) that List rows already import, so a page carries them once however many controls use them; ListItem's grows 356 B for the shared token read.

  • Size: base → head per component in this pull request's CI Component Size report (analyze-pr.js).

Design and alternatives

Scope

  • One capability is added.
  • Unrelated fixes, cleanup, and policy changes were removed or split.
  • Consumer docs, focused tests, and migration evidence ship with the feature.
  • Public text and artifacts contain no internal Meta context.

Testing

@vercel

vercel Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Oct 29, 2026 9:24pm UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 24, 2026
@astracat-bot

astracat-bot Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟡 Reviewed (for maintainers only) Oct 29, 2026, 9:48 PM UTC

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

Preview availability: Storybook and Sandbox are not both ready on the exact-head Vercel preview.

Modified Components

CheckboxInput (@astryxdesign/core)
Metric Before After Delta
Entry File (ESM) 478B 478B 0B
Lines of Code 355 384 -
Complexity Very High Very High (50) -
Item (@astryxdesign/core)
Metric Before After Delta
Entry File (ESM) 284B 284B 0B
Lines of Code 1372 1402 -
Complexity Very High Very High (131) -
TreeList (@astryxdesign/core)
Metric Before After Delta
Entry File (ESM) 648B 648B 0B
Lines of Code 872 878 -
Complexity Very High Very High (100) -

Component Size

Component Import before Import after Delta CSS before CSS after Delta
core/AlertDialog 56.9KB 57.2KB +293B 12.4KB 12.5KB +36B
core/AppShell 57.9KB 58.1KB +244B 11.6KB 11.7KB +35B
core/AspectRatio 3.7KB 3.8KB +66B 3.5KB 3.5KB +53B
core/Avatar 37.5KB 37.5KB +54B 6.3KB 6.3KB +35B
core/AvatarGroup 39.8KB 39.8KB +50B 6.4KB 6.5KB +35B
core/AvatarGroupOverflow 39.9KB 40.2KB +304B 6.4KB 6.4KB +36B
core/AvatarStatusDot 7.1KB 7.1KB +61B 3.4KB 3.5KB +53B
core/Badge 3.9KB 4.0KB +64B 3.8KB 3.9KB +52B
core/Banner 47.8KB 48.1KB +294B 9.9KB 10.0KB +35B
core/BaseTypeahead 54.3KB 54.6KB +252B 9.9KB 9.9KB +35B
core/Blockquote 3.5KB 3.6KB +66B 3.4KB 3.4KB +52B
core/BottomSheet 34.0KB 34.0KB +69B 7.9KB 7.9KB +35B
core/BottomSheetSwitcher 14.8KB 14.8KB +67B 3.3KB 3.3KB +54B
core/BreadcrumbItem 66.4KB 67.2KB +882B 11.0KB 11.4KB +423B
core/Breadcrumbs 22.4KB 22.5KB +71B 3.3KB 3.3KB +53B
core/Button 43.3KB 43.6KB +282B 9.2KB 9.2KB +34B
core/ButtonGroup 8.4KB 8.5KB +67B 3.3KB 3.3KB +52B
core/Calendar 54.9KB 55.2KB +296B 10.0KB 10.0KB +35B
core/Card 6.4KB 6.5KB +66B 6.3KB 6.4KB +57B
core/Carousel 50.2KB 50.5KB +284B 10.2KB 10.2KB +34B
core/Center 4.2KB 4.2KB +63B 4.6KB 4.6KB +56B
core/ChatComposer 60.6KB 60.9KB +274B 10.8KB 10.9KB +33B
core/ChatComposerDrawer 23.9KB 23.9KB +66B 4.5KB 4.6KB +52B
core/ChatComposerInput 55.7KB 56.0KB +265B 10.1KB 10.1KB +35B
core/ChatComposerTokenElement 55.7KB 56.0KB +265B 10.1KB 10.1KB +35B
core/ChatDictationButton 46.5KB 46.8KB +273B 9.5KB 9.5KB +33B
core/ChatLayout 48.8KB 49.1KB +277B 9.9KB 10.0KB +33B
core/ChatLayoutScrollButton 46.4KB 46.6KB +259B 9.6KB 9.6KB +33B
core/ChatMessage 23.1KB 23.1KB +59B 3.5KB 3.6KB +52B
core/ChatMessageBubble 7.0KB 7.1KB +65B 3.6KB 3.6KB +55B
core/ChatMessageList 28.9KB 29.0KB +71B 7.8KB 7.8KB +34B
core/ChatMessageMetadata 25.8KB 25.9KB +60B 3.9KB 3.9KB +36B
core/ChatSendButton 45.8KB 46.1KB +283B 9.2KB 9.2KB +34B
core/ChatSystemMessage 6.7KB 6.8KB +71B 3.7KB 3.7KB +51B
core/ChatTokenizedText 6.9KB 7.0KB +63B 3.9KB 3.9KB +53B
core/ChatToolCalls 31.9KB 31.9KB +65B 8.9KB 8.9KB +35B
core/CheckIndicator 9.0KB 9.1KB +68B 3.6KB 3.6KB +52B
core/CheckboxIndicator 4.1KB 4.1KB +65B 3.8KB 3.8KB +34B
core/CheckboxInput 49.9KB 53.1KB +3.2KB ⚠️ 9.3KB 9.5KB +243B
core/CheckboxList 46.0KB 46.1KB +63B 8.1KB 8.2KB +35B
core/CheckboxListItem 54.0KB 57.9KB +3.9KB ⚠️ 10.5KB 11.2KB +763B
core/Citation 25.9KB 26.0KB +69B 4.1KB 4.2KB +54B
core/ClickableCard 12.8KB 13.1KB +315B 6.9KB 7.0KB +55B
core/Code 3.5KB 3.6KB +63B 3.4KB 3.4KB +54B
core/CodeBlock 60.5KB 60.8KB +281B 10.7KB 10.7KB +40B
core/Collapsible 11.7KB 12.0KB +287B 4.2KB 4.3KB +53B
core/CollapsibleGroup 6.4KB 6.4KB +70B 3.2KB 3.2KB +52B
core/CommandPalette 50.9KB 51.2KB +268B 11.8KB 11.9KB +36B
core/CommandPaletteEmpty 6.1KB 6.2KB +64B 3.3KB 3.4KB +55B
core/CommandPaletteFooter 23.3KB 23.3KB +68B 3.5KB 3.6KB +52B
core/CommandPaletteGroup 3.5KB 3.5KB +64B 3.3KB 3.4KB +52B
core/CommandPaletteInput 32.3KB 32.4KB +60B 8.1KB 8.2KB +34B
core/CommandPaletteItem 8.4KB 8.7KB +285B 3.5KB 3.5KB +53B
core/CommandPaletteList 22.4KB 22.5KB +65B 3.3KB 3.3KB +54B
core/ComplexSelector 55.8KB 56.1KB +303B 10.6KB 10.7KB +35B
core/ContextMenu 77.7KB 81.8KB +4.1KB ⚠️ 14.6KB 15.4KB +765B
core/ContextMenuItem 16.6KB 17.3KB +770B 5.2KB 5.6KB +431B
core/DateInput 99.9KB 100.1KB +212B 14.8KB 14.8KB +33B
core/DateRangeInput 69.4KB 69.6KB +267B 11.2KB 11.2KB +35B
core/DateTimeInput 110.1KB 110.3KB +227B 15.2KB 15.3KB +34B
core/Dialog 16.2KB 16.3KB +64B 7.1KB 7.1KB +36B
core/DialogHeader 48.8KB 49.1KB +282B 9.8KB 9.8KB +33B
core/Divider 6.5KB 6.5KB +64B 3.6KB 3.6KB +56B
core/Drawer 31.6KB 31.7KB +85B 8.0KB 8.1KB +34B
core/DrawerHeader 48.9KB 49.2KB +264B 11.2KB 11.3KB +35B
core/DropdownMenu 72.7KB 73.6KB +950B 14.7KB 15.5KB +774B
core/DropdownMenuCheckboxItem 16.1KB 17.0KB +887B 5.6KB 6.0KB +414B
core/DropdownMenuDivider 6.6KB 6.6KB +61B 3.6KB 3.6KB +55B
core/DropdownMenuGroup 6.1KB 6.1KB +69B 3.3KB 3.3KB +52B
core/DropdownMenuItem 15.4KB 16.3KB +877B 5.2KB 5.6KB +432B
core/DropdownMenuRadioGroup 6.0KB 6.1KB +62B 3.2KB 3.3KB +56B
core/DropdownMenuRadioItem 16.2KB 17.0KB +862B 5.6KB 6.0KB +414B
core/DropdownMenuSubMenu 58.1KB 58.9KB +849B 9.5KB 9.9KB +419B
core/EmptyState 7.7KB 7.8KB +64B 3.5KB 3.6KB +55B
core/Field 44.2KB 44.3KB +71B 8.0KB 8.0KB +35B
core/FieldLabel 39.8KB 39.8KB +56B 6.5KB 6.6KB +35B
core/FieldStatus 10.4KB 10.5KB +74B 4.2KB 4.3KB +36B
core/FileInput 54.1KB 54.4KB +265B 10.3KB 10.4KB +36B
core/FormLayout 6.3KB 6.3KB +66B 3.4KB 3.4KB +53B
core/Grid 4.3KB 4.4KB +67B 3.7KB 3.7KB +53B
core/GridSpan 3.4KB 3.5KB +63B 3.2KB 3.3KB +53B
core/HStack 7.3KB 7.3KB +62B 4.9KB 5.0KB +57B
core/Heading 9.1KB 9.2KB +64B 6.8KB 6.8KB +36B
core/HoverCard 17.2KB 17.2KB 0B 4.9KB 4.9KB +13B
core/Icon 8.8KB 8.9KB +60B 3.6KB 3.6KB +52B
core/IconButton 43.3KB 43.6KB +285B 9.2KB 9.2KB +34B
core/InputGroup 44.8KB 44.9KB +61B 8.0KB 8.1KB +35B
core/InputGroupText 6.3KB 6.4KB +66B 3.7KB 3.8KB +54B
core/Item 11.4KB 12.3KB +1004B 4.7KB 5.1KB +435B
core/Kbd 6.7KB 6.7KB +67B 3.5KB 3.5KB +53B
core/LayerProvider 63.3KB 63.6KB +303B 10.1KB 10.1KB +36B
core/Layout 8.1KB 8.2KB +65B 5.5KB 5.6KB +56B
core/LayoutContent 7.4KB 7.5KB +66B 4.9KB 5.0KB +56B
core/LayoutFooter 7.3KB 7.4KB +68B 4.8KB 4.9KB +54B
core/LayoutHeader 7.4KB 7.4KB +65B 4.8KB 4.9KB +55B
core/LayoutPanel 7.6KB 7.6KB +68B 4.8KB 4.9KB +56B
core/Lightbox 51.2KB 51.4KB +263B 9.8KB 9.8KB +34B
core/Link 43.5KB 43.8KB +280B 7.6KB 7.6KB +38B
core/List 6.7KB 6.8KB +59B 3.4KB 3.5KB +52B
core/ListItem 53.5KB 57.3KB +3.9KB ⚠️ 10.5KB 11.2KB +763B
core/Markdown 144.5KB 148.5KB +4.1KB ⚠️ 17.4KB 18.1KB +765B
core/MetadataList 23.1KB 23.2KB +67B 3.6KB 3.7KB +54B
core/MetadataListItem 6.5KB 6.5KB +65B 3.4KB 3.4KB +56B
core/MobileNav 51.0KB 51.3KB +246B 10.1KB 10.1KB +34B
core/MobileNavToggle 46.2KB 46.5KB +278B 9.4KB 9.4KB +34B
core/MoreMenu 72.9KB 73.8KB +932B 14.7KB 15.5KB +774B
core/MultiSelector 76.2KB 79.6KB +3.4KB ⚠️ 14.6KB 14.9KB +236B
core/NavHeadingMenu 8.9KB 9.0KB +65B 3.2KB 3.3KB +55B
core/NavIcon 3.4KB 3.5KB +63B 3.3KB 3.3KB +55B
core/NumberInput 55.7KB 56.0KB +293B 10.7KB 10.7KB +44B
core/Outline 28.6KB 28.9KB +278B 4.0KB 4.1KB +53B
core/OverflowList 8.5KB 8.6KB +67B 3.5KB 3.6KB +53B
core/Overlay 19.5KB 19.6KB +55B 3.8KB 3.9KB +30B
core/Pagination 87.7KB 88.6KB +867B 15.3KB 15.7KB +407B
core/Popover 49.8KB 50.1KB +223B 12.1KB 12.1KB +33B
core/PowerSearch 155.1KB 155.9KB +895B 18.6KB 19.0KB +416B
core/ProgressBar 7.7KB 7.8KB +66B 6.6KB 6.6KB +32B
core/RadioIndicator 3.8KB 3.9KB +62B 3.7KB 3.7KB +33B
core/RadioList 45.6KB 45.6KB +61B 8.0KB 8.0KB +35B
core/RadioListItem 52.1KB 55.8KB +3.7KB ⚠️ 9.7KB 10.3KB +610B
core/ResizeHandle 25.1KB 25.2KB +73B 3.9KB 3.9KB +52B
core/ScrollableArea 10.4KB 10.4KB 0B 4.3KB 4.3KB +13B
core/Section 7.5KB 7.6KB +68B 6.2KB 6.2KB +56B
core/SegmentedControl 38.8KB 38.9KB +73B 6.3KB 6.4KB +35B
core/SegmentedControlItem 8.6KB 8.9KB +292B 3.9KB 3.9KB +53B
core/SelectableCard 12.8KB 13.1KB +297B 7.1KB 7.2KB +58B
core/Selector 79.1KB 80.0KB +947B 15.0KB 15.4KB +415B
core/SelectorOption 14.5KB 15.5KB +1018B 5.1KB 5.5KB +433B
core/SideNav 58.0KB 58.3KB +257B 10.6KB 10.6KB +33B
core/SideNavCollapseButton 46.6KB 46.9KB +255B 9.5KB 9.5KB +33B
core/SideNavHeading 54.7KB 55.0KB +264B 10.1KB 10.2KB +35B
core/SideNavItem 54.5KB 54.8KB +269B 10.1KB 10.1KB +35B
core/SideNavSection 6.5KB 6.6KB +59B 3.6KB 3.6KB +51B
core/Skeleton 3.8KB 3.8KB +60B 3.6KB 3.7KB +36B
core/Slider 48.5KB 48.5KB +58B 8.5KB 8.6KB +32B
core/Spinner 26.3KB 26.4KB +58B 7.5KB 7.6KB +32B
core/Stack 7.1KB 7.1KB +62B 4.9KB 5.0KB +57B
core/StackItem 6.0KB 6.1KB +63B 3.3KB 3.3KB +51B
core/StatusDot 19.0KB 19.0KB +59B 6.2KB 6.2KB +32B
core/Step 32.4KB 32.7KB +283B 5.3KB 5.4KB +35B
core/Stepper 47.4KB 47.6KB +260B 9.6KB 9.6KB +33B
core/Switch 48.4KB 48.7KB +290B 9.3KB 9.4KB +34B
core/Tab 9.7KB 10.0KB +296B 4.1KB 4.1KB +54B
core/TabList 40.2KB 40.3KB +63B 7.2KB 7.2KB +35B
core/TabMenu 51.6KB 51.9KB +253B 10.0KB 10.0KB +34B
core/Table 84.0KB 88.1KB +4.1KB ⚠️ 15.1KB 15.9KB +757B
core/TableBody 3.3KB 3.3KB +63B 3.2KB 3.2KB +53B
core/TableCell 78.8KB 82.9KB +4.1KB ⚠️ 14.8KB 15.6KB +756B
core/TableFooter 3.3KB 3.3KB +63B 3.2KB 3.2KB +53B
core/TableHeader 3.3KB 3.3KB +63B 3.2KB 3.2KB +53B
core/TableHeaderCell 78.6KB 82.7KB +4.1KB ⚠️ 14.8KB 15.6KB +769B
core/TableRow 6.2KB 6.3KB +66B 3.5KB 3.6KB +54B
core/TableSelectionToolbar 52.4KB 52.6KB +282B 11.2KB 11.2KB +34B
core/Text 8.6KB 8.6KB +66B 6.8KB 6.8KB +36B
core/TextArea 49.4KB 49.5KB +68B 9.4KB 9.4KB +33B
core/TextInput 53.5KB 53.8KB +284B 10.5KB 10.5KB +35B
core/Thumbnail 50.7KB 51.0KB +300B 11.0KB 11.0KB +38B
core/TimeInput 86.8KB 87.1KB +254B 13.8KB 13.8KB +34B
core/Timer 9.2KB 9.3KB +70B 6.8KB 6.8KB +36B
core/Timestamp 27.5KB 27.6KB +75B 9.5KB 9.6KB +34B
core/Toast 59.8KB 60.1KB +286B 9.7KB 9.7KB +35B
core/ToggleButton 44.1KB 44.4KB +259B 9.3KB 9.3KB +34B
core/ToggleButtonGroup 6.3KB 6.4KB +68B 3.2KB 3.3KB +55B
core/Token 29.6KB 29.9KB +296B 4.5KB 4.5KB +55B
core/Tokenizer 64.8KB 65.1KB +306B 11.7KB 11.8KB +34B
core/Toolbar 39.8KB 39.8KB +63B 7.7KB 7.8KB +59B
core/Tooltip 16.8KB 16.8KB 0B 4.9KB 4.9KB +13B
core/TopNav 51.9KB 52.1KB +250B 10.4KB 10.4KB +35B
core/TopNavHeading 54.2KB 54.4KB +260B 9.9KB 10.0KB +33B
core/TopNavItem 9.0KB 9.3KB +291B 3.8KB 3.9KB +52B
core/TopNavMegaMenu 54.2KB 54.5KB +283B 10.8KB 10.9KB +36B
core/TopNavMegaMenuFeaturedCard 6.7KB 6.8KB +66B 3.4KB 3.5KB +51B
core/TopNavMegaMenuItem 9.1KB 9.4KB +295B 4.1KB 4.1KB +51B
core/TopNavMenu 53.6KB 53.9KB +265B 10.1KB 10.1KB +36B
core/TreeList 32.5KB 33.3KB +826B 4.7KB 5.1KB +436B
core/Typeahead 61.5KB 61.7KB +276B 11.3KB 11.3KB +35B
core/TypeaheadItem 6.2KB 6.3KB +60B 3.4KB 3.5KB +52B
core/VStack 7.3KB 7.3KB +61B 4.9KB 5.0KB +57B

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.

⚠️ Touch-only size budget

These components grew past the touch-only budget (2 KB gzip JavaScript or 1 KB gzip CSS per component). If the growth runs only on a coarse pointer, load its JavaScript lazily so the import does not carry it, or justify the cost in the pull request description; CSS stays in the package stylesheet, so justify it.

Component JavaScript CSS
core/CheckboxInput +3.2KB ⚠️ +243B
core/CheckboxListItem +3.9KB ⚠️ +763B
core/ContextMenu +4.1KB ⚠️ +765B
core/ListItem +3.9KB ⚠️ +763B
core/Markdown +4.1KB ⚠️ +765B
core/MultiSelector +3.4KB ⚠️ +236B
core/RadioListItem +3.7KB ⚠️ +610B
core/Table +4.1KB ⚠️ +757B
core/TableCell +4.1KB ⚠️ +756B
core/TableHeaderCell +4.1KB ⚠️ +769B

Bundle Size Summary

Gzip figures measure each package's entry file, not the code an import pulls in.

Package Entry (ESM) Entry gzip before Entry gzip after Delta
@astryxdesign/core 4.9KB 1.2KB 1.2KB 0B
Package stylesheet Gzip before Gzip after Delta
@astryxdesign/core 34.6KB 35.3KB +773B

Accessibility Audit

Status: 2 accessibility violation(s) found — 2 serious.

Radio group pattern - 1 issue(s)
  • 🟠 serious: Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds
    • Rule: color-contrast · Affects 3/11 stories · Learn more
    • WCAG: 1.4.3 (Level AA)
RadioList - 1 issue(s)
  • 🟠 serious: Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds
    • Rule: color-contrast · Affects 3/14 stories · Learn more
    • WCAG: 1.4.3 (Level AA)

Visual Regression

55 of 502 shot(s) changed.

A change here is a question, not a failure: check whether the after is the
picture you intended. Record that review on the PR. Baseline maintenance is an
explicit dispatch of CI; this report never rewrites the baseline or adds a release gate.

component story theme mode pixels
Selector Indicator Space Bottom Sheet Narrow End RTL neutral light 753,933
Selector Indicator Space Bottom Sheet Wide Start neutral light 740,072
RichTextEditor Markdown parity: side by side probe dark 558,840
RichTextEditor Markdown parity: side by side probe light 540,756
Chat Full AI Chat probe light 230,823
Chat Full AI Chat probe dark 229,805
AppShell With Mobile Nav probe light 217,010
AppShell With Mobile Nav probe dark 216,960
Collapsible Dividers probe dark 66,445
Collapsible Dividers probe light 66,445
AppShell Playground neutral dark 65,198
AppShell Playground neutral light 63,788
Chat Default neutral dark 36,304
Chat Default neutral light 35,767
Chat Empty State probe light 23,531
Chat Empty State probe dark 22,622
ChatAutoScroll Scroll Behavior Comparison neutral dark 15,378
ChatAutoScroll Scroll Behavior Comparison neutral light 14,107
Chat With Attachments probe light 13,406
Chat With Attachments probe dark 11,232

and 35 more.


Generated by PR Enrichment workflow | View full report

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This needs an engineering owner's decision before it can be approved: the 44 px coarse-pointer targets for CheckboxInput and RadioList, and the List touch rows, press layer and holdSelection export carried in from the stacked pull requests, rest only on the draft spec:AST-094, which no owner has approved yet. An engineering owner records that decision by commenting /approve-spec c99f34a8cd361498a635ae8dc918e42f458296c4 on this pull request (the author may do so as an engineering owner), or by saying which of these behaviours should wait for AST-094 to be approved on main. Whatever that decision, please also:

  • keep the 44 px row off the CheckboxInputs that other components embed, since on a touch screen MultiSelector options grow from 36 to 56 px, compact TableSelection rows from 33 to 53 px and Markdown task items from 32 to 52 px, or document and test that growth;
  • rebase onto main once #8045, #8052 and #8085 land, so this pull request's diff is only the touch-target commit (it is 15,494 authored lines today, and pr-a11y fails because the branch predates a spec file that main's workflow runs);
  • fix the references to files and records that do not exist: utils/touchPresentation.ts, sources.test.ts, packages/core/src/gestures, and AST-094's citation of an AST-090 record.

[Automated review]

{...(isDisabled ? undefined : pressable)}
{...stylex.props(
// Under a finger the row is at least as tall as an iOS control.
touchTargetStyles.row,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On a touch screen this floor applies to every CheckboxInput, including the ones MultiSelector, TableSelection and List task markers embed: their rows grow from 36 to 56 px, 33 to 53 px and 32 to 52 px. Could it apply only where this row is the target (not for isLabelHidden, inert or read-only marker uses), with those composers in the touch tests?

});

/**
* The touch presentation's query (utils/touchPresentation.ts TOUCH_QUERY),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

utils/touchPresentation.ts and TOUCH_QUERY don't exist at this head (the same reference is in List/listRow.stylex.ts:36). Point at the real source of the query or drop the reference.

follows.
- **FR7 — Exits animate as UIKit's do.** A touch presentation MUST play the
exit its UIKit counterpart plays. **Proposed; pending owner review:** this
departs from the draft `spec:AST-090` FR1 (exits off by default) and FR10

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

There is no AST-090 record on main or in this pull request, so this amendment (and the one at line 235) has nothing to amend yet. Cite it once it exists, or drop the reference.

@cixzhang

Copy link
Copy Markdown
Contributor

Posted by Cindy's agent on her behalf.

Parts of this PR re-implement behavior that already exists, or is being specified, as a shared part of core. Converging keeps one implementation per behavior:

  • Touch gating. core/src/Indicator/touchTarget.stylex.ts:36 writes its own (pointer: coarse) check. This conflicts with AST-012 FR2 (touch is resolved once, through the closed adaptation vocabulary) and public-component-api INV16. Resolve through the shared touch resolver key so behavior matches the spec. If this behavior genuinely can't be expressed through the resolver, please raise it here as a spec question instead of shipping a separate check.
  • Reduced motion. core/src/utils/selectionHold.ts:268 handles reduced motion locally. Per design:reduced-motion (DR1–DR4), the animator is the one place that resolves it (touch cross-fades in 200 ms or less with no travel, a fine pointer changes at once), and core has no opt-out, so reducedMotion: 'keep' should be removed.

This is about where the behavior lives, not about the PR's intent.

@vjeux

vjeux commented Oct 24, 2026

Copy link
Copy Markdown
Contributor Author

Agreed: one implementation.

  • Touch gating: the 44 px floor keys on the touch resolver's TOUCH_QUERY alone, spelled the way utils/touchPresentation.ts asks StyleX keys to be. It moves to the resolver's importable constant when that lands; this PR's base, main, doesn't carry the resolver yet.
  • Reduced motion: utils/selectionHold.ts comes from the stacked selection-hold PR, feat(List): a row tapped to push stays selected until the pop deselects it #8082, and its reducedMotion: 'keep' is removed there, in its reduced-motion restack.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approval needs an engineering owner to settle the governing spec: the 44 px coarse-pointer targets for CheckboxInput and RadioList, and the List touch rows, press layer and holdSelection export carried in from the stacked pull requests, rest only on the draft spec:AST-094, and whether the targets ship on their own coarse-pointer query or wait for the shared touch resolver is still open. An engineering owner records that decision by commenting /approve-spec e877f6946b2b99a33f002fada63d412e4046bb28 on this pull request (the author may do so as an engineering owner), or by naming which of these must wait for AST-094 to be approved on main. Whatever that decision, please also:

  • remove reducedMotion: 'keep' from utils/selectionHold.ts (lines 268 and 283), because under reduced motion the deselect still runs 350 ms with a finger and with a mouse, where design:reduced-motion allows at most 200 ms on touch and an immediate change otherwise;
  • rebase onto main once #8045, #8052 and #8085 land, so the diff is only the touch-target commits (15,545 authored lines today);
  • conform AST-094 FR8 to design:reduced-motion or name that amendment, and fix the references to utils/touchPresentation.ts, sources.test.ts, packages/core/src/gestures and spec:AST-090, which do not exist.

[Automated review]

? {}
: {velocity: {opacity: -timing.velocity}}),
},
{at, reducedMotion: 'keep'},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

With reducedMotion: 'keep' (here and at line 283) the deselect plays its full 350 ms under prefers-reduced-motion, with a finger and with a mouse alike. design:reduced-motion asks for an opacity change of 200 ms or less on a coarse pointer and an immediate change otherwise, with no opt-out in core (DR2–DR4). Could the hold drop 'keep' and resolve the deselect that way, with a browser test under reduced motion?

on: a transition that travels becomes a cross-fade carrying the same change
of state. An entrance lands in place and fades in, an exit fades out in
place, and any other move fades through. A navigation push or pop
cross-fades over 0.5 s on the ease-in-out curve; a sheet, a full-screen

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A 0.5 s navigation cross-fade is longer than the 200 ms design:reduced-motion DR2 allows on a touch screen, and the pending-review note under FR8 names only the draft design:motion DR5. Could FR8 follow DR2, or name the amendment to design:reduced-motion so an owner sees it?

});

/**
* The touch presentation's query (utils/touchPresentation.ts TOUCH_QUERY),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

utils/touchPresentation.ts and TOUCH_QUERY don't exist on main or at this head. Point at the real source of the query, or drop the reference until the resolver lands.

@vjeux
vjeux force-pushed the uikit/c06-touch-targets branch from e877f69 to 9282c28 Compare October 25, 2026 01:35
@vjeux

vjeux commented Oct 25, 2026

Copy link
Copy Markdown
Contributor Author

Pushed in 9282c28, restacked on #8085. The 44 px floor keeps the resolver's literal (pointer: coarse) key, because the StyleX build gives an imported at-rule key a different priority. #8331's test pins that literal to the resolver once it is in this base.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approval needs an engineering owner to settle the governing spec: the 44 px coarse-pointer targets for CheckboxInput and RadioList rest only on the draft spec:AST-094, which no owner has approved for this head. An engineering owner records that decision by commenting /approve-spec 9282c287898d26192284c5f6a251282ce3ae1624 on this pull request (the author may do so as an engineering owner), or by saying the targets should wait until a 44 px touch target is approved on main. Whatever that decision, please also:

  • remove the theme platform adaptation condition from this stack, or land an approved amendment to spec:AST-012 FR2 first, because FR2 closes the when vocabulary to width, height, pointer, contrast and motion;
  • rebase onto main once the stacked pull requests land, so the diff is only the touch-target commits (33,535 authored lines today, 429 of them this pull request's);
  • align AST-094 FR8, FR4, DEC-1 and FR13 with design:reduced-motion DR2 and with the code that ships, and fix the references to spec:AST-090 and sources.test.ts, which do not exist.

[Automated review]

* is everything else. Pair `ios` with `pointer: 'coarse'` for a touch
* profile, such as touch motion tuned per platform.
*/
platform?: 'ios' | 'other';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

spec:AST-012 FR2 closes the when vocabulary: "A when object may contain width, height, pointer, contrast, and motion … Future environment fields require explicit additions to this closed vocabulary." No record admits platform, and the theme authoring guide and template already teach it. Could this axis come out of the stack, or wait for an approved FR2 amendment?

measures (0.55 for a scroll view and a sheet), and a release MUST pick its
rest point by projecting its velocity the way its UIKit counterpart does:
with a deceleration rate, or with a measured projection time.
- **FR4 — Physics are not themable in touch presentations.** A touch

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FR4 (and DEC-1) say touch physics are not themable, but this stack ships theme motion roles (defineTheme({motion: {springs, durations, curves}})) and holdSelection reads its deselect clock and curve from them. Could FR4 and DEC-1 describe what the roles allow, or the roles wait, so an owner approving this record approves what ships?

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approval needs an engineering owner to provide or identify the governing spec for the 44 px coarse-pointer target that CheckboxInput and RadioList get here: no record states that size, and the draft spec:AST-094 this branch carries names none and has no owner approval for this head. An engineering owner records that decision by commenting /approve-spec 10c2d49a4fa0c19a3e7fbcbae4505ee855728aa3 on this pull request (the author may do so as an engineering owner), or by saying the targets should wait until a record that states a 44 px coarse-pointer target is approved on main. Whatever that decision, please also:

  • keep the new row press layer off fine pointers, since its unconditional ::before hides a caller's ::before decoration on interactive Item, ListItem and TreeList rows with a mouse too, which spec:AST-017 FR59 does not allow for touch work;
  • drop the platform axis from the theme template (packages/cli/assets/theme.template.ts), because defineTheme now rejects it and spec:AST-012 FR2 does not admit it;
  • make the failing pr-interaction case pass: the theme-spring proof in animator.interaction.browser.spec.ts fails because nothing registers the springs table, so a theme's springs.* roles reach no animation unless something registers that table;
  • rebase onto main once the stacked pull requests land, or retarget onto #8085, so the diff is only the touch-target commits (35,149 authored lines today, 433 of them this pull request's);
  • align AST-094 FR8, FR4, DEC-1 and FR13 with design:reduced-motion DR2 and with the code that ships, and fix the references to spec:AST-090 and "AST-094 OQ4", which do not exist.

[Automated review]

Comment on lines +399 to +412
isolation: 'isolate',
'::before': {
content: '""',
position: 'absolute',
inset: 0,
zIndex: -1,
borderRadius: 'inherit',
pointerEvents: 'none',
backgroundColor: colorVars['--color-overlay-pressed'],
// On at once while the press is believed, and while a selection hold
// keeps the row selected (its own animations move it from there);
// nothing transitions it.
opacity: {
default: 0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

isolation and this ::before (with opacity: 0 by default) apply at every pointer, so on an interactive Item, ListItem or TreeList row a caller's ::before from xstyle is hidden at rest with a mouse too. spec:AST-017 FR59 lets touch work change fine-pointer appearance only to fix a defect mouse users hit or for a named cross-device consistency change. Could the layer's content and isolation sit under @media (pointer: coarse)?

Comment thread packages/cli/assets/theme.template.ts Outdated
Comment on lines +361 to +362
* are primary-pointer precision, contrast preference, motion preference, and
* platform (`ios` for the browsers of iPhone and iPad, `other` for the rest).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The stack removed the platform condition: themeAdaptations.ts accepts only the closed axes and throws … .platform is not supported., and spec:AST-012 FR2 closes the when vocabulary. A theme author who follows this template gets a build error; could the platform clause come out?


export {createAnimator} from '../animator';
export {solveSpring, toSpring} from '../spring';
export {springs} from '../uikit/springs';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This page never calls registerSpringsTable(), and reading a table no longer registers it, so in animator.interaction.browser.spec.ts:321 the themed box plays the table's spring and pr-interaction fails (111.7 px off its themed curve). No shipped module registers the springs table either. Could the table be registered here, or spring roles resolve without an explicit registration?

Comment thread scripts/sync-exports.js Outdated
@@ -177,6 +190,13 @@ const STATIC_EXPORTS = {
types: './dist/utils/interactionOverlay.stylex.d.ts',
default: './dist/utils/interactionOverlay.stylex.js',
},
// Proposed; pending owner review (spec:AST-094 OQ4): the Reduce Motion

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

AST-094 has only OQ1 and OQ2, so this new stable ./motion/reducedMotion.stylex export points at an open question that does not exist. Could it cite the record that governs it, or ship under an experimental subpath?

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approval needs an engineering owner to provide or identify the governing spec for the 44 px coarse-pointer target that CheckboxInput and RadioList get here: no current record states that size, and the pull request itself marks it as proposed and pending owner review. An engineering owner records that decision by commenting /approve-spec 1f32db965954a61a6e29b435510203f160f0fba9 on this pull request (the author may do so as an engineering owner), or by saying the targets should wait until a record that states a coarse-pointer target size is approved on main. Whatever that decision, the diff also needs narrowing:

  • rebase onto main once the stacked pull requests land, or retarget onto #8085, so the diff carries only the touch-target commits (34,549 authored lines today, 433 of them this pull request's).

[Automated review]

@cixzhang

cixzhang commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Posted by Cindy's agent on her behalf.

Cindy's decision on target size: 44 px, for touch only. Requirements:

  1. Touch only. Apply the 44 px target only under a coarse primary pointer (spec:AST-094 FR19). Mouse and desktop stay exactly as today.
  2. Scope: only standalone CheckboxInput, RadioList and CheckboxList. Rows inside dense composites keep their density (Table selection, MultiSelector options, and checkboxes embedded in other components), and other controls such as NumberInput's spin buttons are out of scope.
  3. Markdown task items must not grow. In the touch captures their rows move to a 44 px pitch (about 30 px over three items), which spaces them out too much. Keep today's pitch on touch, matching this PR's own claim that label-hidden checkboxes keep their composer's rows. Add a test that asserts it.
  4. A theme metric, not a constant. The 44 px value comes from a theme metric, so a dense theme can tune it.
  5. Prefer a bigger hit area over a bigger look. Where possible, expand the hit area without changing the visible size or the layout, and keep neighbouring targets from overlapping. Note where that isn't possible.

vjeux, could you update the PR to match these?

@vjeux
vjeux force-pushed the uikit/c06-touch-targets branch from 1f32db9 to 2a302ea Compare October 25, 2026 19:32
vjeux added 23 commits October 28, 2026 11:33
meta#8076's new head carries main 70ea859 with meta#8073's writer of the press
attribute on main's press controller, and its README names both writers.
utils/pressFeedback.ts keeps that controller with this line's own changes
on it: the pointer, drag, scroll and visibility listeners through the
shared input stream (meta#8356) and touchcancel only while the primary pointer
is coarse (meta#8270); the key path stays at the window's bubble phase, so a
Space press the page cancels paints nothing. usePressTracker stays in its
own module, one tracker for a component's life (meta#8315), so meta#8073's
rebuilt-tracker hook and its test are not taken. The harness files are
meta#8076's.
…s, and the action-group tracker writes its own

The header and writePress called it the one writer of the press attribute,
but main's action-group tracker writes its groups' presses itself. They now
say what holds, as meta#8076's gestures README does.
…ss release change

# Conflicts:
#	packages/core/src/utils/pressFeedback.ts
…he press attribute

The release note said every press painter writes data-astryx-press
through one internal writer, but the action-group tracker
(hooks/actionGroupTracker.ts) writes its groups' presses itself, as the
gestures README and utils/pressFeedback.ts already say. The note now says
paintPress writes every press it tracks and the action-group tracker
writes its own.
… release change

# Conflicts:
#	packages/core/src/utils/pressFeedback.test.ts
…llowance under every primary pointer

The useMenuPress record's FR9 puts the trigger's held finger under
spec:AST-094 FR29 under every primary pointer (FR43), so a finger on a
touchscreen laptop may drift 13 pt before the open, as on a phone. The
trigger read (pointer: coarse) as its press started and took the long
press's 10 px where the pointer was fine. Three cases fail until it does
not: a 12 pt drift opens under a fine pointer too, a (12, 12) settle
opens there, and nothing reads a pointer query, the trigger's press
included.
…lowance under every primary pointer

The useMenuPress record's FR9 governs the trigger's held finger by
spec:AST-094 FR29 under every primary pointer (FR43). The trigger now
hands the long press FR29's 13 px drift allowance whatever the primary
pointer, so it no longer reads (pointer: coarse) as its press starts, and
the menus drop their coarsePointer import. ContextMenu keeps the long
press's own allowable movement. The changeset says the same.
…wever late a busy first frame started it

The touch press controller removed `fading` on a clock started at the
lift. A busy main thread delays the release animation's first frame, and
with it its end, so the clock cut the release short mid-fade. The
controller now checks at that clock for the surface's own finite release
animation (on it, or its `::before` or `::after`) and, while one runs or
still waits for its first frame, ends the release when it finishes or is
cancelled; with none, the release ends at the clock. Timers become cancel
functions, so a release that waits on an animation is cancelled the same
way.

The clock is the table's, capped at 200 ms under reduced motion, and the
overlay's release animation is capped the same way
(design:reduced-motion DR2: a touch transition finishes in 200 ms or
less); the stylesheet tests read the capped durations.

This reaches every surface the touch press controller drives (buttons,
switches, checkboxes, cards, menu rows, list rows). Split out of meta#8077 on
review; meta#8077 builds its compositor row release on it.

Red first: with the previous controller, three of the seven new cases
fail (a release whose first frame came late, one still waiting when the
clock ran out, another painter's release); the other four guard what
stays (a cancelled release ends, no animation ends at the clock, other
animations are ignored, a new press owns its paint).
…e row press release change

# Conflicts:
#	packages/core/src/__tests__/pressState.ts
#	packages/core/src/utils/interactionOverlay.stylex.ts
#	packages/core/src/utils/pressFeedback.test.ts
#	packages/core/src/utils/pressFeedback.ts
#	scripts/build-css.test.mjs
…d the changeset says what a caller's ::before does

From review on meta#8077:
- The headers of motion/uikit/list.ts, both ListRowPress browser specs
  and interactionOverlay.cell.test.ts, and the notes in build-css.test.mjs
  and __tests__/pressState.ts, pointed the row press layer at
  utils/interactionOverlay.stylex.ts; it lives in utils/rowPressLayer.ts
  (rowPressLayerStyles.cell), its clocks in rowPressLayer.stylex.ts
  (cellPressConsts).
- Notes that described the release as ending on a timer now say the
  controller checks at the release clock and the release ends with its
  animation; the stylesheet tests no longer parse a theme motion role
  the release stopped playing.
- The changeset said a caller's ::before decoration takes the layer's
  paint during a press. Under a finger any ::before property a caller
  sets wins over the layer's, so a decoration with its own size and
  background jumps to the row's corner and the row shows no pressed fill
  until the release ends; it now says so and keeps the advice to
  decorate with ::after or a child.
…ontroller change split out) into the touch row target change

# Conflicts:
#	.changeset/list-row-press-compositor.md
…le uses

From review on meta#8085: the exemption let a file that paints a press pass
the guard whenever it rendered a marked component through `xstyle`. It
came with ListItem's divider arms, which the revert of meta#8079 took out,
so no file at this head reaches it, and in place it would wave through a
file whose press styles never reach that component's root. The guard is
again exactly as on the line below; it passes without the exemption.
…never needed

From review on meta#8077: the build-css press-paint check filtered out a
`--_press-paint: transparent` declaration, with a note, that the row
layer never writes (only the overlay declares the press paint), and
interactionOverlay.cell.test.ts defined a `hostRules` helper no case
uses. Both go; the stylesheet check is as on the line below again.
…ers a row with an end control

From review on meta#8085:
- `isTouchClick` and its comment sat between `Item`'s docblock and
  `export function Item`, so the docblock attached to the helper and
  `Item` lost its description in editors and Storybook. The helper now
  sits above the docblock.
- component:List FR10's verification names a row with an end control.
  A new List story puts a compact row whose end content is a switch
  between two interactive rows, and the browser spec checks that the
  interactive rows grow only to half the gap to the switch, that the
  browser hit-tests the switch at its center, and that a real tap toggles
  it with no tap reaching the rows beside it. With the hit area's
  neighbour clamp removed, the case fails (a band of 5.5 px where half
  the gap is 2 px).
…ast its divider

From review on meta#8085, two ways a tap in an interactive row's band missed
the row:
- The band is the row's ::after, and the rows after it are positioned
  with no z-index, so a later row that takes no taps (a static row, such
  as the switch row in the "With end controls" story) painted and
  hit-tested over the band. The layer now has z-index: 1 on itself; its
  even-odd clip still leaves the row's own box to the row's content, and
  the row still makes no stacking context.
- The layer is offset from the row's padding box, while the insets are
  measured from its border box, so below a divided row the band was the
  divider's width short. A host that draws a border now declares it
  (--_hit-border-{top,right,bottom,left}), and a divided ListItem declares
  its divider's, so the band starts at the divider's outer edge.

Above everything at z-index auto, the band still takes no tap from a
control near the list: the hit area's neighbour clamp measures every
interactive element on the page, not only rows. The "With end controls"
story gains a button in its header and one 4 px after the list, and a
browser case hit-tests both; with the clamp removed it fails (a 6 px band
where half the gap is 2 px).

Red first: the browser spec now reads the band past the border box and
hit-tests points inside Network's band. On the previous CSS, the
end-control case read a 1 px band where half the gap is 2 px and a
compact divided row's band read -1 px; with z-index removed, a point
0.5 px below Network hit the Wi-Fi row.
…nd the list bounds what rises

From review on meta#8085 and meta#8106:
- A ListItem with swipeActions is a stacking context at rest (Item
  isolates and translates its swipe root), so its touch band's z-index
  ordered only inside it and a following static row still took taps in
  the band. Under a finger, a swipeable interactive row now raises itself
  (z-index: 1 on the row; with a mouse nothing changes). The "With end
  controls" story's Network row is now swipeable, and the browser case
  checks that the row isolates and that taps in its band are its own.
- The list's ul now isolates (isolation: isolate), so what rises inside
  it (a row's band, a swipeable row, and later a crossing row) orders
  above the rows after it but stays below a page-level sticky header at
  the same z-index (spec:AST-027 DEC-1, DEC-2).

Red first: with Network swipeable, a point 0.5 px below it hit the Wi-Fi
row; the unit cases for the list's isolation and the swipeable row's
raise failed on the previous CSS.
From review on meta#8085: ListItem raised every interactive row with a
swipeActions prop, while Item makes a row a stacking context (serves its
swipe actions) only when a side has an entry, and not for a disabled
row, a link root, a role that forbids interactive descendants, or a row
whose press goes to a control inside it (interactiveRef). Rows with empty
swipe sides or a delegate control were raised for nothing. Item's
condition is now one function, servesSwipeActions, which Item and
ListItem both use.

Red first: in List.test.tsx, a row with empty swipe sides and a row with
a delegate control both carried the raise on the change before this one.
ListItem declares --_hit-border-bottom (the divider's width, 0 on the
last row) for the touch hit layer, and List.doc.mjs did not list it, so
derivedVarRegistry.test.ts failed: "List has undocumented CSS vars in
source: --_hit-border-bottom". It is now in List.doc.mjs theming.vars[]
as a private var, and in VARS_WITHOUT_DERIVED_MAPPING with its reason:
it is the ::after layer's geometry, which follows --border-width, not a
property a theme author sets (as with --_thumbnail-hit-inset and
--_input-clear-hit-inset).

Red first: "List: all source vars are in doc file" failed on the change
before this one; it passes now (122 of 122).

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Changes requested: the CheckboxInput and RadioList hit areas and the --size-touch-target token match spec:AST-094 FR42 and the target-size decision on this pull request, and they leave every layout and mouse interaction unchanged. This branch, though, still merges a snapshot of #8085 that makes up 30,787 of its 31,801 changed lines and that #8085 has since moved past. Please land #8085 first, then rebase so this pull request carries only its own 16 files; nothing else found blocks approval.

[Automated review]

@vjeux
vjeux marked this pull request as draft October 29, 2026 22:34
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 29, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 29, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 29, 2026
utils/pressFeedback.ts is taken byte for byte from git's clean merge of
those two heads; nothing in this pull request changes it.
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 29, 2026

This branch was successfully deployed

1 active deployment
Preview — 49c8e40b Deployed Oct 29, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot. needs:design-review Affects visuals — Design should review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants