Skip to content

docs(spec): CommandPalette records its shipped contract as current - #9306

Merged
cixzhang merged 1 commit into
mainfrom
spec-backfill/CommandPalette
Nov 1, 2026
Merged

cixzhang merged 1 commit into
mainfrom
spec-backfill/CommandPalette

Conversation

@cixzhang

@cixzhang cixzhang commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Exact decision needed

Promote component:CommandPalette, component:CommandPaletteList, component:CommandPaletteItem, and component:CommandPaletteEmpty from draft to current, and add new current records for component:CommandPaletteGroup and component:CommandPaletteFooter. component:CommandPaletteInput is already current and unchanged. No behavior, prop, default, target, or export changes.

Existing authority searched

Decision

All six authority: current, approved by cixzhang. Drafts keep their content and owners with draft and audit wording removed. Behavior that does not meet a current rule is recorded as a gap:

  • a standalone Item or List has no keyboard model (OQ1 in each);
  • selected paint hides keyboard highlight on an item (OQ2);
  • List replaces a caller's explicit aria-label with its own name (architecture:public-component-api INV5: a caller's explicit name wins).

The listbox and option roles and option state are component-owned and replace a caller's, which the current component:CommandPaletteInput AR3 already records for the same composite; List and Item cite it, and the Item test that protects option semantics verifies that contract. Group lets a caller's role or aria-label win, which is conformant. CommandPalette OQ2 asks whether INV5 should state the composite-semantics reading family-wide. These follow existing authority; no new decision.

CommandPalette's "Does not own" list now points at the Group, Footer, and Empty records.

Rejected alternatives

None.

Claim scope and non-goals

Open questions on the query-field target, the standalone keyboard model, and whether INV5 states the composite-semantics reading family-wide stay with their owners. Claims read from source without a focused test are listed under each verification map.

Evidence and implementation relationship

CommandPalette.test.tsx, CommandPaletteInput.test.tsx, CommandPaletteList.test.tsx, CommandPaletteItem.test.tsx, CommandPaletteEmpty.test.tsx, CommandPaletteGroup.test.tsx, CommandPaletteFooter.test.tsx, CommandPaletteFooter.a11y.chromium.spec.ts, CommandPaletteEmptyAudit.a11y.chromium.spec.ts, and themingTargets.test.ts.

Writing rubric results

  • R1 narration: none.
  • R2 research in the record: none.
  • R3 evidence naming a change: none.
  • R4 rejected alternatives over one line or outside a decision: none.
  • R5 pull request or issue references remaining: none.
  • R6 ruled open questions still listing options: none; the open questions are unruled.

Scope

  • This PR contains specification records only.
  • It records observable behavior and preserves equivalent internal implementations.
  • Any named internal mechanism is intentionally public, names its dependent caller/system, and explains why an equivalent implementation would not satisfy the contract: the list id and active descendant are the public combobox relationship.
  • Verification states the evidence layer and failure signal without prescribing CI job/workflow topology.
  • It records one intentional durable decision, not a rescue for a separable tagalong.
  • The canonical knowledge owner, affected current claims, and overlapping open work are named; no ownership collision.
  • Adjacent API, visual, accessibility, composition, and implementation facts remain outside scope unless this exact decision depends on them.
  • Public text and artifacts contain no internal Meta context.

Validation

  • pnpm check:knowledge: aligned
  • Prettier: clean
  • git diff --check: clean

@vercel

vercel Bot commented Nov 1, 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 Nov 1, 2026 2:53pm UTC

Request Review

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

astracat-bot Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
❓ Needs maintainer input (for maintainers only) Nov 1, 2026, 3:04 PM UTC

@github-actions github-actions Bot added the needs:spec-owner-review Current knowledge records await owner approval label Nov 1, 2026
@cixzhang
cixzhang marked this pull request as ready for review November 1, 2026 11:10
@cixzhang
cixzhang marked this pull request as draft November 1, 2026 11:10

@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 spec update needs an engineering owner's decision before it can be approved. The six CommandPalette records become current only with an owner's approval of this exact head, and that owner must also settle whether a caller's explicit role or aria-label may replace the listbox and option roles (List FR2 and Item FR1). INV5 says component-owned accessibility "cannot be accidentally overwritten", and the records' own List OQ2 and Item OQ3 leave this open. An engineering owner records the decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so as an engineering owner; fix the Empty verification map first, because a content change resets the approval.

  • CommandPaletteEmpty.spec.md line 173 says message contrast below 4.5:1 fails the audit, but CommandPaletteEmptyAudit.a11y.chromium.spec.ts records contrast without failing on it, and it does check the FR4 320 px wrap that the record lists as having no focused test.

[Automated review]

| ------------- | -------------------------------------------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| FR1, FR5–FR6 | `CommandPaletteEmpty.test.tsx`; `themingTargets.test.ts` | text and element children; root inputs | A dropped input, a moved target, or lost children fails the focused assertions. | `audit:CommandPaletteEmpty/§2,§3,§4` |
| FR2, FR3, AR1 | `CommandPalette.test.tsx`; `CommandPaletteList.test.tsx` | bootstrap, search, rich content, modal and inline | Exposing a listbox, adding a role, or announcing other text than the rendered message fails assertions. | `audit:CommandPaletteEmpty/§1,§4` |
| FR4, AR2 | `CommandPaletteEmptyAudit.a11y.chromium.spec.ts` | Narrow and wide viewports; light and dark; forced colors; rich content | A case with horizontal overflow, or message text below 4.5:1 contrast outside forced colors, fails the audit manifest test. | `audit:CommandPaletteEmpty/accessibility` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CommandPaletteEmptyAudit.a11y.chromium.spec.ts records message contrast as "Recorded, not gating" and leaves it out of passed, so contrast below 4.5:1 does not fail the manifest test. Consider saying overflow fails and contrast is recorded only. FR4's 320 px wrap is covered by the gated content cases, so it can come off the no-test list below.

| ID | Invariant | Basis |
| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
| FR1 | Native props and `ref` reach the listbox root, and consumer `className` and `style` combine with the list target and base styles. Inside CommandPalette the root id is the context list id; standalone, a caller `id` is kept. | Current source and tests |
| FR2 | Standalone, and inside CommandPalette while at least one selectable result exists, the root exposes `role=listbox` with an accessible name from `label`, falling back to the translated default; a caller's explicit `role` or `aria-label` reaches the root (`architecture:public-component-api` INV5). Implementation gap: the component's role and name replace a caller's (Current-state impact; OQ2). Otherwise AR4 applies. | Current source and tests |

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 reverses the earlier rule that consumer role and aria-label do not replace the listbox role and name. INV5 also says component-owned accessibility cannot be accidentally overwritten, and OQ2 below leaves the composite-role exemption open, so this needs an engineering owner's ruling before it becomes current.

@cixzhang
cixzhang marked this pull request as ready for review November 1, 2026 12:03
@cixzhang
cixzhang force-pushed the spec-backfill/CommandPalette branch from df2e60c to f7cb4f4 Compare November 1, 2026 12:08

@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 spec update still needs an engineering owner's decision before it can be approved. The six CommandPalette records become current only with an owner's approval of this exact head, and that owner must also settle whether a caller's explicit role or aria-label may replace the listbox and option roles (List FR2 and Item FR1), which INV5's "cannot be accidentally overwritten" and the records' own List OQ2 and Item OQ3 leave open. An engineering owner records the decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so as an engineering owner. The Empty verification row is now accurate; two CommandPalette rows (CommandPalette.spec.md lines 249 and 255) still name browser evidence their Verification column no longer lists, so make any wording fix before approving, because an edit resets the approval.

[Automated review]

| ------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| FR1, AR1 | CommandPalette root and subcomponent suites | Default, grouped, empty, pending, rich Empty, and replaced slots | Exposing an empty listbox, leaving empty Input popup attributes, or nesting rich Empty controls under option semantics fails focused role and hosted axe assertions. | `audit:CommandPalette/anatomy` |
| FR2 | Focused subcomponent suites and `themingTargets.test.ts` | Seven local targets at their owned elements | Removing or moving a current target fails a focused placement assertion or the global inventory. | `audit:CommandPalette/theming` |
| FR3 | `CommandPaletteInput.test.tsx` and `CommandPaletteFooter.test.tsx` | Default Search glyph, pending spinner, and Footer Kbd | Replacing or removing the delegated Icon, Spinner, or Kbd instance fails a composed-owner assertion and changes the exact-head evidence inventory. | `audit:CommandPalette/theming` |

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 row (and the Theming anatomy map row at line 255) still names browser evidence ("exact-head evidence inventory", "browser sensor counts") that the Verification column no longer lists. CommandPalette.a11y.chromium.spec.ts is still in verified_by, so naming it here, or dropping the browser clause, would keep the map consistent.

@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 spec update still needs an engineering owner's decision before it can be approved. The six CommandPalette records become current only with an owner's approval of this exact head, and that owner must also settle whether a caller's explicit role or aria-label may replace the listbox and option roles (List FR2 and Item FR1), which INV5's "cannot be accidentally overwritten" and the records' own List OQ2 and Item OQ3 leave open. An engineering owner records the decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so as an engineering owner. The CommandPalette verification rows are now consistent; if the ruling goes against caller-wins, reword List FR2, Item FR1, CommandPalette AR1 and the readiness row at CommandPalette.spec.md:49 before approving, because an edit resets the approval.

[Automated review]

| Behavior | Searchable commands in a Dialog: a combobox query field, a listbox of results only while selectable results exist, an empty message otherwise, and a keyboard-guidance footer. Modal Escape belongs to Dialog's shared dismissal. |
| End-user impact | Keyboard and screen-reader users search and run commands with native text editing kept intact, hear the empty message that is shown, and close nested layers one Escape at a time. |
| Builder impact | None. |
| Compatibility/readiness | Records shipped behavior; no public change. No implementation gap; one owner question stays open. |

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 row says "No implementation gap", but AR1 (lines 143-148) now states that a caller's role or aria-label reaches List and Item, which today's parts do not meet. If caller-wins stays, name that gap here; if it goes, drop AR1's new sentence.

@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 spec update needs an engineering owner's decision before it can be approved: the six CommandPalette records become current only with an owner's approval of this exact head. That owner also needs to settle whether a caller's explicit role or aria-label may replace the listbox and option roles (List FR2, Item FR1, CommandPalette AR1), which INV5's "cannot be accidentally overwritten", the records' own List OQ2 and Item OQ3, and the current CommandPaletteInput AR3, which keeps the combobox role over a caller's inside the same palette, leave open. An engineering owner records the decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so as an engineering owner. If the ruling goes against caller-wins, reword those rules and the List and Item review checks before approving, because an edit resets the approval.

[Automated review]

| FR5 | Children provide the option's label and supporting presentation, without nested interactive descendants. | Option semantics and `spec:AST-020/FR1,FR2` | Documented; exact-head a11y remains a gate |
| ID | Invariant | Basis |
| --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| FR1 | Native props and `ref` reach the option root, and a caller's explicit `role` reaches it (`architecture:public-component-api` INV5). CommandPalette context owns registered-item id, selected state, disabled state, and value marker; standalone caller id persists. Implementation gap: `role="option"` replaces a caller's role (Current-state impact; OQ3). | Current source and tests; `architecture:public-component-api` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FR1 drops role from what CommandPalette context owns and lets a caller's role replace option even inside the palette. The current CommandPaletteInput record reads INV5 the other way for the same composite: its AR3 says that with CommandPalette context the field owns role and the popup attributes, "and these replace the same native passthrough props". The OQ3 ruling should cover both, or FR1 keeps role under context ownership until it does.

@cixzhang
cixzhang force-pushed the spec-backfill/CommandPalette branch 2 times, most recently from e5ac990 to dec2203 Compare November 1, 2026 13:27

@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 spec update needs an engineering owner's decision before it can be approved. The six CommandPalette records become current only once an engineering owner approves this exact head by commenting /approve-spec <full head SHA> on the pull request; the author may do so as an engineering owner. That approval settles three rules that no current record states: List FR2's caller aria-label naming the List, Group FR1's caller role replacing group, and standalone listbox and option role ownership in List FR2 and Item FR1. Two record fixes are needed either way:

  • List FR2 and Item FR1 cite component:CommandPaletteInput AR3 for the standalone case, but AR3 covers only the in-palette field and keeps standalone caller roles intact, so state the standalone rule as the record's own.
  • List FR4's Basis says "Current source and tests", but the same record lists FR4 as read from source with no focused test.

[Automated review]

| ID | Invariant | Basis |
| --- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
| FR1 | Native props and `ref` reach the listbox root, and consumer `className` and `style` combine with the list target and base styles. Inside CommandPalette the root id is the context list id; standalone, a caller `id` is kept. | Current source and tests |
| FR2 | Standalone, and inside CommandPalette while at least one selectable result exists, the root exposes `role=listbox`, which a caller's `role` does not replace (composite semantics are component-owned and replace passthrough, as `component:CommandPaletteInput` AR3 records), named by a caller's explicit `aria-label`, else `label`, else the translated default (`architecture:public-component-api` INV5). Implementation gap: the component's name replaces a caller's `aria-label` (Current-state impact). Otherwise AR4 applies. | Current source and tests |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

component:CommandPaletteInput AR3 covers only the field "With CommandPalette context" and says "Standalone caller-owned roles and relationships remain intact." Citing it for the standalone List's listbox role points readers at the opposite rule. Scope the AR3 citation to the in-palette case and state the standalone rule as this record's own.

| FR1 | Native props and `ref` reach the listbox root, and consumer `className` and `style` combine with the list target and base styles. Inside CommandPalette the root id is the context list id; standalone, a caller `id` is kept. | Current source and tests |
| FR2 | Standalone, and inside CommandPalette while at least one selectable result exists, the root exposes `role=listbox`, which a caller's `role` does not replace (composite semantics are component-owned and replace passthrough, as `component:CommandPaletteInput` AR3 records), named by a caller's explicit `aria-label`, else `label`, else the translated default (`architecture:public-component-api` INV5). Implementation gap: the component's name replaces a caller's `aria-label` (Current-state impact). Otherwise AR4 applies. | Current source and tests |
| FR3 | Inside CommandPalette, the query field's `aria-controls` names the listbox id. | Current source and tests |
| FR4 | The root lays out children in one column with spacing-scale padding and gaps, grows within a flex parent, caps its height at the parent's height, and scrolls overflowing children inside itself. | Current source and tests |

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 Basis says "Current source and tests", but this record lists FR4 under "Read from source, with no focused test yet" and CommandPaletteList.test.tsx has no layout or scrolling test. Suggest "Current source".

| FR5 | Children provide the option's label and supporting presentation, without nested interactive descendants. | Option semantics and `spec:AST-020/FR1,FR2` | Documented; exact-head a11y remains a gate |
| ID | Invariant | Basis |
| --- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| FR1 | Native props and `ref` reach the option root. The `option` role, selected state, and disabled state replace a caller's (composite semantics are component-owned and replace passthrough, as `component:CommandPaletteInput` AR3 records). CommandPalette context owns the registered-item id and value marker; a standalone caller id persists. | Current source and tests; `architecture:public-component-api` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FR1 applies the protected option role to standalone items too (the "protects owned option semantics" test renders one without CommandPalette), but component:CommandPaletteInput AR3 governs only the in-palette field and keeps standalone caller roles intact. State the standalone rule here as this record's own instead of attributing it to AR3.

@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 spec update needs an engineering owner's decision before it can be approved: the six CommandPalette records become current only once an engineering owner approves this exact head by commenting /approve-spec <full head SHA> on the pull request, and the author may do so as an engineering owner. That approval settles three rules no current record states yet: List FR2's caller aria-label naming the List, Group FR1's caller role replacing group, and the standalone listbox and option protection in List FR2 and Item FR1. Both record fixes from the previous round are in. Two optional wording fixes remain; make them before approving, because a new commit resets the approval:

  • CommandPalette.spec.md:254 says the FR1/AR1 mutations fail "hosted axe assertions", but its Verification column no longer lists any axe check.
  • CommandPaletteEmpty.spec.md:151-152 says no anatomy map is recorded, while CommandPalette's aggregate map already maps Empty; point at it as the Group and Footer records do.

[Automated review]

| Theming anatomy map | `scripts/check-knowledge.mjs` and exact-head Chromium evidence | Canonical anatomy and seven current local targets | Missing, extra, prefixed, stale, alias-backed, or visually absent mappings fail repository validation or browser sensor counts. | `audit:CommandPalette/theming` |
| Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
| ------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| FR1, AR1 | CommandPalette root and subcomponent suites | Default, grouped, empty, pending, rich Empty, and replaced slots | Exposing an empty listbox, leaving empty Input popup attributes, or nesting rich Empty controls under option semantics fails focused role and hosted axe assertions. | `audit:CommandPalette/anatomy` |

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 Verification column now lists only the unit suites, but this row still says the mutations fail "hosted axe assertions", and none of those suites runs axe. Name the Storybook accessibility audit here, or end the sentence at "focused role assertions". Optional; make it before approving, since a new commit resets the approval.

Comment on lines +151 to +152
No component-local design decision is recorded. No anatomy-theming map is
recorded yet; the block is optional during migration, so the map is deferred.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CommandPalette's aggregate map already maps Empty to command-palette-empty. Suggest the wording the Group and Footer records use: "The aggregate CommandPalette anatomy map, owned by component:CommandPalette, maps the Empty part." Optional.

@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 spec update needs an engineering owner's decision before it can be approved: the six CommandPalette records become current only once an engineering owner approves this exact head by commenting /approve-spec <full head SHA> on the pull request, and the author may do so as an engineering owner. That approval settles three rules no current record states yet: List FR2's caller aria-label naming the List, Group FR1's caller role replacing group, and the listbox and option protection in List FR2 and Item FR1. Both wording fixes from the previous round are in. One optional consistency fix remains; make it before approving, because a new commit resets the approval:

  • CommandPaletteList.spec.md still names only label and the translated default as name sources at lines 42, 80-82, 103 and 126, while FR2, ORD1 and AR1 put a caller's aria-label first; align them with whichever rule the owner keeps.

[Automated review]

| ID | Invariant | Basis |
| --- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
| FR1 | Native props and `ref` reach the listbox root, and consumer `className` and `style` combine with the list target and base styles. Inside CommandPalette the root id is the context list id; standalone, a caller `id` is kept. | Current source and tests |
| FR2 | Standalone, and inside CommandPalette while at least one selectable result exists, the root exposes `role=listbox`, which a caller's `role` does not replace: inside CommandPalette because composite semantics are component-owned and replace passthrough, as `component:CommandPaletteInput` AR3 records, and standalone by this record's own rule, named by a caller's explicit `aria-label`, else `label`, else the translated default (`architecture:public-component-api` INV5). Implementation gap: the component's name replaces a caller's `aria-label` (Current-state impact). Otherwise AR4 applies. | Current source and tests |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Optional: FR2 puts a caller's aria-label first, but lines 42, 80-82, 103 (the Accessible name concept's closed values) and 126 still name only label and the translated default. Align them with whichever rule the owner keeps, before approving, since a new commit resets the approval.

@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.

The six CommandPalette records describe what the components ship today, with the shortfalls named as gaps, and I found no defects, but approval waits on an engineering owner's decision because no current record yet states three of the rules they introduce. The rules to settle: List FR2 lets a builder's aria-label name the List (recording today's replacement as a gap), List FR2 and Item FR1 keep listbox and option protected from a builder's role (inside the palette by analogy with CommandPaletteInput AR3, which covers only the query field), and Group FR1 and FR4 let a builder's role replace group. An engineering owner records the decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so as an engineering owner; otherwise, say which of those rules should change.

[Automated review]

| FR2, AR3 | `CommandPaletteItem.test.tsx` | enabled; disabled; consumer-cancelled; contextual | Disabled consumer activation, ignored cancellation, missing local report, selection, or close fails tests. | `audit:CommandPaletteItem/behavior` |
| FR4, PR2 | `CommandPaletteItem.test.tsx`, `CommandPalette.test.tsx` | standalone; inline initial; changed highlight | Lost nearest scrolling, duplicate contextual scrolling, or initial inline scroll fails Effect assertions. | `audit:CommandPaletteItem/behavior` |
| Theme/RTL | focused class assertion, `themingTargets.test.ts`, RTL verified N/A | all visual states | Target loss fails inventory/DOM tests; any new directional behavior requires a non-empty RTL dimension. | `audit:CommandPaletteItem/theming` |
| FR5, AR4 | Source review | Item children | Gap: no check fails if item children contain a nested interactive descendant. | `audit:CommandPaletteItem/accessibility` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Optional: CommandPaletteItemAudit.a11y.chromium.spec.ts (lines 273-275) already fails when an option in its stories contains a button, a or [tabindex], though it runs only for Item audit pull requests. Naming it here, scoped to the stories, would make this row exact; caller content stays unchecked.

@cixzhang

cixzhang commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 589168e

@github-actions github-actions Bot removed the needs:spec-owner-review Current knowledge records await owner approval label Nov 1, 2026
@cixzhang
cixzhang merged commit 27ccfe0 into main Nov 1, 2026
53 checks passed
@cixzhang
cixzhang deleted the spec-backfill/CommandPalette branch November 1, 2026 17:33

This branch was successfully deployed

1 active deployment
Preview — 589168e2 Deployed Nov 1, 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant