Repository navigation
feat(FieldStatus): deprecate the tooltip variant; field controls keep statusVariant="tooltip" #9196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
56c1f9e
9251bd6
4d45182
c63d90b
8315c10
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| --- | ||
| '@astryxdesign/core': patch | ||
| --- | ||
|
|
||
| [feat] FieldStatus: the `tooltip` variant is deprecated and is removed in the next minor release. FieldStatus has no tooltip presentation: a direct `<FieldStatus variant="tooltip">` draws a plain message box with no tooltip, and your editor now marks it deprecated. To show a status message from a field's on-field icon, set `statusVariant="tooltip"` on the field control instead; that stays supported. | ||
|
|
||
| Before: | ||
|
|
||
| ```tsx | ||
| <FieldStatus type="error" message="Required" variant="tooltip" /> | ||
| ``` | ||
|
|
||
| After: | ||
|
|
||
| ```tsx | ||
| <TextInput | ||
| label="Name" | ||
| value={name} | ||
| onChange={setName} | ||
| status={{type: 'error', message: 'Required'}} | ||
| statusVariant="tooltip" | ||
| /> | ||
| ``` | ||
|
|
||
| @cixzhang | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| '@astryxdesign/richtext': patch | ||
| --- | ||
|
|
||
| [chore] RichTextEditor: `statusVariant` names `'tooltip'` in its own type, so it keeps accepting `statusVariant="tooltip"` after FieldStatus drops its deprecated `tooltip` variant in the next minor release. No behavior change. | ||
|
|
||
| @cixzhang |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // Copyright (c) Meta Platforms, Inc. and affiliates. | ||
|
|
||
| /** | ||
| * @file fieldStatusPlacement.ts | ||
| * @input The FieldStatus variant map | ||
| * @output FieldStatusPlacement, where a field control shows its status | ||
| * @position Field family type behind every field control's `statusVariant` | ||
| * | ||
| * A field control places its status message as a FieldStatus variant, or under | ||
| * `'tooltip'`, which the Field family consumes before rendering FieldStatus and | ||
| * shows through the control's on-field status icon (`component:FieldStatus` | ||
| * FR7, DEC-2). `'tooltip'` belongs here, not to FieldStatus itself, whose map | ||
| * keeps it only as a deprecated entry until the next minor. | ||
| */ | ||
|
|
||
| import type {FieldStatusVariantMap} from '../FieldStatus'; | ||
|
|
||
| export type FieldStatusPlacement = keyof FieldStatusVariantMap | 'tooltip'; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No package entry exports this, so |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| // Copyright (c) Meta Platforms, Inc. and affiliates. | ||
|
|
||
| /** | ||
| * @file FieldStatus.deprecation.test.ts | ||
| * @input The TypeScript language service and FieldStatus.tsx | ||
| * @output Verifies an editor marks a direct `variant="tooltip"` deprecated, | ||
| * and leaves the supported variants and Field-family placements unmarked | ||
| * @position Static deprecation evidence for `component:FieldStatus` FR7 | ||
| * (`spec:AST-017` FR29a: the warning lives in the declarations) | ||
| */ | ||
|
|
||
| import path from 'node:path'; | ||
| import {fileURLToPath} from 'node:url'; | ||
| import ts from 'typescript'; | ||
| import {describe, expect, it} from 'vitest'; | ||
|
|
||
| const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||
| const CORE_ROOT = path.resolve(__dirname, '../..'); | ||
| const FIXTURE = path.join(__dirname, '__deprecation_fixture__.tsx'); | ||
|
|
||
| const SOURCE = ` | ||
| import {FieldStatus} from './FieldStatus'; | ||
| import type {FieldStatusVariant} from './FieldStatus'; | ||
| import {TextInput} from '../TextInput/TextInput'; | ||
|
|
||
| declare const someVariant: FieldStatusVariant; | ||
|
|
||
| export const direct = <FieldStatus type="error" message="m" variant="tooltip" />; | ||
| export const attached = <FieldStatus type="error" message="m" variant="attached" />; | ||
| export const detached = <FieldStatus type="error" message="m" variant="detached" />; | ||
| export const typed = <FieldStatus type="error" message="m" variant={someVariant} />; | ||
| export const field = ( | ||
| <TextInput label="Name" value="" onChange={() => {}} status={{type: 'error', message: 'm'}} statusVariant="tooltip" /> | ||
| ); | ||
| `; | ||
|
|
||
| function deprecatedLines(): number[] { | ||
| const configPath = path.join(CORE_ROOT, 'tsconfig.json'); | ||
| const config = ts.readConfigFile(configPath, ts.sys.readFile); | ||
| const parsed = ts.parseJsonConfigFileContent( | ||
| config.config, | ||
| ts.sys, | ||
| CORE_ROOT, | ||
| undefined, | ||
| configPath, | ||
| ); | ||
| const files = new Map([[FIXTURE, SOURCE]]); | ||
| const host: ts.LanguageServiceHost = { | ||
| getScriptFileNames: () => [FIXTURE], | ||
| getScriptVersion: () => '1', | ||
| getScriptSnapshot: name => { | ||
| const text = files.get(name) ?? ts.sys.readFile(name); | ||
| return text == null ? undefined : ts.ScriptSnapshot.fromString(text); | ||
| }, | ||
| getCurrentDirectory: () => CORE_ROOT, | ||
| getCompilationSettings: () => ({...parsed.options, noEmit: true}), | ||
| getDefaultLibFileName: options => ts.getDefaultLibFilePath(options), | ||
| fileExists: name => files.has(name) || ts.sys.fileExists(name), | ||
| readFile: name => files.get(name) ?? ts.sys.readFile(name), | ||
| readDirectory: ts.sys.readDirectory, | ||
| directoryExists: ts.sys.directoryExists, | ||
| getDirectories: ts.sys.getDirectories, | ||
| }; | ||
| const service = ts.createLanguageService(host); | ||
| const errors = service.getSemanticDiagnostics(FIXTURE); | ||
| expect( | ||
| errors.map(d => ts.flattenDiagnosticMessageText(d.messageText, '\n')), | ||
| ).toEqual([]); | ||
| const source = service.getProgram()!.getSourceFile(FIXTURE)!; | ||
| return service | ||
| .getSuggestionDiagnostics(FIXTURE) | ||
| .filter(d => d.reportsDeprecated) | ||
| .map(d => source.getLineAndCharacterOfPosition(d.start ?? 0).line); | ||
| } | ||
|
|
||
| function lineOf(name: string): number { | ||
| return SOURCE.split('\n').findIndex(line => line.includes(`const ${name} =`)); | ||
| } | ||
|
|
||
| describe('FieldStatus tooltip deprecation (component:FieldStatus FR7)', () => { | ||
| it('marks a direct variant="tooltip" deprecated and nothing else', () => { | ||
| const lines = deprecatedLines(); | ||
| expect(lines).toEqual([lineOf('direct')]); | ||
| }, 120_000); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,13 @@ | |
| export interface FieldStatusVariantMap { | ||
| attached: true; | ||
| detached: true; | ||
| /** | ||
| * @deprecated FieldStatus has no `tooltip` presentation | ||
| * (`component:FieldStatus` FR7): given it directly, it draws a plain message | ||
| * box with no tooltip. 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. | ||
| */ | ||
|
Comment on lines
+28
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TypeScript reports this tag only where the member is referenced ( |
||
| tooltip: true; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TextInputProps.valueis required, so this example fails with TS2741 as written. AddvalueandonChange.