From bdb9460d0a9156dd541683e9eed57b5c1db91f4f Mon Sep 17 00:00:00 2001 From: cixzhang Date: Wed, 22 Jul 2026 12:34:55 +0000 Subject: [PATCH 1/2] feat(inputs): add statusVariant to the bordered input family (#4187) --- .changeset/input-status-variant.md | 7 ++++ apps/storybook/stories/DateInput.stories.tsx | 28 +++++++++++++++ .../stories/DateRangeInput.stories.tsx | 24 +++++++++++++ apps/storybook/stories/FileInput.stories.tsx | 24 +++++++++++++ .../stories/MultiSelector.stories.tsx | 29 +++++++++++++++ .../storybook/stories/NumberInput.stories.tsx | 24 +++++++++++++ .../storybook/stories/PowerSearch.stories.tsx | 28 +++++++++++++++ apps/storybook/stories/Selector.stories.tsx | 35 +++++++++++++++++++ apps/storybook/stories/TextArea.stories.tsx | 24 +++++++++++++ apps/storybook/stories/TextInput.stories.tsx | 24 +++++++++++++ apps/storybook/stories/TimeInput.stories.tsx | 28 +++++++++++++++ apps/storybook/stories/Tokenizer.stories.tsx | 26 ++++++++++++++ apps/storybook/stories/Typeahead.stories.tsx | 26 ++++++++++++++ packages/core/src/DateInput/DateInput.doc.mjs | 15 ++++++++ .../core/src/DateInput/DateInput.test.tsx | 23 ++++++++++++ packages/core/src/DateInput/DateInput.tsx | 10 ++++++ .../src/DateRangeInput/DateRangeInput.doc.mjs | 8 +++++ .../DateRangeInput/DateRangeInput.test.tsx | 23 ++++++++++++ .../src/DateRangeInput/DateRangeInput.tsx | 10 ++++++ packages/core/src/FileInput/FileInput.doc.mjs | 15 ++++++++ .../core/src/FileInput/FileInput.test.tsx | 23 ++++++++++++ packages/core/src/FileInput/FileInput.tsx | 10 ++++++ .../src/MultiSelector/MultiSelector.doc.mjs | 9 +++++ .../src/MultiSelector/MultiSelector.test.tsx | 23 ++++++++++++ .../core/src/MultiSelector/MultiSelector.tsx | 10 ++++++ .../core/src/NumberInput/NumberInput.doc.mjs | 15 ++++++++ .../core/src/NumberInput/NumberInput.test.tsx | 23 ++++++++++++ packages/core/src/NumberInput/NumberInput.tsx | 10 ++++++ .../core/src/PowerSearch/PowerSearch.doc.mjs | 15 ++++++++ .../core/src/PowerSearch/PowerSearch.test.tsx | 23 ++++++++++++ packages/core/src/PowerSearch/PowerSearch.tsx | 11 +++++- packages/core/src/Selector/Selector.doc.mjs | 7 ++++ packages/core/src/Selector/Selector.test.tsx | 23 ++++++++++++ packages/core/src/Selector/Selector.tsx | 10 ++++++ packages/core/src/TextArea/TextArea.doc.mjs | 15 ++++++++ packages/core/src/TextArea/TextArea.test.tsx | 23 ++++++++++++ packages/core/src/TextArea/TextArea.tsx | 10 ++++++ packages/core/src/TextInput/TextInput.doc.mjs | 15 ++++++++ .../core/src/TextInput/TextInput.test.tsx | 23 ++++++++++++ packages/core/src/TextInput/TextInput.tsx | 10 ++++++ packages/core/src/TimeInput/TimeInput.doc.mjs | 15 ++++++++ .../core/src/TimeInput/TimeInput.test.tsx | 23 ++++++++++++ packages/core/src/TimeInput/TimeInput.tsx | 10 ++++++ packages/core/src/Tokenizer/Tokenizer.doc.mjs | 15 ++++++++ .../core/src/Tokenizer/Tokenizer.test.tsx | 23 ++++++++++++ packages/core/src/Tokenizer/Tokenizer.tsx | 10 ++++++ packages/core/src/Typeahead/Typeahead.doc.mjs | 7 ++++ .../core/src/Typeahead/Typeahead.test.tsx | 23 ++++++++++++ packages/core/src/Typeahead/Typeahead.tsx | 10 ++++++ 49 files changed, 874 insertions(+), 1 deletion(-) create mode 100644 .changeset/input-status-variant.md diff --git a/.changeset/input-status-variant.md b/.changeset/input-status-variant.md new file mode 100644 index 000000000000..68504ddce8df --- /dev/null +++ b/.changeset/input-status-variant.md @@ -0,0 +1,7 @@ +--- +'@astryxdesign/core': patch +--- + +[feat] The bordered input family now accepts a `statusVariant` prop (`'attached' | 'detached'`, default `'attached'`) that forwards to the underlying `Field`, letting you float the status message below the input with spacing instead of overlapping it. Added to TextInput, TextArea, NumberInput, DateInput, DateRangeInput, TimeInput, Selector, MultiSelector, Typeahead, Tokenizer, FileInput, and PowerSearch. Non-breaking: the default matches today's behavior. (#4187) + +@cixzhang diff --git a/apps/storybook/stories/DateInput.stories.tsx b/apps/storybook/stories/DateInput.stories.tsx index 720471811754..11c4f10d0579 100644 --- a/apps/storybook/stories/DateInput.stories.tsx +++ b/apps/storybook/stories/DateInput.stories.tsx @@ -366,3 +366,31 @@ export const ClearableWithStatus: Story = { status: {type: 'error', message: 'Date is in the past'}, }, }; + +export const StatusVariantComparison: Story = { + render: () => { + const [a, setA] = useState( + '2026-01-25' as ISODateString, + ); + const [b, setB] = useState( + '2026-01-25' as ISODateString, + ); + return ( +
+ + +
+ ); + }, +}; diff --git a/apps/storybook/stories/DateRangeInput.stories.tsx b/apps/storybook/stories/DateRangeInput.stories.tsx index db147a678320..d01fd5032d43 100644 --- a/apps/storybook/stories/DateRangeInput.stories.tsx +++ b/apps/storybook/stories/DateRangeInput.stories.tsx @@ -333,3 +333,27 @@ export const AllVariations: Story = { ); }, }; + +export const StatusVariantComparison: Story = { + render: () => { + const [a, setA] = useState(null); + const [b, setB] = useState(null); + return ( +
+ + +
+ ); + }, +}; diff --git a/apps/storybook/stories/FileInput.stories.tsx b/apps/storybook/stories/FileInput.stories.tsx index 0aae44b88269..e71fee85a638 100644 --- a/apps/storybook/stories/FileInput.stories.tsx +++ b/apps/storybook/stories/FileInput.stories.tsx @@ -282,3 +282,27 @@ export const AllVariations: Story = { ); }, }; + +export const StatusVariantComparison: Story = { + render: () => { + const [a, setA] = useState(null); + const [b, setB] = useState(null); + return ( +
+ + +
+ ); + }, +}; diff --git a/apps/storybook/stories/MultiSelector.stories.tsx b/apps/storybook/stories/MultiSelector.stories.tsx index 31129b2e266f..0a3fb54b5c00 100644 --- a/apps/storybook/stories/MultiSelector.stories.tsx +++ b/apps/storybook/stories/MultiSelector.stories.tsx @@ -405,3 +405,32 @@ export const Clearable: Story = { placeholder: 'Select technologies...', }, }; + +export const StatusVariantComparison: Story = { + render: () => { + const [a, setA] = useState([]); + const [b, setB] = useState([]); + return ( +
+ + +
+ ); + }, + decorators: [Story => ], +}; diff --git a/apps/storybook/stories/NumberInput.stories.tsx b/apps/storybook/stories/NumberInput.stories.tsx index bbe2f378149d..ca16963abab6 100644 --- a/apps/storybook/stories/NumberInput.stories.tsx +++ b/apps/storybook/stories/NumberInput.stories.tsx @@ -555,3 +555,27 @@ export const ClearableWithUnits: Story = { max: 100, }, }; + +export const StatusVariantComparison: Story = { + render: () => { + const [a, setA] = useState(-5); + const [b, setB] = useState(-5); + return ( +
+ + +
+ ); + }, +}; diff --git a/apps/storybook/stories/PowerSearch.stories.tsx b/apps/storybook/stories/PowerSearch.stories.tsx index 154a3b7cb433..f471a0665d96 100644 --- a/apps/storybook/stories/PowerSearch.stories.tsx +++ b/apps/storybook/stories/PowerSearch.stories.tsx @@ -1375,3 +1375,31 @@ export const DisabledWithMessage: Story = { placeholder: 'Search...', }, }; + +export const StatusVariantComparison: Story = { + render: () => { + const [a, setA] = useState([]); + const [b, setB] = useState([]); + return ( +
+ setA([...newFilters])} + isLabelHidden={false} + label="Attached (default)" + status={{type: 'error', message: 'Add at least one filter'}} + /> + setB([...newFilters])} + isLabelHidden={false} + label="Detached" + status={{type: 'error', message: 'Add at least one filter'}} + statusVariant="detached" + /> +
+ ); + }, +}; diff --git a/apps/storybook/stories/Selector.stories.tsx b/apps/storybook/stories/Selector.stories.tsx index 574d42388767..eaffea17797f 100644 --- a/apps/storybook/stories/Selector.stories.tsx +++ b/apps/storybook/stories/Selector.stories.tsx @@ -603,3 +603,38 @@ export const PlacementAbove: Story = { ); }, }; + +export const StatusVariantComparison: Story = { + render: () => { + const [a, setA] = useState(); + const [b, setB] = useState(); + return ( +
+ + +
+ ); + }, + decorators: [Story => ], +}; diff --git a/apps/storybook/stories/TextArea.stories.tsx b/apps/storybook/stories/TextArea.stories.tsx index 45178076c5e2..ee55a25e419b 100644 --- a/apps/storybook/stories/TextArea.stories.tsx +++ b/apps/storybook/stories/TextArea.stories.tsx @@ -635,3 +635,27 @@ export const MaxLengthVariations: Story = { ); }, }; + +export const StatusVariantComparison: Story = { + render: () => { + const [a, setA] = useState('Too short'); + const [b, setB] = useState('Too short'); + return ( +
+