Skip to content

feat(DropdownMenu): anchorRef places the menu against an element other than its trigger - #7352

Closed
vjeux wants to merge 1 commit into
meta:mainfrom
vjeux:dropdown-menu-anchor-ref
Closed

vjeux wants to merge 1 commit into
meta:mainfrom
vjeux:dropdown-menu-anchor-ref

Conversation

@vjeux

@vjeux vjeux commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Review only this PR's change: the branch sits on main, so this diff is already its own.

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 our menus, such as a filter beside a search field, should open under the whole row at its width, but DropdownMenu can only anchor to its own trigger.

Why: callers either change the design or host rows in a Popover, which loses the menu's press model and keyboard opens.

Problem and solution fit

DropdownMenu takes anchorRef, Popover's name for an external anchor. The menu is placed against that element (placement, alignment, default width), while the trigger keeps focus, focus return, the press model, keyboard opens and the menu's name. The bottom sheet ignores it.

Current specification

component:DropdownMenu (draft): this PR proposes a Menu anchor concept, FR19 and DEC-12, pending owner review. component:Popover defines anchorRef.

Public delta and caller burden

  • One optional prop, anchorRef; nothing changes without it. menuWidth defaults to the anchor's width; an empty ref anchors on the trigger.
const rowRef = useRef<HTMLDivElement>(null);
<div ref={rowRef}>
  <TextInput label="Search" isLabelHidden />
  <DropdownMenu anchorRef={rowRef} alignment="end" button={{label: 'Filter'}} items={filters} />
</div>

Design and alternatives

  • A second ref handed to the trigger render prop. But the anchor is usually an ancestor the trigger never renders.
  • An offset from the trigger. Breaks as soon as the layout changes.
  • Host the rows in a Popover. Works, but drops the menu's press model and keyboard behaviour.
  • anchorRef, as on Popover and Tooltip (chosen). Same name and shape callers already know; the trigger keeps every menu behaviour. The cost: a caller who sets it must keep the anchor mounted while the menu is open, or the menu falls back to the trigger.

Evidence

Seven of nine new unit cases fail on main: the row carries the menu's anchor and the trigger none, for the default and a custom trigger, and empty, late and unmounted anchors behave as FR19 says. A Chromium test checks placement under the row at its width, dismissal, keyboard opens and focus return; placement fails on main.

Writing rubric results

R1 narration: the concept, FR19 and DEC-12 are present tense.
R2 research: none.
R3 evidence: FR19's verification row names the tests.
R4 rejected alternatives: DEC-12 lists five.
R5 change references: none.
R6 open questions: none.

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

In Storybook, open Core/DropdownMenu → Anchored to a row (anchorRef).

  1. Click "Filter": the menu opens under the whole search row, as wide as the row, ending at its end edge.
  2. Press Escape: the menu closes and focus returns to "Filter".
  3. Focus "Filter" and press Enter: the menu opens in the same place.

@vercel

vercel Bot commented Oct 11, 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 26, 2026 4:44pm UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 11, 2026
@vjeux
vjeux force-pushed the dropdown-menu-anchor-ref branch from 63b9cb4 to f0a9bab Compare October 11, 2026 21:28
@astracat-bot

astracat-bot Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
❓ Needs maintainer input (for maintainers only) Oct 30, 2026, 12:45 AM UTC

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 Storybook Preview

View Storybook for this PR

🧪 Sandbox Preview

View Sandbox for this PR

Component Size

Component Import before Import after Delta CSS before CSS after Delta
core/ContextMenuItem 16.6KB 16.6KB 0B 5.2KB 5.2KB 0B
core/DropdownMenu 72.2KB 72.3KB +27B 14.6KB 14.6KB 0B
core/DropdownMenuCheckboxItem 16.1KB 16.1KB 0B 5.6KB 5.6KB 0B
core/DropdownMenuDivider 6.6KB 6.6KB 0B 3.6KB 3.6KB 0B
core/DropdownMenuGroup 6.1KB 6.1KB 0B 3.3KB 3.3KB 0B
core/DropdownMenuItem 15.4KB 15.4KB 0B 5.2KB 5.2KB 0B
core/DropdownMenuRadioGroup 6.0KB 6.0KB 0B 3.2KB 3.2KB 0B
core/DropdownMenuRadioItem 16.2KB 16.2KB 0B 5.6KB 5.6KB 0B
core/DropdownMenuSubMenu 57.5KB 57.5KB 0B 9.5KB 9.5KB 0B
core/MoreMenu 72.5KB 72.5KB +39B 14.6KB 14.6KB 0B

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 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.3KB 34.3KB 0B

Accessibility Audit

Status: No accessibility violations detected.

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 | Storybook | Sandbox | 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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so the new anchorRef prop and the proposed FR15 and DEC-8 have no approved spec behind them yet. A maintainer needs to approve or reject FR15 and DEC-8 as the governing spec for this addition, and settle the two points below. Separately, please fix one defect: with anchorRef, the new layout effect clears the anchor on every open before the layer checks whether it is in view, so anchored menus never get the off-screen-anchor hold of spec:AST-059 FR5/FR8, and a test asserting that the visibility observer watches the anchorRef element would lock the fix in.

  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, allows an anchor supplied outside those props.
  • Whether anchorRef may mean positioning-only here, when Popover's referenced anchor also supplies the trigger.

[Automated review]

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so the new anchorRef prop and the proposed FR16, DEC-9 and Menu anchor concept have no approved spec behind them yet, and a maintainer needs to approve or reject them and settle the two points below. Separately, please fix one defect whatever that decision is: the new layout effect clears the menu's anchor on every open before the layer checks whether the anchor is in view, so anchored menus never get the off-screen-anchor hold of spec:AST-059 FR5/FR8, and a test asserting that the visibility observer watches the anchorRef element would lock the fix in. The PR description still calls the proposal FR15 and DEC-8, which on this branch are the header and footer rows, so please update it.

  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may mean positioning-only here, when Popover's and Tooltip's referenced anchor is also the control.

[Automated review]

@vjeux

vjeux commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

Thanks. Fixed in 1b66fd2.

  • Off-screen anchor: confirmed. The anchor effect depended on the popover's triggerRef, whose identity follows the layer's open state, so every open cleared the anchor and set it again. Its cleanup ran before the layer's own layout effect read the anchor, so neither the first-frame visibility read nor the IntersectionObserver saw it. The anchor effects now run ahead of the popover in the hook order and read the latest setter through a ref, so the anchor stays set across opens. A new unit case stubs IntersectionObserver: the layer now watches the row, and withdraws the slide when the row leaves the viewport. It failed on the previous head (0c2fae6, nothing observed) and passes now. DropdownMenu, ContextMenu, Popover, Layer and Selector suites, typecheck, lint, knowledge and the Chromium anchor, header/footer, press and drill-in specs pass.
  • Description: it names FR16 and DEC-9 now (updated after the rebase past the header/footer change); the evidence and Testing sections are refreshed for this head.
  • AST-055 FR2 and the positioning-only meaning of anchorRef: those are for the record owner, so I've left them open.

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so approval needs a maintainer to provide the governing spec for the new anchorRef prop, by approving or rejecting the proposed FR16, DEC-9 and Menu anchor concept, and to settle the two points below. The off-screen-anchor issue from the last round is fixed. Separately, please handle an anchorRef that is still empty when the menu opens: today the menu opens attached to nothing (at the page's top-left in Chromium) with no warning, so falling back to the trigger, as BaseTypeahead falls back to its input, or warning in development, plus a test, would close it.

  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may mean positioning-only here, when Popover's and Tooltip's referenced anchor is also the control.

[Automated review]

if (anchorRef == null) {
return;
}
const element = anchorRef.current;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

When anchorRef.current is null here (for example, a ref on a component that doesn't forward it, or a conditionally rendered anchor), nothing is anchored: attachTrigger skips the trigger whenever anchorRef is set, so the layer's position-anchor names an anchor no element carries. In Chromium the menu then opens at the page's top-left, over other content, with no warning.

Falling back to the trigger while the element is absent, as BaseTypeahead falls back to its input, or warning in development, would avoid a silently broken state (spec:AST-002 FR15). A test for the empty-ref case would lock it in.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 165c041. While anchorRef.current is null, the trigger is now the anchor, as BaseTypeahead falls back to its input. The menu moves to the caller's element once it's attached, so it's never placed against nothing. I chose the documented fallback over a development warning, per spec:AST-002 FR15: an anchor rendered only in some layouts is legitimate composition, and a warning would flag it. The prop doc, the changeset, FR16 and DEC-9 now say what an empty ref does. Two new unit cases: an empty ref keeps the menu on its trigger through an open, and an anchor that appears later takes over from the trigger. Both fail on 1b66fd2 and pass now. The DropdownMenu, ContextMenu, Popover, Layer and Selector suites, typecheck, lint, knowledge, the Storybook build and the Chromium anchor, header/footer, press and drill-in specs pass.

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so approval needs a maintainer to provide the governing spec for the new anchorRef prop, by approving or rejecting the proposed FR16, DEC-9 and Menu anchor concept, and to settle the two points below. The empty-ref issue from the last round is fixed: an unattached anchorRef now leaves the menu on its trigger, and the new tests fail without that fallback. One optional follow-up: if the anchor element unmounts while the menu is open, the menu moves to its trigger but keeps the old element's off-screen hold until it closes, so either re-subscribing the layer's visibility observer when its anchor changes or noting this in FR16 would close it.

  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may mean positioning-only here, when Popover's and Tooltip's referenced anchor is also the control.

[Automated review]

if (anchorRef == null) {
return;
}
const element = anchorRef.current ?? buttonRef.current;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Non-blocking: when this re-points the anchor during an open (the referenced element unmounts or mounts while the menu is open), the layer's anchor-visibility observer keeps watching the element it subscribed to when the menu opened, because that effect only re-subscribes when the open state changes (useLayer.tsx, the anchor-visibility effect). In Chromium, after a sibling anchor unmounted mid-open, the menu correctly moved under the trigger but kept justify-self: unsafe self-end (the off-screen hold) while the trigger was in view, so the slide stays withdrawn until the menu closes. Narrow and self-correcting at the next open; re-subscribing the observer when the layer's anchor changes, or saying in FR16 that an anchor change during an open takes full effect at the next open, would close it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Noted in FR16 in 86a921a: an anchor change during an open moves the menu at once, and the off-screen hold (spec:AST-059 FR5) follows the new anchor from the next open. I kept the observer change out of this PR. The layer's visibility effect is shared by every layer, and re-subscribing it when the anchor changes is a separate fix to useLayer.

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so approval needs a maintainer to provide the governing spec for the new anchorRef prop, by approving or rejecting the proposed FR16, DEC-9 and Menu anchor concept, and to settle the points below. Separately, please fix one small issue whatever that decision is: FR16's new sentence says an anchor change during an open moves the menu at once, but the menu only re-reads anchorRef when it renders, so with a sibling anchor beside a memoized menu it stays on its trigger when that anchor mounts mid-open and is left for a frame with no anchor, at the viewport's top-left, when it unmounts; narrowing FR16 and DEC-9 to what the code guarantees, or following the element without a menu render, plus a test, would close it.

  • Whether the off-screen hold may follow the previous anchor for the rest of an open under spec:AST-059 FR4, FR5 and FR7, or the layer must re-observe a changed anchor first.
  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may mean positioning-only here, when Popover's and Tooltip's referenced anchor is also the control.

[Automated review]

| FR13 | On a mouse, a nested flyout stays open while the pointer is inside the triangle from where it left its row to the flyout's near edge — including while the pointer is paused there — and closes after the existing delay once the pointer has left both the row and that triangle. The row's click toggle and its guard window are unchanged. | Proposed in this change; `DropdownMenuSubMenu.test.tsx` safe-triangle suite, `useMenuHover.test.tsx` | Proposed; verified in jsdom, pending owner review |
| FR14 | A compound `DropdownMenuGroup` is one `role="group"` named by its heading through `aria-labelledby`; the heading carries `dropdown-menu-section-heading`, is plain text rather than a menu item, and is skipped by roving focus and typeahead. An untitled group is an unnamed `role="group"`. | DEC-1, docs, and tests | Proposed; awaiting owner approval |
| FR15 | With `header` or `footer`, the pointer popover holds the header, then the `role="menu"` element, then the footer, and the menu element holds only its rows. A region keeps its own keys and presses: neither the menu's key handling nor its press model claims an event that begins there. The menu is one Tab stop between the regions. Tab from the menu moves to the footer, and Shift+Tab to the header, when that region holds a control Tab can reach; otherwise Tab closes the menu as before. Tab past the footer's last control or Shift+Tab before the header's first closes the menu, and focus returns to the trigger. From a row of an open sub-menu, Tab and Shift+Tab close every open flyout and continue as they do from a row of the root menu. Escape closes from anywhere in the popover. The bottom sheet shows the header above the actions and the footer below them. Without either, the menu renders and behaves exactly as it does without the props. | DEC-8, docs, and tests | Proposed; awaiting owner approval |
| FR16 | With `anchorRef`, the pointer menu MUST be placed against the referenced element, with `placement` and `alignment` read against it and its default minimum width that element's width, still capped by the viewport, while the Trigger button keeps focus and focus return (FR6), the press model (FR8), the keyboard opens and the menu's name (FR9); a press on that element outside the trigger is a press outside the menu and dismisses it. Without it, or while its ref is empty, the trigger is the anchor. An anchor change during an open moves the menu at once; the off-screen hold (`spec:AST-059` FR5) follows it from the next open. The touch sheet ignores it. | Proposed DEC-9; `component:Popover` `anchorRef` | Proposed; verified in jsdom and Chromium, pending owner review |

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 first half of the new sentence holds only when the anchor change also re-renders the menu: the anchor effect in DropdownMenu.tsx runs on menu renders. With a sibling anchor beside a memoized menu, the menu stayed on its trigger in Chromium after the anchor mounted mid-open, and when the anchor unmounted it sat for one frame at the viewport's top-left, with no element carrying its anchor name, before the layer's observer re-rendered it onto the trigger. DEC-9's "never placed against nothing" has the same gap. Stating what the code guarantees (the menu reads anchorRef whenever it renders, including at every open), or following the element without depending on a menu render, would close it; a memoized-menu case would lock it in.

The second half (the hold follows the element observed at open) is a question for the maintainer under spec:AST-059 FR4, FR5 and FR7.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Narrowed in 37516c6. FR16 now says the menu reads anchorRef whenever it renders, every open included, rather than observing it, as Popover and BaseTypeahead read theirs. An anchor that mounts or unmounts between renders of the menu is followed at its next render, and the off-screen hold follows the anchor the menu opened against until it closes. DEC-9 drops "never placed against nothing": it now covers an empty ref when the menu renders, states the same read-on-render rule, and rejects observing the document for anchor changes. A new memoized-menu case puts a sibling anchor beside the menu and mounts it mid-open. The menu stays open and keeps an anchor, then follows the row at its next render. That case fails against main's DropdownMenu and passes now; the whole anchorRef suite is 8/8. The off-screen-hold question stays with the maintainer, as you noted.

if (anchorRef == null) {
return;
}
const element = anchorRef.current ?? buttonRef.current;

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 read happens only when DropdownMenuPopover renders. A caller whose anchor mounts or unmounts during an open without re-rendering the menu (for example, a sibling anchor beside a memo-wrapped menu) gets no update: the trigger keeps the anchor after a mount, and after an unmount the layer's position-anchor names an element that is no longer connected until something re-renders the menu (in Chromium the layer's IntersectionObserver does, a frame later). See the comment on FR16.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed by narrowing FR16 and DEC-9 to this read-on-render behavior, in 37516c6 (see the FR16 thread). The code is unchanged: following the element without a render would mean a document-wide DOM observer on every open menu, which DEC-9 now lists as rejected. The memoized-menu case pins the guarantee.

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so approval needs a maintainer to provide the governing spec for the new anchorRef prop, by approving or rejecting the proposed FR16, DEC-9 and Menu anchor concept, and to settle the points below. The narrowed FR16 and DEC-9 now match the code; if the maintainer holds spec:AST-059 FR8 for this case, the menu must not paint without an anchor when such an anchor unmounts mid-open, and if FR16 is accepted as written, the prop docs should carry its at-render wording too.

  • Whether FR16 may accept that, when an anchor rendered outside the menu unmounts during an open, the menu paints one frame at the viewport's top-left before moving to its trigger and keeps the old anchor's off-screen hold until it closes (spec:AST-059 FR4, FR5, FR7, FR8).
  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may mean positioning-only here, when Popover's and Tooltip's referenced anchor is also the control.

[Automated review]

name: 'anchorRef',
type: 'React.RefObject<HTMLElement | null>',
description:
"External ref to use as the menu's anchor, as on Popover. The popover presentation is placed against this element, with placement and alignment read against it, and takes its width by default, instead of the trigger's: a menu that lines up with a toolbar or a search row wider than its control. The trigger keeps focus and focus return, the press model, the keyboard opens and the menu's name. While the ref is empty (an element rendered only in some layouts, or a component that does not forward its ref), the trigger is the anchor. Ignored by bottom-sheet presentation.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

If FR16's read-on-render rule is accepted, this sentence should carry it too: an anchor that unmounts while the menu is open empties the ref, but the trigger only becomes the anchor at the menu's next render.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 768353a: the prop's JSDoc, this doc entry and the changeset now carry FR16's read-on-render rule. The ref is read whenever the menu renders, every open included, as on Popover. While it is empty the trigger is the anchor, and an element that mounts or unmounts while the menu is open is followed at the menu's next render. The one-frame paint after an outside anchor unmounts mid-open stays with the maintainer, under spec:AST-059 FR8.

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so approval needs a maintainer to provide the governing spec for the new anchorRef prop, by approving or rejecting the proposed FR16, DEC-9 and Menu anchor concept, and to settle the points below. The prop docs now carry FR16's read-on-render rule; any further change depends on that decision.

  • Whether FR16 may accept that, when an anchor rendered outside the menu unmounts while the menu is open, the menu has no anchor until its next render (one painted frame at the viewport's top-left in Chromium) and keeps the removed anchor's off-screen hold until it closes (spec:AST-059 FR4, FR5, FR7, FR8).
  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may mean positioning-only here, when Popover's and Tooltip's referenced anchor is also the element that opens the overlay.

[Automated review]

interaction fact. A menu that lines up with a box wider than its control, a
toolbar or a search row, needs the first without moving the second: the
trigger keeps focus and focus return, the press model, the keyboard opens and
the menu's name (DEC-3), and only placement, alignment and the default width

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 anchorRef applied, more than placement, alignment and the default width read the anchor: the layer also passes it to the browser as the popover's invoker source (useLayer.tsx, where the comment says the invoker sets the layer's sequential focus order and popover nesting), and its visibility observation, which FR16's off-screen-hold clause relies on, watches it too. If DEC-9 is accepted, this sentence should say so, so the approver sees the whole effect.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 4e0593f (amended from 53609d9 to add the visibility read). DEC-10 now says that placement, alignment, the default width and the layer's anchor-visibility read (spec:AST-059 FR5) follow the anchor. It also says the anchor is the popover's invoker (showPopover({source})), so popover nesting follows it. The invoker's sequential focus order never reaches the menu, because Tab closes it and returns focus to the trigger before the browser moves focus. A new Chromium case covers this: Shift+Tab lands on the field before the trigger. FR16 says the same in its contract clause. The other two points are in the PR comment above.

@vjeux

vjeux commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main 250fd9a as one commit (67a11b0). #7459 recorded DEC-9 (the Menu Button trigger), so this PR's proposed decision is now DEC-10; the concept row and FR16 are unchanged, and the verification row sits in #7459's wider table. The code merged cleanly past #7382 and #7475. DropdownMenu, MoreMenu, Popover, Layer and ContextMenu suites pass (600 tests), as do 28 Chromium tests, typecheck, lint:strict, check:knowledge and the Storybook build.

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so a maintainer needs to provide the governing spec for the new anchorRef prop by approving or rejecting the proposed Menu anchor concept, FR16 and DEC-10, and to settle the points below. Without anchorRef nothing changes and the new tests pass; whether anything else must change depends on that decision.

  • Whether FR16 may accept that, when an anchor rendered outside the menu unmounts while the menu is open, the menu has no anchor until its next render and keeps the removed anchor's off-screen hold until it closes (spec:AST-059 FR4, FR5, FR7, FR8).
  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may mean positioning-only here, when Popover's referenced anchor is also the control, and the element also becomes the popover's invoker, which DEC-10 does not mention.

[Automated review]

@vjeux

vjeux commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

Thanks. 53609d9 writes the three points into the proposed text, so the ruling is on complete wording. No runtime code changed.

  1. FR16 now says it outright. An anchor that unmounts while the menu is open leaves the menu with no anchor until its next render, when the trigger becomes the anchor. The anchor-visibility read stays on the removed element, so the menu keeps its off-screen hold, without the FR4 slide, until it closes. DEC-10 names this as a departure from spec:AST-059 FR4, FR5 and FR8. It lists re-observing a changed anchor in the shared layer as a rejected alternative, alongside observing the document. A new unit case pins each step: no element carries the anchor after the unmount, the trigger carries it after the render, the observer still watches the removed row, and the hold stays.
  2. DEC-10 now states that with anchorRef the handed-back trigger props carry the focus-return target but not the anchor that spec:AST-055 FR2 places in them. The reason is that the anchor is usually an ancestor the render prop does not render.
  3. DEC-10 and FR16 now say the anchor is also the popover's invoker (showPopover({source})). The menu's popover nesting follows the anchor, which can differ from the trigger's only when the two sit in different open popovers. The sequential focus order never reaches the menu, because Tab closes it and returns focus to the trigger first. A new Chromium case checks this: Shift+Tab from the open menu lands on the Search field before the trigger, not before the row. In Chromium's accessibility tree the row gains no relation; only the trigger has hasPopup, expanded and controls. DEC-10 also notes that Popover's anchorRef names its control, while here the trigger stays the control.

The prop docs carry the unmount sentence. The anchorRef suite (7 of 9 fail on main), 601 unit tests, 29 Chromium tests, typecheck, lint:strict, check:knowledge and the Storybook build all pass.

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so a maintainer needs to provide the governing spec for the new anchorRef prop by approving or rejecting the proposed Menu anchor concept, FR19 and DEC-12, including the departures they state. Placement, width, keyboard opens, focus return, dismissal and the empty-ref fallback check out on this revision; optionally, the block comment above the anchor effects in DropdownMenu.tsx could be brought in line with FR19 and DEC-12.

  • Whether an anchor rendered outside the menu that unmounts while it is open may leave it unanchored until its next render and held in place until it closes, against spec:AST-059 FR4, FR5 and FR8.
  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may name an element that anchors the menu and becomes its popover invoker while the trigger stays the control, when Popover's referenced anchor is also the control.

[Automated review]

vjeux added a commit to vjeux/astryx that referenced this pull request Oct 21, 2026
Five open pull requests propose rules in this record: meta#7319 (FR18, DEC-11), meta#7352 (FR19, DEC-12), meta#7530 (FR20, AR7, DEC-13), meta#7532 (FR21, DEC-14) and meta#7541 (FR22, DEC-15). Each takes its own number, so none changes when another merges first. Record wording only.
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 21, 2026
Five open pull requests propose rules in this record: meta#7319 (FR18, DEC-11), meta#7352 (FR19, DEC-12), meta#7530 (FR20, AR7, DEC-13), meta#7532 (FR21, DEC-14) and meta#7541 (FR22, DEC-15). Each takes its own number, so none changes when another merges first. Record wording only.
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 21, 2026
Five open pull requests propose rules in this record: meta#7319 (FR18, DEC-11), meta#7352 (FR19, DEC-12), meta#7530 (FR20, AR7, DEC-13), meta#7532 (FR21, DEC-14) and meta#7541 (FR22, DEC-15). Each takes its own number, so none changes when another merges first. Record wording only.
@vjeux
vjeux force-pushed the dropdown-menu-anchor-ref branch from 3b49c7a to 1585e48 Compare October 21, 2026 19:06

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so a maintainer needs to provide the governing spec for the new anchorRef prop by approving or rejecting the proposed Menu anchor concept, FR19 and DEC-12, including the departures they state. Placement, width, keyboard opens, focus return, dismissal, the empty-ref fallback and the new accessibility-tree case check out on this revision; one optional touch remains: the comment above the anchor effects in DropdownMenu.tsx still ends with "so the menu is never placed against nothing", which FR19 no longer says.

  • Whether an anchor rendered outside the menu that unmounts while it is open may leave it unanchored until its next render and held in place until it closes, against spec:AST-059 FR4, FR5 and FR8.
  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may name an element that anchors the menu and becomes its popover invoker while the trigger stays the control, when Popover's referenced anchor is also the control.

[Automated review]

Comment on lines +1102 to +1103
// is the anchor, as BaseTypeahead falls back to its input, so the menu is
// never placed against nothing.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Non-blocking: this clause predates FR19. With an anchor rendered outside the menu that unmounts while the menu is open, the menu has no anchor until its next render (FR19, DEC-12 and the prop docs say so), so "never placed against nothing" no longer holds. Dropping the clause, and rewrapping line 1092, keeps the comment in step with the proposal.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Dropped in 37933d4, and the comment is rewrapped; it now ends "…the trigger is the anchor, as BaseTypeahead falls back to its input." The same push adds a "Run DropdownMenu anchorRef contract" step to pr-a11y, so this file's real-engine checks gate every head (6 passed locally against a Storybook built from it).

vjeux added a commit to vjeux/astryx that referenced this pull request Oct 21, 2026
Five open pull requests propose rules in this record: meta#7319 (FR18, DEC-11), meta#7352 (FR19, DEC-12), meta#7530 (FR20, AR7, DEC-13), meta#7532 (FR21, DEC-14) and meta#7541 (FR22, DEC-15). Each takes its own number, so none changes when another merges first. Record wording only.
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 21, 2026
Five open pull requests propose rules in this record: meta#7319 (FR18, DEC-11), meta#7352 (FR19, DEC-12), meta#7530 (FR20, AR7, DEC-13), meta#7532 (FR21, DEC-14) and meta#7541 (FR22, DEC-15). Each takes its own number, so none changes when another merges first. Record wording only.
@vjeux
vjeux force-pushed the dropdown-menu-anchor-ref branch from 1585e48 to 37933d4 Compare October 21, 2026 20:06

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so a maintainer needs to provide the governing spec for the new anchorRef prop by approving or rejecting the proposed Menu anchor concept, FR19 and DEC-12, including the departures they state. Placement, width, keyboard opens, focus return, dismissal, the empty-ref fallback and the new pr-a11y step check out on this revision, so nothing else is required from you; one optional touch is the comment over the default width style in DropdownMenu.tsx, which still says the menu prefers the trigger's width.

  • Whether an anchor rendered outside the menu that unmounts while it is open may leave it unanchored until its next render and held in place until it closes, against spec:AST-059 FR4, FR5 and FR8.
  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may name an element that anchors the menu and becomes its popover invoker while the trigger stays the control, when Popover's referenced anchor is also the control.

[Automated review]

cixzhang pushed a commit that referenced this pull request Oct 21, 2026
…#7530)

> Data items' `header` and `footer`, and the bottom sheet's level regions, follow once this merges.

## User need

A sub-menu picking from a long list needs a filter field above its rows, often a "Create" button below. #7344 gave the root menu `header` and `footer`; a sub-menu has neither, so the field goes among the rows (DEC-8 forbids it) or the picker leaves the menu.

## Problem and solution fit

`DropdownMenuSubMenu` takes `header` and `footer` under the root's rules (DEC-8, DEC-10). With either, the sub-menu's surface (the flyout, or the drilled-in view on a phone) is a modal dialog named by its row, holding the header, the sub-menu's `role="menu"` with rows only, and the footer. A flyout renders inside its parent menu, so `DropdownMenu` renders a host beside its menu for the dialog. A drilled-in view with regions replaces the root's menu and regions until popped, by a style rule that reads the host.

```tsx
<DropdownMenuSubMenu label="Labels" header={<TextInput label="Filter labels" … />} footer={<Button label="Create label" … />}>
  {visibleLabelRows}
</DropdownMenuSubMenu>
```

## Current specification

`component:DropdownMenu` (draft) gains a concept row, FR20, AR7 and DEC-13, all proposed and pending owner review. Other proposals in open pull requests: #7319 FR18/DEC-11, #7352 FR19/DEC-12, #7532 FR21/DEC-14, #7541 FR22/DEC-15. `module:DropdownMenu/useMenuPress` (current) gains a proposed ORD1a: a press released on a row of that dialog's menu acts, as FR1 requires for any flyout; a picker placed in its header or footer stays its own press root.

## Public delta and caller burden

- `header` and `footer` on `DropdownMenuSubMenu`.
- With either, the row says `aria-haspopup="dialog"`; Tab walks header, rows as one stop, footer, and wraps; an Escape nothing inside handled returns to the row; a pointer leaving the flyout keeps it open until focus leaves. Rendered beside the root's menu, such a flyout closes with the flyout holding its row.
- Phone drill-in: a shown view follows its regions and caps at the root's `menuMaxHeight`.
- `ContextMenu` renders no host: there the sub-menu shows its rows alone and warns in development; parity follows once this merges.
- Without them, nothing changes.

## Design and alternatives

Rejected: regions inside the flyout (inside the parent menu); a separate `DropdownMenu` per level; closing on pointer-leave, losing typed text. A drilled-in view's header sits above Back.

## Writing rubric results

- R1 narration: none.
- R2 research in a 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: none.
- R6 ruled open questions listing options: none.

## Evidence

See Testing.

## Scope

- [x] One capability is added.
- [x] Unrelated fixes, cleanup, and policy changes were removed or split.
- [x] Consumer docs, focused tests, a story and a changeset ship with the feature.
- [x] Public text and artifacts contain no internal Meta context.

## Testing

Review round 8 (rebased onto `main` b74cf21): `pr-a11y` gets a "Run DropdownMenu sub-menu header and footer contract" step beside "Run DropdownMenu header and footer contract". It runs `SubMenuHeaderFooter.a11y.chromium.spec.ts` with `--project chromium`, so FR20's real-engine checks gate every head. That exact command passes locally against a Storybook built from this head (6 cases). 15 files, +1867/−121 (1,988 lines). DropdownMenu, ContextMenu, Layer, MoreMenu, RadioList, `useMenuPress` and doc-prop suites: 739 tests; header and footer Chromium specs: 16; `.github/scripts` workflow tests: 100; typecheck, `lint:strict`, `check:knowledge`, Storybook build: clean.

Review round 7 (rebased onto `main` 863e167): `surfaceHost`, `surfaceOwnerId` and `menuMaxHeight` leave the exported `DropdownMenuContextValue` for `DropdownMenuSurfaceContext`, which the package does not export, layer-scoped and re-provided by each flyout as the menu context is; the public type matches `main`. A new `DropdownMenuContext.public.test.ts` pins its four members (it fails typecheck with the three back) and checks the internal context is not exported. Data-mode parity (data items' `header` and `footer`, `renderDropdownItems`, the bottom sheet's warning and their tests) moves to the follow-up, and the three pointer-leave cases share one setup: 14 files, +1856/−121 (1,977 lines). DropdownMenu, ContextMenu, Layer, MoreMenu, RadioList, `useMenuPress` and doc-prop suites: 739 tests; header and footer Chromium specs: 16; typecheck, `lint:strict` (no warnings), `check:knowledge`, Storybook build: clean.

Rebased onto `main` d0f9afe, no conflicts or changes. The previous head's `pr-a11y` and `smoke-test` reds came from CI: main's #7802 added a `pr-a11y` step whose spec file the older head lacked, and jsdelivr was still propagating core@0.7.2. DropdownMenu, ContextMenu, RadioList, docProp* suites: 477 tests; typecheck, `check:knowledge`: clean.

Review round 6: a flyout the pointer has left now decides that focus left once the move has completed, so an arrow key in a header radio group, where the browser moves focus itself, no longer closes it. A jsdom case replays the browser's order (focusout, a microtask checkpoint, focusin) and fails on the previous head; a Chromium case on the new "Submenu / header with a choice" story presses ArrowDown after the pointer leaves, and fails against a Storybook built from the previous head, where the flyout closes. DropdownMenu, ContextMenu, Layer, MoreMenu, RadioList, `useMenuPress` and doc-prop suites: 741 tests; header and footer Chromium specs: 16; typecheck, `lint:strict`, `check:knowledge`, Storybook build: clean.

Review round 5 (rebased onto `main` 2c3ed99; the earlier `test` and `test-node` reds were `main`'s own, a PostCSS fixture that #7797 fixed): an Escape a control in a region already handled (a header menu closing, a field clearing itself) closes nothing more, and the new case fails on the previous head. The contract takes FR20, AR7 and DEC-13 so open proposals in this record stay distinct. DropdownMenu, ContextMenu, Layer, MoreMenu, `useMenuPress` and doc-prop suites: 646 tests; header and footer Chromium specs: 15; typecheck, `lint:strict`, `check:knowledge`, Storybook build: clean.

Rebased onto `main` 577a62e after #7737 merged: one commit, 15 files, +1733/−109. DropdownMenu, ContextMenu, Layer, MoreMenu, `useMenuPress` and doc-prop suites: 645 tests; header and footer Chromium specs: 15; typecheck, `lint:strict`, `check:knowledge`, Storybook build: clean.

Review round 4 (amended into the last commit): the surface host is owned through a ref, with only a key in state that changes when a host attaches (it moves when the root's header or footer comes or goes); a drilled-in view with regions caps at the root's `menuMaxHeight`. New cases: the view cap (fails on the previous head) and the host move (a guard). Gates below are for this head.

Round 3, then stacked on #7737: the root steps aside for a view by a style rule over its surface host instead of a drill-in record kept in an Effect; a flyout with regions closes from the `onHide` of the flyout holding its row instead of an Effect; the bottom sheet's level regions moved to a follow-up. Each change has a case that fails with it reverted.

- `DropdownMenuSubMenu.test.tsx` "header and footer" suite: 20 cases, plus one in `ContextMenu.test.tsx` (rows alone, with the warning). They cover the dialog's role, modality, name and row wiring; regions outside every menu; the Tab walk and wrap from a field, a row and a deeper flyout; field keys; Escape, an IME Escape and Escapes a region handled; a press from a menu row released on a dialog row (acts) or its field (outside); a menu placed in a region keeping its own press; pointer-leave with focus inside, focus moving within (a header radio's arrow included), then focus leaving; a nested flyout closing with its parent; the phone drill-in, the root stepping aside, a shown view following its regions and its height cap.
- `__tests__/SubMenuHeaderFooter.a11y.chromium.spec.ts`, real Chromium: six cases (laptop structure, keyboard walk, picks, press-drag pick, a header radio after the pointer leaves; phone drill-in with the root stepped aside).
- iOS 26.2 simulator (Mobile Safari), earlier head: phone drill-in as described above; on `main` the level has no field or button.
@vjeux
vjeux force-pushed the dropdown-menu-anchor-ref branch from 37933d4 to d8f960d Compare October 21, 2026 21:25

@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 a maintainer decision before it can be approved: DropdownMenu.spec.md is still a draft, so a maintainer needs to provide the governing spec for the new anchorRef prop by approving or rejecting the proposed Menu anchor concept, FR19 and DEC-12, including the departures they state. Placement, width, keyboard opens, focus return, dismissal and the empty-ref fallback check out on this revision; the red pr-a11y job comes from a step main added after this branch's base, so a rebase should clear it, and the comment over the default width style in DropdownMenu.tsx still says the menu prefers the trigger's width.

  • Whether an anchor rendered outside the menu that unmounts while it is open may leave it unanchored until its next render and held in place until it closes, against spec:AST-059 FR4, FR5 and FR8.
  • Whether spec:AST-055 FR2, which says the trigger props carry the anchor the overlay positions against, admits an anchor supplied outside those props.
  • Whether anchorRef may name an element that anchors the menu and becomes its popover invoker while the trigger stays the control, when Popover's referenced anchor is also the control.

[Automated review]

@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 can't be approved until a maintainer settles the spec: DropdownMenu.spec.md is a draft, so the governing spec for anchorRef has to come from the record owner approving or rejecting the proposed Menu anchor concept, FR19 and DEC-12, departures included. On this revision placement, width, keyboard opening, focus return and dismissal behave as FR19 describes, so nothing else is needed from you before that ruling; optionally, the comment above popoverMatchTrigger in DropdownMenu.tsx still says the menu prefers the trigger's width.

  • May an anchor that lives outside the menu and unmounts mid-open leave the menu without an anchor until it re-renders, and keep that anchor's off-screen hold until it closes (spec:AST-059 FR4, FR5, FR8)?
  • Does spec:AST-055 FR2, which puts the anchor in the handed-back trigger props, allow an anchor supplied outside them, or should it be amended?
  • Can anchorRef name an element that only positions the menu and becomes its popover invoker, when Popover uses the name for an element that is also the control?

[Automated review]

@vjeux

vjeux commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Six older review threads, each addressed in this branch's commit (b8ebd17):

  • The anchor cleared around each open (1): the anchor is set when the caller's element attaches or changes, and cleared only when the menu unmounts or drops the ref. "the layer watches the anchorRef element, so a menu whose anchor scrolls out of view holds its alignment" asserts that the observer watches it.
  • The code comment (2, 3): the comment above the anchor effects now names the layer's three reads of the anchor (positioning, the visibility hold, the popover's invoker), and the trigger as the anchor while the element is absent.
  • Tab with a header or footer (4, 5): FR19 and the decision text now say Tab closes the menu and returns focus to the trigger first or, with header or footer, wraps in its dialog (FR15).
  • An anchor that unmounts mid-open (6): FR19 states the outcome for the owner's ruling, and "an anchor that unmounts mid-open leaves the menu without one until its next render, then on its trigger, held by the removed anchor" covers the unmount case beside the mount case.

Resolving these six.

…r than its trigger

`anchorRef` (Popover's name and shape) moves the pointer menu's anchor off
the trigger: placement, alignment and the default width read the referenced
element, while the trigger keeps focus and focus return, the press model, the
keyboard opens and the menu's name. While the ref is empty the trigger is the
anchor. The ref is read whenever the menu renders, every open included; the
anchor effects run ahead of the layer's own layout effects, so the layer's
off-screen hold observes the anchor the menu opened against. The bottom sheet
ignores it.

The draft record gains the Menu anchor concept, proposed FR19 and DEC-12: the
anchor gains no role, state or relation for assistive technology, and Tab
closes an anchored menu and returns focus to the trigger, or wraps in its
dialog with a header or footer (FR15). pr-a11y runs the anchorRef Chromium
contract.

Rebased onto main after meta#7530 as one commit; review rounds 1 to 5 are folded
in unchanged.

@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 can't be approved until the spec is settled: DropdownMenu.spec.md is a draft, so the governing spec for anchorRef has to come from an engineering owner approving or amending the proposed Menu anchor concept, FR19 and DEC-12, including the departures they state. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and the author may do so as an engineering owner. On this revision placement, width, keyboard opening, focus return and dismissal behave as FR19 describes, so nothing else is needed from you before that ruling.

  • May an anchor outside the menu that unmounts mid-open leave the menu unanchored until it re-renders, and keep that anchor's off-screen hold until it closes (spec:AST-059 FR4, FR5, FR8)?
  • Does spec:AST-055 FR2, which puts the anchor in the handed-back trigger props, admit an anchor supplied outside them, or should it be amended?
  • Can anchorRef name an element that positions the menu and becomes its popover invoker, when Popover uses the name for an element that is also the control?

[Automated review]

@vjeux

vjeux commented Oct 30, 2026

Copy link
Copy Markdown
Contributor Author

I'm pausing this work for now to reduce contention on the repo. Thank you for the reviews and the spec guidance.

@vjeux vjeux closed this Oct 30, 2026

This branch was successfully deployed

1 active deployment
Preview — 955f58e2 Deployed Oct 26, 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