Skip to content

feat(FieldStatus): deprecate the tooltip variant; field controls keep statusVariant="tooltip" - #9196

Merged
cixzhang merged 5 commits into
mainfrom
fix/fieldstatus-tooltip-deprecate
Nov 1, 2026
Merged

cixzhang merged 5 commits into
mainfrom
fix/fieldstatus-tooltip-deprecate

Conversation

@cixzhang

@cixzhang cixzhang commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Who this helps

  • Someone writing <FieldStatus variant="tooltip"> directly: their editor now marks that call deprecated and names what to use. Today it draws a plain message box with no tooltip, with no hint why.
  • Everyone else: nothing changes. A field control's statusVariant="tooltip" (TextInput, Selector, DateInput and the rest) keeps working and stays supported.

Change

  • A deprecated signature for a direct tooltip. FieldStatus gets a @deprecated overload for variant: 'tooltip' ahead of its general signature, so an editor marks that call. Every other call, including a value typed FieldStatusVariant, resolves to the general signature, which ComponentProps<typeof FieldStatus> reads. FieldStatusVariantMap.tooltip carries the same @deprecated note. Both name the replacement (the field control's statusVariant="tooltip") and say it is removed in the next minor release. It stays until then, so existing callers still compile.
  • Field family type: every field control's statusVariant now uses a Field-local type, FieldStatusPlacement = keyof FieldStatusVariantMap | 'tooltip' (Field/fieldStatusPlacement.ts). No package entry re-exports it. When the next minor drops tooltip from the public map, these props are unaffected. Outside core, RichTextEditor and Lab's MobilePowerSearch type statusVariant as FieldStatusVariant | 'tooltip' for the same reason.
  • No runtime warning. spec:AST-017 FR29 says a deprecation adds no runtime behavior; a development-only diagnostic is only for an ambiguous old-and-new coexistence, which this is not. FR29a puts the warning in static @deprecated metadata.
  • Changeset: [feat] (spec:AST-017 FR7), with a before/after migration. A second [chore] patch Changeset covers @astryxdesign/richtext for RichTextEditor's type.

Current specification

  • component:FieldStatus FR7 and DEC-2: direct FieldStatus supports only attached and detached; the Field family consumes tooltip before rendering FieldStatus.
  • architecture:public-component-api INV9 and spec:AST-017 FR7, FR28, FR29 and FR29a: a patch stages the removal compatibly, with static deprecation metadata and a migration.

Evidence

  • FieldStatus.deprecation.test.ts (TypeScript language service): only the direct variant="tooltip" call is reported deprecated; attached, detached, a FieldStatusVariant-typed value and TextInput's statusVariant="tooltip" compile unmarked.
  • tsc -p packages/core: clean, so existing callers compile.
  • FieldStatus, Field, TextInput, TextArea and useInputStatusIcon suites pass (410), including the field controls' tooltip placement.
  • pnpm check:changesets and pnpm check:knowledge: clean. The Changeset's TextInput example passes the required value and onChange.

LOC

+183 / −38: about 37 lines across 16 field controls (one import and one type name each), the overloads and docs in FieldStatus and its map, the 18-line type module, the deprecation test (about 95 lines), and the Changeset.

Scope

  • One change: deprecating the FieldStatus tooltip variant.
  • tooltip is not removed; removal waits for the next minor.
  • No record change.
  • Public text contains no internal context.

… statusVariant="tooltip"

component:FieldStatus FR7 and DEC-2: direct FieldStatus supports only attached
and detached, and the Field family consumes tooltip before rendering
FieldStatus. FieldStatusVariantMap.tooltip is marked @deprecated, naming the
field control's statusVariant="tooltip" as the replacement, and stays until
the next minor. Every field control's statusVariant now takes a Field-local
FieldStatusPlacement (keyof FieldStatusVariantMap | 'tooltip'), so dropping
tooltip from the public map later leaves them unchanged. No runtime warning
(spec:AST-017 FR29, FR29a). [feat] Changeset with migration.
@vercel

vercel Bot commented Oct 31, 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 5:30am UTC

Request Review

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

astracat-bot Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Nov 1, 2026, 5:38 AM UTC

@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · 8315c10

Storybook · Sandbox · built from this PR's head

Modified components

Component Size LoC
BaseTypeahead 56.9 kB (not measured) · 10.2 kB CSS (not measured) —
CheckboxInput 52.5 kB (not measured) · 9.6 kB CSS (not measured) —
CheckboxList 47.7 kB (not measured) · 8.5 kB CSS (not measured) —
48 more components
Component Size LoC
CheckboxListItem 57.1 kB (not measured) · 11.0 kB CSS (not measured) —
ComplexSelector · Storybook 59.0 kB (not measured) · 11.0 kB CSS (not measured) 680 (not measured)
ContextMenu 77.4 kB (not measured) · 15.2 kB CSS (not measured) —
DateInput · Storybook 103.0 kB (not measured) · 15.1 kB CSS (not measured) 3,609 (not measured)
DateRangeInput · Storybook 72.4 kB (not measured) · 11.5 kB CSS (not measured) 640 (not measured)
DateTimeInput 114.4 kB (not measured) · 15.6 kB CSS (not measured) —
DropdownMenu 75.3 kB (not measured) · 15.4 kB CSS (not measured) —
Field 45.8 kB (not measured) · 8.3 kB CSS (not measured) —
FieldLabel 39.6 kB (not measured) · 5.9 kB CSS (not measured) —
FieldStatus · Storybook 9.4 kB (not measured) · 3.6 kB CSS (not measured) 163 (not measured)
FileInput · Storybook 56.9 kB (not measured) · 10.7 kB CSS (not measured) 739 (not measured)
InputGroup 46.4 kB (not measured) · 8.3 kB CSS (not measured) —
ListItem 56.5 kB (not measured) · 11.0 kB CSS (not measured) —
Markdown 147.7 kB (not measured) · 18.2 kB CSS (not measured) —
MoreMenu 75.6 kB (not measured) · 15.4 kB CSS (not measured) —
MultiSelector · Storybook 75.4 kB (not measured) · 15.0 kB CSS (not measured) 2,701 (not measured)
NumberInput · Storybook 58.5 kB (not measured) · 11.0 kB CSS (not measured) 1,151 (not measured)
Pagination 87.9 kB (not measured) · 15.7 kB CSS (not measured) —
PowerSearch · Storybook 171.7 kB (not measured) · 20.3 kB CSS (not measured) 3,958 (not measured)
RadioList 47.2 kB (not measured) · 8.3 kB CSS (not measured) —
RadioListItem 55.0 kB (not measured) · 10.0 kB CSS (not measured) —
Selector 79.5 kB (not measured) · 15.4 kB CSS (not measured) —
SelectorOption 15.9 kB (not measured) · 5.4 kB CSS (not measured) —
Slider 50.4 kB (not measured) · 8.8 kB CSS (not measured) —
Switch 50.9 kB (not measured) · 9.7 kB CSS (not measured) —
Table 87.2 kB (not measured) · 15.9 kB CSS (not measured) —
TableCell 78.6 kB (not measured) · 15.7 kB CSS (not measured) —
TableHeaderCell 78.2 kB (not measured) · 15.4 kB CSS (not measured) —
TextArea · Storybook 51.1 kB (not measured) · 9.7 kB CSS (not measured) 474 (not measured)
TextInput · Storybook 56.2 kB (not measured) · 10.8 kB CSS (not measured) 391 (not measured)
TimeInput · Storybook 91.3 kB (not measured) · 14.1 kB CSS (not measured) 1,256 (not measured)
Tokenizer · Storybook 71.6 kB (not measured) · 16.9 kB CSS (not measured) 1,953 (not measured)
Typeahead 64.4 kB (not measured) · 11.6 kB CSS (not measured) —
TypeaheadItem 6.3 kB (not measured) · 3.6 kB CSS (not measured) —
lab/ChatEmojiPicker 68.0 kB (not measured) · 773 B CSS (not measured) —
lab/ChatReactionBar 68.6 kB (not measured) · 1.1 kB CSS (not measured) —
lab/CommentComposer 97.2 kB (not measured) · 1.9 kB CSS (not measured) —
lab/Comments 224.8 kB (not measured) · 2.5 kB CSS (not measured) —
lab/CommentThread 220.2 kB (not measured) · 2.4 kB CSS (not measured) —
lab/EmojiPicker 66.0 kB (not measured) · 722 B CSS (not measured) —
lab/ListInput 77.9 kB (not measured) · 1.6 kB CSS (not measured) —
lab/MobilePowerSearch · Storybook 158.2 kB (not measured) · 1.2 kB CSS (not measured) 3,224 (not measured)
lab/MobileTokenizer 95.5 kB (not measured) · 880 B CSS (not measured) —
lab/TransferList 69.9 kB (not measured) · 1.7 kB CSS (not measured) —
lab/TransferListSelector 75.6 kB (not measured) · 1.9 kB CSS (not measured) —
richtext/RichTextEditor · Storybook 272.6 kB (not measured) · 2.6 kB CSS (not measured) 662 (not measured)
richtext/RichTextEditorToolbar 215.9 kB (not measured) · 454 B CSS (not measured) —
richtext/RichTextView 253.0 kB (not measured) · 2.3 kB CSS (not measured) —

Package size:

  • @astryxdesign/core 6.52 MB packed (+1.3 kB); no new dependencies
  • @astryxdesign/richtext 190.5 kB packed (+11 B); no new dependencies

Not run on this PR: add ci:run-visual, ci:run-a11y or ci:run-rtl to run them.


Generated by PR Enrichment workflow | View full report

@astracat-bot astracat-bot Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Requesting changes: the direction matches the FieldStatus contract, but the deprecation doesn't reach callers yet, and the release note misdescribes how a direct tooltip behaves today.

  • TypeScript reports the @deprecated member only at FieldStatusVariantMap['tooltip'], not at <FieldStatus variant="tooltip">, so the deprecation needs a form editors flag at that call, such as a deprecated FieldStatus overload for variant: 'tooltip'.
  • A direct <FieldStatus variant="tooltip"> renders a visible detached-style box without the status glyph, so the Changeset and JSDoc should say that, name variant="detached" as the direct replacement, and give the TextInput example its required value.
  • RichTextEditor and Lab's MobilePowerSearch still type statusVariant as FieldStatusVariant, and FieldStatusPlacement isn't exported, so both need migrating in this patch or they lose tooltip at removal.

[Automated review]

Comment on lines +28 to +33
/**
* @deprecated FieldStatus does not render a `tooltip` status: it shows no
* message box (`component:FieldStatus` FR7). Set `statusVariant="tooltip"`
* on the field control (TextInput, Selector, and the rest), which shows the
* message from its on-field status icon. Removed in the next minor release.
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

TypeScript reports this tag only where the member is referenced (FieldStatusVariantMap['tooltip'], map.tooltip). <FieldStatus variant="tooltip"> and const v: FieldStatusVariant = 'tooltip' get no deprecation, and completions offer 'tooltip' unmarked (checked with the TypeScript 6.0.3 language service). A @deprecated FieldStatus overload for variant: 'tooltip' is flagged at that call alone. This text also says FieldStatus shows no message box, but it renders one: detached spacing, no glyph.

'@astryxdesign/core': patch
---

[feat] FieldStatus: the `tooltip` variant is deprecated and is removed in the next minor release. FieldStatus renders no message box for it, so a direct `<FieldStatus variant="tooltip">` shows nothing. To show a status message from a field's on-field icon, set `statusVariant="tooltip"` on the field control instead; that stays supported.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A direct <FieldStatus variant="tooltip"> doesn't show nothing. FieldStatus renders the message in a visible box with detached spacing and the status colours but no glyph (FieldStatus.tsx:206, :213). For a custom control, the like-for-like replacement is variant="detached", which is the same box plus the status glyph; the field-control route fits only callers who can switch components.

Comment on lines +16 to +20
<TextInput
label="Name"
status={{type: 'error', message: 'Required'}}
statusVariant="tooltip"
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

TextInputProps.value is required, so this example fails with TS2741 as written. Add value and onChange.


import type {FieldStatusVariantMap} from '../FieldStatus';

export type FieldStatusPlacement = keyof FieldStatusVariantMap | 'tooltip';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No package entry exports this, so @astryxdesign/richtext can't adopt it. RichTextEditor.tsx:373, and Lab's MobilePowerSearch.tsx:210, still declare statusVariant?: FieldStatusVariant, which the announced removal would narrow. AST-017 FR29c asks for maintained packages to migrate in the deprecation patch.

@cixzhang
cixzhang marked this pull request as ready for review October 31, 2026 20:22
… signature, and the Changeset says what it draws

CodeBunny on #9196: @deprecated on the map entry never surfaced at
<FieldStatus variant="tooltip">, and FieldStatus does draw a message box
for it. FieldStatus now has a deprecated overload for variant: 'tooltip'
ahead of its general one, so an editor marks that call, while every other
call, a FieldStatusVariant-typed value included, resolves to the general
signature. A language-service test checks only the direct tooltip is marked
and every case compiles. The Changeset, the map JSDoc and the component docs
say it draws a plain message box with no tooltip.

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

Requesting changes: a direct <FieldStatus variant="tooltip"> is now flagged deprecated at the call, but one maintained component and the migration example still need fixing.

  • RichTextEditor (and Lab's MobilePowerSearch) still type statusVariant as FieldStatusVariant, so they lose tooltip when the map member is removed; typing it as keyof FieldStatusVariantMap | 'tooltip' keeps it and migrates them in this patch.
  • The Changeset's After example renders <TextInput> without its required value, so it fails to compile as written; add value and onChange.

[Automated review]

… itself; the migration example compiles

CodeBunny on #9196: RichTextEditor (and Lab's MobilePowerSearch) typed
statusVariant as FieldStatusVariant alone, so 'tooltip' reached them only
through the deprecated map entry. They now take FieldStatusVariant |
'tooltip', like core's field controls, and TransferList's doc names the
three placements. The Changeset's TextInput example passes value and
onChange, which TextInput requires.

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

Requesting changes: both earlier points are fixed (RichTextEditor and MobilePowerSearch now keep 'tooltip' themselves, and the migration example compiles), but the RichTextEditor change needs its own release note. The only Changeset names @astryxdesign/core, so the lint job's Changeset coverage step fails for @astryxdesign/richtext; adding a Changeset for that package (pnpm changeset:new --packages @astryxdesign/richtext) clears it.

[Automated review]

* @default 'attached'
*/
statusVariant?: FieldStatusVariant;
statusVariant?: FieldStatusVariant | 'tooltip';

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 changes the published @astryxdesign/richtext surface, but the only Changeset names @astryxdesign/core, so CI's Changeset coverage step fails on this file. A Changeset for @astryxdesign/richtext (pnpm changeset:new --packages @astryxdesign/richtext) covers it.

…iant type

CodeBunny on #9196: the RichTextEditor type change touches the published
@astryxdesign/richtext surface, so it gets its own Changeset (spec:AST-017
FR7).

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

Requesting changes for one small documentation regression: the deprecation itself is in good shape (only a direct variant="tooltip" is flagged, and @astryxdesign/richtext now has its own Changeset), but moving the component JSDoc onto the general overload left the implementation signature without it, so Storybook's FieldStatus Docs page now shows no description. Repeating that JSDoc directly above the implementation (or setting the story's docs.description.component) fixes it. Optionally, the Changeset could also name variant="detached" for custom controls that can't switch to a field control.

[Automated review]

* />
* ```
*/
export function FieldStatus(props: FieldStatusProps): React.JSX.Element;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Storybook's docgen reads the JSDoc above the implementation on the next line, not this overload's, so CI's Storybook build for this head documents FieldStatus with an empty description. Repeating the description directly above the implementation fixes it; this copy keeps the editor hover.

… where Storybook reads them

CodeBunny on #9196: with the docs on an overload, Storybook's docgen, which
reads the implementation, showed FieldStatus with no description. The full
JSDoc is back on the implementation; the general overload keeps a short
summary and example for editor hovers.

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

Looks ready to merge: a direct <FieldStatus variant="tooltip"> is now flagged deprecated at the call, every field control keeps statusVariant="tooltip", and FieldStatus's Storybook description is back on the implementation. Every earlier point is addressed, and the new language-service test fails if the deprecated overload is removed. Optionally, the Changeset could name variant="detached" for custom controls that can't switch to a field control, and tell code that types a field control's statusVariant as FieldStatusVariant to use the control's own prop type before the removal.

[Automated review]

@cixzhang
cixzhang merged commit 8f345cb into main Nov 1, 2026
52 checks passed

This branch was successfully deployed

1 active deployment
Preview — 8315c100 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