Skip to content

feat(Tokenizer): presentation is a stable prop, and adaptive is its default - #9796

Merged
imdreamrunner merged 1 commit into
mainfrom
feat/tokenizer-presentation-stable
Nov 3, 2026
Merged

imdreamrunner merged 1 commit into
mainfrom
feat/tokenizer-presentation-stable

Conversation

@imdreamrunner

@imdreamrunner imdreamrunner commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

User need

On a phone, Tokenizer's inline combobox competes with the software keyboard: the suggestion menu opens under the keyboard, and the field moves as tokens wrap. The touch sheet already exists behind experimental.presentation. The owner asked to make it a stable presentation prop and to make adaptive the default. A phone then gets the sheet without each caller opting in. A mouse, a trackpad, a screen that is not compact, the server render and hydration all keep today's inline combobox.

Problem and solution fit

  • Stable prop. presentation?: 'popover' | 'bottom-sheet' | 'adaptive' is added at the top level, typed by the new exported TokenizerPresentation. That is the selection controls' AdaptivePresentation value set. The default is 'adaptive'.
  • Alias. experimental.presentation stays as a deprecated experimental alias (@experimental and @deprecated). When both are set, presentation wins, and the field warns once in development. "Alias decision" below gives the reason.
  • Codemod. The staged promote-tokenizer-presentation codemod rewrites a static experimental={{presentation: x}} to presentation={x}, also past a spread of props that comes before experimental (the {...args} story pattern). It leaves a TODO, and the working alias, where it cannot prove the rewrite, including a spread after experimental. Its own Changeset names @astryxdesign/cli. The repository's own stories are the codemod's output: codemod-verify.mjs reproduces them.
  • ref type. TokenizerProps['ref'] keeps its released Ref<HTMLInputElement> type, so wrappers keep compiling. Under the default, ref reaches the sheet's trigger on a phone, so the component also accepts Ref<HTMLInputElement | HTMLButtonElement>. That overload replaces the one that accepted the wider ref only when experimental was passed.
  • Internal consumers. Composites pin presentation="popover" where they must not change. The table below lists each one.
  • Docs, stories, record. Tokenizer.doc.mjs (en, zh, dense) documents the stable prop and its default, and labels the alias as deprecated. The stories are renamed without "Experimental:" (Bottom sheet, Adaptive (default), Bottom sheet states). The record graduates DEC-3. api-report.md is regenerated.

Current specification

  • component:Tokenizer: DEC-3 (rewritten here), FR16, and Compatibility and migration.
  • spec:AST-017: FR3, FR21–FR23, FR29, and DEC-23.
  • architecture:public-component-api: INV16.
  • component:Selector: DEC-1, DEP-0011 and CLN-0020 are the precedent.

Release tier: patch, by owner decision

One Changeset, [feat], patch. The engineering owner ruled the change nonbreaking and ships it in a patch, and the owner of spec:AST-017 agrees. The record (Compatibility and migration, DEC-3) and the Changeset state the reasons:

  • The API doesn't change. The stable presentation prop is additive: it is new and optional. No existing prop, type or export is removed or narrowed. TokenizerProps['ref'] keeps its released type, and the experimental spelling stays as a deprecated alias.
  • The behavior changes only on phones, which is the point of 'adaptive': compact touch screens get the sheet. Desktop, fine pointers and server rendering are unchanged. presentation="popover" keeps the previous behavior everywhere, and the codemod is available for the alias.
  • Shipping it in a patch is a product decision by the engineering owner, agreed with the owner of spec:AST-017.

Precedent. Selector, MultiSelector, DropdownMenu (and MoreMenu), ContextMenu and Popover already ship a stable presentation with the same three values. component:Selector DEC-1 also makes adaptive the default, with presentation="popover" as the way back. This PR follows the same shape.

Alias decision

experimental.presentation was not removed. It is in the v0.7.7 tag, which was cut today on release/v0.7.7, and that release's CHANGELOG lists it. npm latest still showed 0.7.6 when this PR was written. FR49 makes the newest vX.Y.Z tag the latest stable release, so this experimental surface is released. FR22 would allow an [experimental] removal. FR23 encourages a deprecated alias and asks for a codemod when the rewrite is mechanical, so this PR keeps the alias and adds the codemod. FR29 forbids a runtime warning for plain use, so the only development warning is the precedence warning, shown when both spellings are set.

Internal consumers

The rule is simple. A composite whose design is the inline field pins presentation="popover". An example or template that passes a prop the sheet does not render pins it too, as the development warning asks. Everything else follows the new default.

Use Decision Why
PowerSearch's field (its inline Tokenizer, popover presentation) pin popover PowerSearch owns its own touch flow. Its popover must never turn the field into a Tokenizer sheet.
PowerSearchValueEditor string_list and entity_list isSheet ? 'bottom-sheet' : 'popover' PowerSearch's sheet asks for Tokenizer's sheet. The popover's editor stays inline.
PowerSearchValueEditor enum_list pin popover This editor is used only by the popover; the sheet uses choice rows.
Table filtering plugin, list filter pin popover It is a header or inline filter control. Its Selector and MultiSelector siblings keep popover until CLN-0020.
Blocks TokenizerShowcase, Icon, MaxEntries, States, and Creatable (first field) follow They pass no prop the sheet drops.
Blocks TokenizerClear, EndContent, Overflow (both fields), and Creatable (second field, hasEntriesOnFocus) pin popover Each one demonstrates an inline-only prop.
Template table-inbox, the compose window's To, Cc and Bcc fields pin popover (all three) To carries the Cc and Bcc buttons in endContent and hasAutoFocus. The three rows read as one header, so Cc and Bcc match To.
Template work-item-detail (renderToken) pin popover Its custom tokens need the inline field.
Stories: 15 inline-feature stories (hasClear, endContent, tokenOverflowBehavior, hasEntriesOnFocus, renderToken), 3 of them through args (With Clear All Button, Logical order, Caret placement) pin popover They show those props.
Stories: Default and the other plain stories, BaseTypeahead.stories, Grid.stories follow No prop the sheet drops.
Sandbox tap-targets page (hasClear ×2) pin popover The page measures the inline field's touch targets.
Docsite follows doc.mjs and the blocks —

A new test, Tokenizer.composites.test.tsx, proves the composite pins on a compact coarse-pointer matchMedia: PowerSearch's field, the three list editors and Table's list filter stay inline combobox fields, and PowerSearch's sheet still gets Tokenizer's sheet. When the pins are removed, 5 of its 6 cases fail.

Evidence: the phone interaction lane

The interaction lane runs every *.interaction.browser.spec.ts on a 402×714 touch phone, where the default now presents the sheet. SearchKeyboard.interaction.browser.spec.ts opened the default Tokenizer story and expected a combobox. Its inline case now opens the pinned "With end content" story. A new case taps the default story's trigger and checks that the sheet's search field asks for the Search key with no autocorrection. All 7 cases pass in Chromium on this lane locally, and the full Chromium interaction suite passes (512 passed, 7 skipped).

Evidence: desktop and server unchanged

  • Inline tests unchanged. Tokenizer.test.tsx, PowerSearch.test.tsx and PowerSearchEditPopover.test.tsx are not edited. Their 185 tests pass on this branch as on main.
  • Chromium 149, desktop. The viewport is 1280×800 with no touch (pointer: fine). The DOM is identical to main for all 26 Tokenizer and 35 PowerSearch stories. Screenshots are identical except for caret-placement, which differs because of the blinking caret. The same story differs on the PowerSearch branch, which does not touch Tokenizer. Opening the default Tokenizer menu and the default PowerSearch menu gives identical page markup.
  • Chromium 149, phone. The device is the iPhone 13 profile (pointer: coarse, 390px). On main, the default Tokenizer story renders the combobox. On this branch it renders the trigger, and a tap opens the sheet dialog "Team Members". The "With end content" story is pinned, so it stays a combobox. PowerSearch's default story keeps its inner Tokenizer as a combobox.
  • Server render and hydration. The renderToString output is byte-identical to main for four no-prop cases: a Tokenizer that is empty, a Tokenizer with tokens, hasClear, hasAutoFocus and description, a PowerSearch that is empty, and a PowerSearch with filters and resultCount. Tokenizer.ssr.test.tsx now runs the default with no prop. It server-renders the combobox and hydrates with no recoverable error. On a coarse client it swaps to the trigger with focus undisturbed. Its markup equals presentation="popover"'s.

Bundle

The sizes come from the PR size report's measurer (gzip of the eager import).

Import main branch Δ
Tokenizer JS 73,010 B 73,109 B +99 B (precedence warning, message)
Tokenizer CSS 17,537 B 17,537 B 0
PowerSearch JS 197,409 B 197,513 B +104 B (the pins)
TokenizerBottomSheet (lazy chunk) 88,890 B 88,890 B 0
  • Lazy loading. The sheet still loads only when the field resolves to the sheet. TokenizerBottomSheet is not in any eager chunk of Tokenizer or PowerSearch.
  • Touch-only budget (INV6). No touch-only JavaScript or CSS is added: the sheet code is unchanged and lazy.
  • Single bundle. scripts/core-single-bundle.test.mjs passes.

Scope

  • One capability is added: the stable prop with its default, in one Changeset.
  • Unrelated fixes, cleanup, and policy changes were removed or split. A stale UseLongPressHandlers hunk that api:report regenerates on main is left out.
  • Consumer docs, focused tests, and migration evidence ship with the feature.
  • Public text and artifacts contain no internal Meta context.

Testing

  • vitest. Tokenizer, PowerSearch, Table, BottomSheet, Field, Typeahead, internal/, useAnnounceRenderedText adopters, slotPresence, touchTriggerTargets, the i18n PowerSearch end-to-end test, the CLI codemods, the CLI golden reads, experimental isolation and the single-bundle test: 172 files and 3,357 tests pass.
  • Typecheck. pnpm typecheck passes. It runs every workspace typecheck script, as CI does.
  • Strict lint. ASTRYX_STRICT_LINT=1 eslint on the changed files reports 0 errors. Prettier is clean.
  • check:repo. Every step passes, check:changesets included. sync-exports --check is up to date.
  • Other checks. Changeset coverage names both packages it ships to (@astryxdesign/core, @astryxdesign/cli), and codemod-verify.mjs reproduces the story edits. check:knowledge is aligned. The single-bundle test passes. git diff --check is clean.
  • CLI tests. 27 of 28 files pass. global-local.test.mjs fails locally on npm pack because the local Node install has no npm binary. That is an environment failure; CI runs it.
  • Chromium and the server render. See the evidence above.

Overlap with open work

Writing rubric results

docs/specs/components/Tokenizer/Tokenizer.spec.md:

  • R1 narration: the new Compatibility bullets name the released popover default only to classify the change, and they state the release tier as the owners' product decision. DEC-3 records that decision with its reasons. FR16 states the present contract. No other narration was added.
  • R2 research: none.
  • R3 evidence: none names a PR. The verification row now names the Adaptive (default) and Bottom sheet stories in place of the Experimental stories.
  • R4 rejected alternatives: DEC-3 has one-line rejections. "Keeping popover as the default" was added. Two old lines were removed because this decision overturns them: an automatic switch without an opt-in, and a stable prop before consumer evidence.
  • R5 change references: two links to a PowerSearch draft PR remained from before. Both now point to component:PowerSearch.
  • R6 open questions: one remains open, whether the sheet should honor renderItem and renderToken. It is unanswered and keeps its options.

@vercel

vercel Bot commented Nov 3, 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 3, 2026 9:49pm UTC

Request Review

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

astracat-bot Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟡 Reviewed (for maintainers only) Nov 3, 2026, 10:01 PM UTC

@imdreamrunner

Copy link
Copy Markdown
Contributor Author

/approve-spec 2bab017

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

Current run: The current CI run concluded skipped. Current analysis is unavailable.


Generated by PR Enrichment workflow | View current CI run

astracat-bot[bot]
astracat-bot Bot previously requested changes Nov 3, 2026

@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 stable presentation prop, its adaptive default, the alias, the codemod and the composite pins match the approved Tokenizer record. Two things block merging:

  • packages/core/src/Field/__tests__/SearchKeyboard.interaction.browser.spec.ts (lines 42-47) still expects a combobox on the default Tokenizer story, which the phone interaction lane now renders as the sheet trigger, so pr-interaction will fail once the pull request leaves draft; point that case at a story pinned to presentation="popover" and add a sheet case that taps the "Team Members" trigger and checks the sheet's search field.
  • The [breaking] Changeset cannot merge while main declares 0.7.7 (pnpm check:changesets, AST-017 FR31); merge it after main declares 0.8.0, or land the patch-safe half described in the pull request first.

Optional: the comment at Tokenizer.tsx:796-798 could read "An open sheet keeps its presentation until it closes. A resolution change during a task does not replace the open surface."

[Automated review]

// open sheet keeps its presentation until it closes, so a resolution change
// mid-task cannot pull the surface out from under the person.
const presentation =
presentationProp ?? experimental?.presentation ?? 'adaptive';

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 this default, core-tokenizer--default renders the sheet trigger in the phone interaction lane (402×714, coarse pointer), so the unchanged Tokenizer case in packages/core/src/Field/__tests__/SearchKeyboard.interaction.browser.spec.ts (lines 42-47) no longer finds a combobox. Point that case at a story pinned to presentation="popover" and add a case that opens the sheet and checks its search field.

@@ -0,0 +1,7 @@
---
'@astryxdesign/core': minor

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

pnpm check:changesets refuses this minor [breaking] entry while main declares 0.7.7 (AST-017 FR31). It can merge once main declares 0.8.0; until then the patch-safe half can land on its own.

Comment on lines +796 to +798
// `adaptive` resolves through the policy the selection controls share; an
// open sheet keeps its presentation until it closes, so a resolution change
// mid-task cannot pull the surface out from under the person.

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 is one 32-word sentence with three topics and an idiom. Suggested:

// An open sheet keeps its presentation until it closes. A resolution change
// during a task does not replace the open surface.

@imdreamrunner
imdreamrunner force-pushed the feat/tokenizer-presentation-stable branch from 2bab017 to d53419d Compare November 3, 2026 19:39
@imdreamrunner

Copy link
Copy Markdown
Contributor Author

/approve-spec d53419d

astracat-bot[bot]
astracat-bot Bot previously requested changes Nov 3, 2026

@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 stable presentation prop, its adaptive default, the deprecated alias, the codemod and the composite pins match the Tokenizer record approved at this head, and the earlier phone-lane test and comment findings are fixed. Two things block merging:

  • The [breaking] Changeset (.changeset/tokenizer-presentation-default-adaptive.md) cannot merge while main declares 0.7.7 (pnpm check:changesets, AST-017 FR31); merge it after main declares 0.8.0, or land the patch-safe half described in the pull request first.
  • Line 63 of docs/specs/components/Tokenizer/Tokenizer.spec.md has unescaped | inside 'popover' | 'bottom-sheet' | 'adaptive', so GitHub renders the Public contract row as "A stable presentation prop, 'popover'" and drops the rest; escape both pipes as |` and restore the spaces around the code spans.

[Automated review]

| Governing rules | This canonical `component:Tokenizer` record: [FR13–FR27](#behavioral-and-layout-contract), [AR5–AR6](#accessibility-contract), [DEC-2](#dec-2--focus-bootstrap-supports-consecutive-committed-selections), [DEC-3](#dec-3--the-touch-sheet-presentation-is-an-experimental-option), and [DEC-4](#dec-4--the-sheet-edits-a-draft-that-save-commits). |
| Area | Contract |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Public contract | A stable `presentation` prop, `'popover' | 'bottom-sheet' | 'adaptive'`with`adaptive`the default, selects the surface (DEC-3); the sheet edits a draft committed by Save (DEC-4).`TokenizerProps`stays an interface; its`ref`is`Ref<HTMLInputElement \| HTMLButtonElement>`because it reaches the sheet's trigger.`experimental.presentation`stays as a deprecated experimental alias. The existing`hasEntriesOnFocus` mode has a defined post-selection lifecycle (DEC-2). |

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 code span holds two unescaped |, so GitHub-flavoured Markdown splits the row into four cells and drops the last two: the row renders as "A stable presentation prop, 'popover'" and the rest of the contract disappears. Escape both as |, as Ref<HTMLInputElement | HTMLButtonElement>` already is, and restore the spaces the formatter removed around the code spans:

| Public contract | A stable `presentation` prop, `'popover' \| 'bottom-sheet' \| 'adaptive'` with `adaptive` the default, selects the surface (DEC-3); the sheet edits a draft committed by Save (DEC-4). `TokenizerProps` stays an interface; its `ref` is `Ref<HTMLInputElement \| HTMLButtonElement>` because it reaches the sheet's trigger. `experimental.presentation` stays as a deprecated experimental alias. The existing `hasEntriesOnFocus` mode has a defined post-selection lifecycle (DEC-2). |

@@ -0,0 +1,7 @@
---
'@astryxdesign/core': minor

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

pnpm check:changesets refuses this minor [breaking] entry while main declares 0.7.7 (AST-017 FR31). Merge it after main declares 0.8.0, or land the patch-safe half described in the pull request first.

@imdreamrunner
imdreamrunner force-pushed the feat/tokenizer-presentation-stable branch from d53419d to a089127 Compare November 3, 2026 21:27
@imdreamrunner
imdreamrunner marked this pull request as ready for review November 3, 2026 21:27
@imdreamrunner

Copy link
Copy Markdown
Contributor Author

/approve-spec a089127

…efault

Tokenizer's touch sheet presentation graduates from
`experimental.presentation` to a stable top-level `presentation` prop
(`'popover' | 'bottom-sheet' | 'adaptive'`, typed by the new exported
`TokenizerPresentation`), and an omitted `presentation` resolves
`adaptive`: the sheet on a compact coarse-pointer screen, and the inline
combobox with a fine pointer, on a screen that is not compact, on the
server, and while hydrating.

`experimental.presentation` stays as a deprecated experimental alias; the
top-level prop wins when both are set, with one development warning. A
staged codemod rewrites a static `experimental={{presentation: x}}` to
`presentation={x}`.

Core composites that render Tokenizer as an inline field pin
`presentation="popover"`: PowerSearch's field and its list value editors,
and Table's list filter. Stories, blocks, templates, and the sandbox page
that pass a prop the sheet does not render pin it too.

The default change is `[breaking]` under spec:AST-017 FR1, FR3, and FR31,
so it is held for a declared minor; the promotion is `[feat]`.
@imdreamrunner
imdreamrunner force-pushed the feat/tokenizer-presentation-stable branch from a089127 to 2bd3a08 Compare November 3, 2026 21:37
@imdreamrunner

Copy link
Copy Markdown
Contributor Author

/approve-spec 2bd3a08

astracat-bot[bot]
astracat-bot Bot previously requested changes Nov 3, 2026

@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 stable presentation prop, the deprecated alias, the codemod and the composite pins match the Tokenizer record approved at this head, and the earlier test, comment and record-formatting findings are fixed. One thing blocks merging:

  • The adaptive default changes a released functional contract on phones (onChange timing, the ref element and the inline-only props), so spec:AST-017 FR1 and FR3 classify it as breaking, and FR6, FR31 and FR54 allow it only as a [breaking] Changeset in a declared minor, not as the patch [feat] in .changeset/tokenizer-presentation-stable.md while main declares 0.7.7.

To fix it, restore the [breaking] entry and merge once main declares 0.8.0, or land the stable prop with a popover default as a patch now and flip the default in the minor; either way, drop the patch-tier sentences from the Tokenizer record and the Changeset. If the owners want this default in a patch, spec:AST-017 has to change on main first.

[Automated review]

'@astryxdesign/core': patch
---

[feat] Tokenizer's `presentation` prop is stable, and its default is `'adaptive'`. `presentation` takes `'popover' | 'bottom-sheet' | 'adaptive'`, typed by the new exported `TokenizerPresentation`. The API change is additive: the prop is new and optional, no existing prop, type or export is removed or narrowed (`TokenizerProps['ref']` keeps its input type, and the component also accepts a ref typed `Ref<HTMLInputElement | HTMLButtonElement>`), and `experimental={{presentation: x}}` keeps working as a deprecated experimental alias that `astryx upgrade` rewrites to `presentation={x}`; when both are set, `presentation` wins and the field warns once in development. The behavior changes only on compact coarse-pointer screens (phones), which is what `'adaptive'` is for: there a Tokenizer with no `presentation` shows a trigger that opens the bottom sheet, the sheet edits a draft so `onChange` reports once, on Save, `ref` receives the trigger button, and `renderItem`, `renderToken`, `endContent`, `hasClear`, `hasEntriesOnFocus`, `menuWidth`, `tokenOverflowBehavior` and `hasAutoFocus` are not rendered, with one development warning that names them. With a mouse or trackpad, on a screen that is not compact, in the server render and while hydrating, nothing changes. Pass `presentation="popover"` to keep the previous behavior on every device. Shipping this default in a patch is a product decision of the engineering owner, agreed with the owner of the compatibility policy.

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 entry ships the adaptive default as a patch [feat]. On a phone, a released caller that uses renderToken, endContent or hasClear, saves on each onChange, or calls input methods on ref must add presentation="popover" to keep working. spec:AST-017 FR1 and FR3 make that a breaking change. FR6 and FR54 say an owner decision cannot make it patch-eligible, and FR31 refuses [breaking] while main declares 0.7.7. Restore the [breaking] entry and merge once main declares 0.8.0. Or ship the prop with a popover default now and flip the default in the minor.

* stays the component's declared props type: it is an interface, so
* `interface X extends TokenizerProps<T>`, `Omit<TokenizerProps<T>, …>` and
* `ComponentProps<typeof Tokenizer>` keep their released shapes.
* The props the component accepts: `TokenizerProps`, whose `ref` keeps its

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: the first sentence restates the type below it. Keep only the reason:

/**
 * `TokenizerProps` stays the declared props type, so `interface X extends
 * TokenizerProps<T>`, `Omit<TokenizerProps<T>, …>` and
 * `ComponentProps<typeof Tokenizer>` keep their released shapes.
 */

@imdreamrunner
imdreamrunner dismissed stale reviews from astracat-bot[bot], astracat-bot[bot], and astracat-bot[bot] November 3, 2026 22:03

Owner ruling (engineering owner), agreed with the AST-017 owner: the stable presentation prop and its adaptive default ship as a [feat] patch. The API does not change (the stable prop is new and optional; the experimental spelling stays as a deprecated alias); the behavior change is on compact touch screens only, by design of adaptive, with desktop and server rendering unchanged; presentation="popover" and the codemod keep the previous behavior. Every other review item is resolved at 2bd3a08.

@imdreamrunner
imdreamrunner enabled auto-merge (squash) November 3, 2026 22:03
@imdreamrunner
imdreamrunner merged commit dcf3d6f into main Nov 3, 2026
70 checks passed

This branch was successfully deployed

1 active deployment
Preview — 2bd3a08f Deployed Nov 3, 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