@agentero/design-system 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mcp/manifests/components.html +384 -103
- package/mcp/manifests/components.json +191 -20
- package/package.json +5 -1
- package/src/combobox/combobox.d.ts +12 -7
- package/src/combobox/combobox.js +79 -62
- package/src/field/context.d.ts +6 -2
- package/src/field/field.d.ts +4 -2
- package/src/field/field.js +30 -27
- package/src/field/index.d.ts +1 -1
- package/src/field-text/field-text.d.ts +1 -1
- package/src/form-text/form-text.d.ts +4 -4
- package/src/form-text/form-text.js +2 -2
- package/src/input-search/icons.d.ts +16 -0
- package/src/input-search/icons.js +23 -0
- package/src/input-search/index.d.ts +2 -0
- package/src/input-search/index.js +2 -0
- package/src/input-search/input-search.d.ts +96 -0
- package/src/input-search/input-search.js +53 -0
|
@@ -2798,7 +2798,7 @@
|
|
|
2798
2798
|
"id": "components-combobox--default",
|
|
2799
2799
|
"name": "Default",
|
|
2800
2800
|
"snippet": "const Default = () => (\n <Combobox.Root items={STATES}>\n <Combobox.Input placeholder=\"Search states\" aria-label=\"Search states\" />\n <Combobox.Content>\n <Combobox.Empty>No matches found</Combobox.Empty>\n <Combobox.List>\n {(state: string) => (\n <Combobox.Item key={state} value={state}>\n {state}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n);",
|
|
2801
|
-
"description": "The common case: options are already in memory and Base UI filters them against\nwhat you type. Selecting a row fills the input and closes the list. The field is\na search out of the box — a magnifier in front, a clear button once
|
|
2801
|
+
"description": "The common case: options are already in memory and Base UI filters them against\nwhat you type. Selecting a row fills the input and closes the list. The field is\na search out of the box — a magnifier in front, a clear button once there is\ntext — and the list hangs from the whole field. Clearing drops the picked option.",
|
|
2802
2802
|
"summary": "Search field with a magnifier and clear button over an in-memory list"
|
|
2803
2803
|
},
|
|
2804
2804
|
{
|
|
@@ -2837,20 +2837,20 @@
|
|
|
2837
2837
|
{
|
|
2838
2838
|
"id": "components-combobox--async-search",
|
|
2839
2839
|
"name": "Async Search",
|
|
2840
|
-
"snippet": "const AsyncSearch = () => {\n const [query, setQuery] = useState('');\n\n return (\n // No `items` and `filter={null}`: the server did the filtering, the child renders what came\n // back, and `isItemEqualToValue` keeps a re-fetched copy counting as the selected one.\n <Combobox.Root\n filter={null}\n itemToStringLabel={(agency: Agency) => agency.name}\n isItemEqualToValue={(a: Agency, b: Agency) => a.id === b.id}\n onInputValueChange={(value, { reason }) => {\n // Picking a row writes its label into the input; that is not a new search.\n if (reason !== 'item-press') setQuery(value);\n }}>\n <Combobox.Input placeholder=\"Search agencies\" aria-label=\"Search agencies\" />\n <Combobox.Content>\n <Suspense fallback={<SkeletonRows />}>\n <AgencyItems query={
|
|
2841
|
-
"description": "Options fetched as you type, the way the apps load data: the rows are a component\nthat suspends on the request, so a `Suspense` boundary inside `Content` shows\nplaceholder rows until
|
|
2840
|
+
"snippet": "const AsyncSearch = () => {\n const [query, setQuery] = useState('');\n // The rows read the deferred query: while the new one suspends, React keeps rendering the\n // old rows instead of falling back to the placeholders.\n const deferredQuery = useDeferredValue(query);\n const isStale = query !== deferredQuery;\n\n return (\n // No `items` and `filter={null}`: the server did the filtering, the child renders what came\n // back, and `isItemEqualToValue` keeps a re-fetched copy counting as the selected one.\n <Combobox.Root\n filter={null}\n itemToStringLabel={(agency: Agency) => agency.name}\n isItemEqualToValue={(a: Agency, b: Agency) => a.id === b.id}\n onInputValueChange={(value, { reason }) => {\n // Picking a row writes its label into the input; that is not a new search.\n if (reason !== 'item-press') setQuery(value);\n }}>\n <Combobox.Input placeholder=\"Search agencies\" aria-label=\"Search agencies\" />\n <Combobox.Content aria-busy={isStale || undefined}>\n <Suspense fallback={<SkeletonRows />}>\n <AgencyItems query={deferredQuery} />\n </Suspense>\n </Combobox.Content>\n </Combobox.Root>\n );\n};",
|
|
2841
|
+
"description": "Options fetched as you type, the way the apps load data: the rows are a component\nthat suspends on the request, so a `Suspense` boundary inside `Content` shows\nplaceholder rows until the first results land. The rows read a deferred copy of\nthe query, so a new search keeps the previous rows on screen while it loads and\n`Content` is marked busy until they are replaced; the placeholders never come\nback. Nothing tracks `loading` by hand, and reading the data by query is what\nmakes out-of-order responses harmless. With react-query, drop a\n`useSuspenseQuery` where `use()` is, or use `placeholderData: keepPreviousData`\nwith a plain `useQuery` for the same behaviour."
|
|
2842
2842
|
},
|
|
2843
2843
|
{
|
|
2844
2844
|
"id": "components-combobox--async-search-with-status",
|
|
2845
2845
|
"name": "Async Search With Status",
|
|
2846
|
-
"snippet": "const AsyncSearchWithStatus = () => {\n const [results, setResults] = useState<Agency[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n // Only the latest request may land; fast typing returns responses out of order.\n const latestRequest = useRef(0);\n\n const onInputValueChange = async (query: string) => {\n const request = ++latestRequest.current;\n if (query.trim().length < MIN_QUERY_LENGTH) {\n setResults([]);\n setIsLoading(false);\n return;\n }\n\n // The previous rows
|
|
2847
|
-
"description": "The same search without Suspense, for a consumer that gets a `loading` flag from\nits data layer instead: `filter={null}`, the rows arrive through `filteredItems`,\n`Content` is marked busy and `Status` announces the wait.
|
|
2846
|
+
"snippet": "const AsyncSearchWithStatus = () => {\n const [results, setResults] = useState<Agency[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n // Only the latest request may land; fast typing returns responses out of order.\n const latestRequest = useRef(0);\n\n const onInputValueChange = async (query: string) => {\n const request = ++latestRequest.current;\n if (query.trim().length < MIN_QUERY_LENGTH) {\n setResults([]);\n setIsLoading(false);\n return;\n }\n\n // The previous rows stay through the wait, marked busy, rather than blinking out and back.\n setIsLoading(true);\n const agencies = await searchAgencies(query);\n if (request !== latestRequest.current) return;\n\n setResults(agencies);\n setIsLoading(false);\n };\n\n return (\n // `filter={null}` hands filtering to the server; `filteredItems` is what came back.\n <Combobox.Root\n items={results}\n filteredItems={results}\n filter={null}\n minInputLength={MIN_QUERY_LENGTH}\n itemToStringLabel={(agency: Agency) => agency.name}\n isItemEqualToValue={(a: Agency, b: Agency) => a.id === b.id}\n onInputValueChange={onInputValueChange}>\n <Combobox.Input placeholder=\"Search agencies\" aria-label=\"Search agencies\" />\n <Combobox.Content aria-busy={isLoading || undefined}>\n {/* The rows show the wait; `Status` only announces it. */}\n <Combobox.Status className=\"sr-only\">\n {isLoading ? 'Searching…' : undefined}\n </Combobox.Status>\n {isLoading && results.length === 0 && <SkeletonRows />}\n <Combobox.Empty>{isLoading ? undefined : 'No agencies found'}</Combobox.Empty>\n <Combobox.List>\n {(agency: Agency) => (\n <Combobox.Item key={agency.id} value={agency}>\n {agency.name}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n );\n};",
|
|
2847
|
+
"description": "The same search without Suspense, for a consumer that gets a `loading` flag from\nits data layer instead: `filter={null}`, the rows arrive through `filteredItems`,\n`Content` is marked busy and `Status` announces the wait. Placeholder rows show\nonly while there is nothing to show yet; after that, the previous rows stay\nuntil the new ones replace them. A request that is no longer the latest is\ndropped.\n\n`minInputLength` keeps the list shut until two characters are typed — focusing\nthe field opens nothing, and deleting back under the minimum closes it — and\nno request goes out for a shorter query either.",
|
|
2848
2848
|
"summary": "API search that waits for two characters, with loading status"
|
|
2849
2849
|
},
|
|
2850
2850
|
{
|
|
2851
2851
|
"id": "components-combobox--inside-field-text",
|
|
2852
2852
|
"name": "Inside Field Text",
|
|
2853
|
-
"snippet": "const InsideFieldText = () => (\n <FieldText invalid required>\n <Label>Agency</Label>\n <Combobox.Root items={STATES}>\n <Combobox.Input placeholder=\"Search agencies\" />\n <Combobox.Content>\n <Combobox.Empty>No matches found</Combobox.Empty>\n <Combobox.List>\n {(state: string) => (\n <Combobox.Item key={state} value={state}>\n {state}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n <Field.
|
|
2853
|
+
"snippet": "const InsideFieldText = () => (\n <FieldText invalid required>\n <Label>Agency</Label>\n <Combobox.Root items={STATES}>\n <Combobox.Input placeholder=\"Search agencies\" />\n <Combobox.Content>\n <Combobox.Empty>No matches found</Combobox.Empty>\n <Combobox.List>\n {(state: string) => (\n <Combobox.Item key={state} value={state}>\n {state}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n <Field.Error errors={[{ message: 'Pick an agency from the list' }]} />\n <Field.Description>The agency this agent will be added to.</Field.Description>\n </FieldText>\n);",
|
|
2854
2854
|
"description": "Dropped into a `FieldText`, the input takes the label, the description and\nthe error from the field with nothing wired by hand: `Combobox.Input` reads the\nsame `InputContext` the plain `Input` does. It also points `aria-labelledby`\nat the label, so the name survives the list opening: Base UI then hides the\nrest of the page from assistive technology, label included, and a\n`<label for>` alone would stop naming the input."
|
|
2855
2855
|
},
|
|
2856
2856
|
{
|
|
@@ -5295,7 +5295,7 @@
|
|
|
5295
5295
|
"Field for a single-line text control, wiring the Input inside it"
|
|
5296
5296
|
],
|
|
5297
5297
|
"example": [
|
|
5298
|
-
"<FieldText invalid={!!error} required>\n <Label>Email</Label>\n <Input type=\"email\" />\n <Field.Description>We only use this for policy documents.</Field.Description>\n
|
|
5298
|
+
"<FieldText invalid={!!error} required>\n <Label>Email</Label>\n <Input type=\"email\" />\n <Field.Error errors={[error]} />\n <Field.Description>We only use this for policy documents.</Field.Description>\n</FieldText>"
|
|
5299
5299
|
]
|
|
5300
5300
|
},
|
|
5301
5301
|
"description": "FieldText is a `Field.Root` for a single-line text control. It provides\n`InputContext`, so the `Input` inside associates itself with the label and\nthe messages and takes `invalid`, `required`, `disabled` and `readOnly` from\nthe field — no `id`, `htmlFor`, `aria-describedby` or `aria-invalid` written\nby hand.\n\nIt knows nothing about form libraries, and its contexts compose: a provider\nnested inside it can extend `InputContext` with `value`, `onChange`, `onBlur`\nand `name`, and `FieldContext` with the errors, as the last story shows.",
|
|
@@ -5310,7 +5310,7 @@
|
|
|
5310
5310
|
"Field for a single-line text control, wiring the Input inside it"
|
|
5311
5311
|
],
|
|
5312
5312
|
"example": [
|
|
5313
|
-
"<FieldText invalid={!!error} required>\n <Label>Email</Label>\n <Input type=\"email\" />\n <Field.Description>We only use this for policy documents.</Field.Description>\n
|
|
5313
|
+
"<FieldText invalid={!!error} required>\n <Label>Email</Label>\n <Input type=\"email\" />\n <Field.Error errors={[error]} />\n <Field.Description>We only use this for policy documents.</Field.Description>\n</FieldText>"
|
|
5314
5314
|
]
|
|
5315
5315
|
},
|
|
5316
5316
|
"props": {
|
|
@@ -5504,7 +5504,7 @@
|
|
|
5504
5504
|
"Wraps a label, control, description and error into one field"
|
|
5505
5505
|
],
|
|
5506
5506
|
"example": [
|
|
5507
|
-
"<Field.Root invalid={!!error} required>\n <Field.Label>Email</Field.Label>\n <Input type=\"email\" />\n <Field.Description>We only use this for policy documents.</Field.Description>\n
|
|
5507
|
+
"<Field.Root invalid={!!error} required>\n <Field.Label>Email</Field.Label>\n <Input type=\"email\" />\n <Field.Error errors={[error]} />\n <Field.Description>We only use this for policy documents.</Field.Description>\n</Field.Root>"
|
|
5508
5508
|
]
|
|
5509
5509
|
},
|
|
5510
5510
|
"description": "Field lays out a single form field — label, control, helper text and error —\nand wires the accessibility relationships between them. `Field.Root`\ngenerates the ids and shares them through context: `Label` reads\n`LabelContext`, `Field.Description` and `Field.Error` read `FieldContext`,\nand a `Field<X>` such as `FieldText` provides the control's context. Nobody\npasses an `id` by hand.\n\nPresentational and form-library agnostic: pass `invalid` and the error\nmessages from whatever validates the form. Spacing between fields belongs to\n`Field.Group`, never to a margin on the field itself.\n\n`Field.Description` and `Field.Error` register themselves with the root, so\nthe control's `aria-describedby` lists exactly the messages on screen and is\nabsent when there is none.",
|
|
@@ -5519,7 +5519,7 @@
|
|
|
5519
5519
|
"Wraps a label, control, description and error into one field"
|
|
5520
5520
|
],
|
|
5521
5521
|
"example": [
|
|
5522
|
-
"<Field.Root invalid={!!error} required>\n <Field.Label>Email</Field.Label>\n <Input type=\"email\" />\n <Field.Description>We only use this for policy documents.</Field.Description>\n
|
|
5522
|
+
"<Field.Root invalid={!!error} required>\n <Field.Label>Email</Field.Label>\n <Input type=\"email\" />\n <Field.Error errors={[error]} />\n <Field.Description>We only use this for policy documents.</Field.Description>\n</Field.Root>"
|
|
5523
5523
|
]
|
|
5524
5524
|
},
|
|
5525
5525
|
"props": {
|
|
@@ -5718,6 +5718,13 @@
|
|
|
5718
5718
|
"description": "`Field.Error` renders nothing without a message, so it can stay mounted and\nreceive `undefined` entries while the field is valid. With no description\neither, the control carries no `aria-describedby` at all.",
|
|
5719
5719
|
"summary": "Error stays mounted and renders nothing while valid"
|
|
5720
5720
|
},
|
|
5721
|
+
{
|
|
5722
|
+
"id": "components-field--error-before-description",
|
|
5723
|
+
"name": "Error Before Description",
|
|
5724
|
+
"snippet": "const ErrorBeforeDescription = () => {\n const [error, setError] = useState<string>();\n\n return (\n <div className=\"flex flex-col items-start gap-4\">\n <Field.Root\n orientation=\"vertical\"\n disabled={false}\n readOnly={false}\n required={false}\n invalid={!!error}>\n <Label>Tax ID</Label>\n <DemoInput inputMode=\"numeric\" />\n <Field.Error id=\"tax-id-error\">{error}</Field.Error>\n <Field.Description>Nine digits, with or without the dash.</Field.Description>\n </Field.Root>\n <button type=\"button\" onClick={() => setError('Enter the tax ID.')}>Validate\n </button>\n </div>\n );\n};",
|
|
5725
|
+
"description": "The error sits right under the control and is announced before the\ndescription, even when it appears after the description is on screen and\ncarries an `id` of its own.",
|
|
5726
|
+
"summary": "Error announced before the description, whenever it appears"
|
|
5727
|
+
},
|
|
5721
5728
|
{
|
|
5722
5729
|
"id": "components-field--disabled",
|
|
5723
5730
|
"name": "Disabled",
|
|
@@ -5795,7 +5802,7 @@
|
|
|
5795
5802
|
"displayName": "FormText",
|
|
5796
5803
|
"exportName": "FormText",
|
|
5797
5804
|
"filePath": "/home/runner/work/design-system/design-system/src/form-text/index.ts",
|
|
5798
|
-
"description": "A complete text field bound to one react-hook-form value: label, `Input`,\
|
|
5805
|
+
"description": "A complete text field bound to one react-hook-form value: label, `Input`,\nvalidation error and helper text, laid out in the standard order and wired\nthrough `useController`. It renders inside a `Form.Root`, which provides the\nform, and needs only a `name`, which on a typed form must point at a string\n(`FormTextPath`). The `required`, `invalid` and error states\nreach the label, the input's `aria-*` attributes and the message with no\nids written by hand.\n\nUse it for the common case: a labelled single-line input in a form. When\nthe layout is different — an input with addons, another control, a\nmessage rendered elsewhere — compose the primitives yourself:\n`useController` with [FieldText](?path=/docs/components-fieldtext--docs),\n`Label`, `Input`, `Field.Description` and `Field.Error`. `FormText` adds no\nbehaviour of its own over that composition.\n\nErrors come from `useController`'s per-field state, never from\n`formState.errors`, so the message stays fresh under the React Compiler.\nWith `criteriaMode: 'all'` on the form the error carries every rule that\nfailed and `Field.Error` lists them all. An error on an array or object path\n(`error.root`) is not this field's: render a `Field.Error` for it where the\ngroup lives.",
|
|
5799
5806
|
"jsDocTags": {
|
|
5800
5807
|
"summary": [
|
|
5801
5808
|
"Label, Input, description and error bound to one react-hook-form field"
|
|
@@ -6021,7 +6028,7 @@
|
|
|
6021
6028
|
"type": {
|
|
6022
6029
|
"name": "ReactNode"
|
|
6023
6030
|
},
|
|
6024
|
-
"description": "Helper text shown under the control
|
|
6031
|
+
"description": "Helper text shown under the control, below the error when there is one,\nand announced through its `aria-describedby`. Use it for guidance the\nuser needs before typing; put details worth a click in `tooltip` instead.",
|
|
6025
6032
|
"defaultValue": null,
|
|
6026
6033
|
"parent": {
|
|
6027
6034
|
"name": "FormTextProps",
|
|
@@ -6156,6 +6163,13 @@
|
|
|
6156
6163
|
"description": "`rules` are react-hook-form's, and `name` accepts nested paths typed against\nthe form's values through the generic. `rules.required` validates but does\nnot mark the field required: that stays an explicit `required` prop.",
|
|
6157
6164
|
"summary": "Nested path with validation rules, typed through the generic"
|
|
6158
6165
|
},
|
|
6166
|
+
{
|
|
6167
|
+
"id": "components-formtext--error-and-description",
|
|
6168
|
+
"name": "Error And Description",
|
|
6169
|
+
"snippet": "const ErrorAndDescription = () => {\n const methods = useForm<TaxValues>({ defaultValues: { taxId: '' } });\n\n return (\n <Form.Root\n methods={methods}\n onSubmit={onSubmit}\n aria-label=\"Tax details\"\n className=\"flex flex-col items-start gap-7\">\n <FormText\n name=\"taxId\"\n label=\"Tax ID\"\n description=\"Nine digits, with or without the dash.\"\n rules={{ required: 'Enter the tax ID.' }}\n inputProps={{ inputMode: 'numeric', autoComplete: 'off' }}\n />\n <Button type=\"submit\">Save</Button>\n </Form.Root>\n );\n};",
|
|
6170
|
+
"description": "The error sits right under the input and the description stays below it, so\nthe message lands next to the value it is about. Screen readers announce\nthem in the same order.",
|
|
6171
|
+
"summary": "Error under the input, above the helper text"
|
|
6172
|
+
},
|
|
6159
6173
|
{
|
|
6160
6174
|
"id": "components-formtext--all-errors",
|
|
6161
6175
|
"name": "All Errors",
|
|
@@ -6538,7 +6552,7 @@
|
|
|
6538
6552
|
"id": "components-inputgroup--default",
|
|
6539
6553
|
"name": "Default",
|
|
6540
6554
|
"snippet": "const Default = () => (\n <InputGroup.Root>\n <InputGroup.Addon>\n <IconSearch />\n </InputGroup.Addon>\n <Input type=\"search\" placeholder=\"Search agencies\" aria-label=\"Search agencies\" />\n </InputGroup.Root>\n);",
|
|
6541
|
-
"description": "A search field: the icon leads and the input takes the rest of the frame.\nPressing the icon focuses the input, and the frame — not the input — draws the\nfocus ring, so the two never show a double border.",
|
|
6555
|
+
"description": "A search field: the icon leads and the input takes the rest of the frame.\nPressing the icon focuses the input, and the frame — not the input — draws the\nfocus ring, so the two never show a double border. A search field with a\nclear button and a loading state is\n[InputSearch](?path=/docs/components-inputsearch--docs), built on this frame.",
|
|
6542
6556
|
"summary": "Leading icon addon with the frame drawing the focus ring"
|
|
6543
6557
|
},
|
|
6544
6558
|
{
|
|
@@ -6595,11 +6609,6 @@
|
|
|
6595
6609
|
"description": "Inside a `FieldText` nothing changes for the group: the `Input` reads the\nfield's context at any depth, so the label names it and the description\ndescribes it with no ids written by hand. The frame is not in the way.",
|
|
6596
6610
|
"summary": "Label and description reaching the input through the frame"
|
|
6597
6611
|
},
|
|
6598
|
-
{
|
|
6599
|
-
"id": "components-inputgroup--search-field",
|
|
6600
|
-
"name": "Search Field",
|
|
6601
|
-
"snippet": "const SearchField = () => (\n <form onSubmit={handleSearchSubmit}>\n <FieldStates\n label=\"Agency\"\n tooltip=\"Search by agency name or NPN.\"\n required\n error=\"Pick an agency from the list.\">\n <SearchInput />\n </FieldStates>\n </form>\n);"
|
|
6602
|
-
},
|
|
6603
6612
|
{
|
|
6604
6613
|
"id": "components-inputgroup--email-field",
|
|
6605
6614
|
"name": "Email Field",
|
|
@@ -6622,7 +6631,7 @@
|
|
|
6622
6631
|
"summary": "Phone field with a leading country code picker, valid and invalid"
|
|
6623
6632
|
}
|
|
6624
6633
|
],
|
|
6625
|
-
"import": "import {\n Button,\n Divider,\n DropdownMenu,\n Field,\n FieldText,\n
|
|
6634
|
+
"import": "import {\n Button,\n Divider,\n DropdownMenu,\n Field,\n FieldText,\n IconKeyboardArrowDown,\n IconSearch,\n Input,\n InputGroup,\n Label,\n Tag,\n} from \"@agentero/design-system\";"
|
|
6626
6635
|
},
|
|
6627
6636
|
"components-inputpassword": {
|
|
6628
6637
|
"id": "components-inputpassword",
|
|
@@ -6730,6 +6739,168 @@
|
|
|
6730
6739
|
],
|
|
6731
6740
|
"import": "import { Field, FieldText, InputPassword, Label } from \"@agentero/design-system\";"
|
|
6732
6741
|
},
|
|
6742
|
+
"components-inputsearch": {
|
|
6743
|
+
"id": "components-inputsearch",
|
|
6744
|
+
"name": "InputSearch",
|
|
6745
|
+
"path": "./src/input-search/input-search.stories.tsx",
|
|
6746
|
+
"jsDocTags": {
|
|
6747
|
+
"summary": [
|
|
6748
|
+
"Search input with a leading icon, a clear button and a loading slot"
|
|
6749
|
+
],
|
|
6750
|
+
"dataAttribute": [
|
|
6751
|
+
"{string} data-slot - Always set to \"input-search\" on the frame"
|
|
6752
|
+
],
|
|
6753
|
+
"example": [
|
|
6754
|
+
"<InputSearch\n aria-label=\"Search agencies\"\n value={query}\n onChange={event => setQuery(event.target.value)}\n isLoading={isFetching}\n/>"
|
|
6755
|
+
]
|
|
6756
|
+
},
|
|
6757
|
+
"description": "InputSearch is a search field with a magnifier in front and a clear button\nonce there is text. It is an `Input` of `type=\"search\"` inside an\n`InputGroup`: `className` styles the frame and every other prop reaches the\n`<input>`. Clearing reports a real change event with an empty value, and\n`isLoading` swaps the clear button for a spinner.",
|
|
6758
|
+
"summary": "Search input with a leading icon, a clear button and a loading slot",
|
|
6759
|
+
"reactComponentMeta": {
|
|
6760
|
+
"displayName": "InputSearch",
|
|
6761
|
+
"exportName": "InputSearch",
|
|
6762
|
+
"filePath": "/home/runner/work/design-system/design-system/src/input-search/input-search.tsx",
|
|
6763
|
+
"description": "InputSearch is a search field: a magnifier in front of the text and, once\nthere is text, a clear button after it, named \"Clear search\" unless\n`clearLabel` says otherwise. The clear button empties the field\nand puts focus back in it, and it reports the change through `onChange` like\na keystroke would: a real change event whose `event.target.value` is `''`,\nso a controlled field, an uncontrolled one and one registered with\nreact-hook-form all clear the same way. While `isLoading` is set, a spinner\ntakes the clear button's place. The clear button is not rendered while the\ninput is disabled, whether `disabled` comes from the prop, from a\nsurrounding `FieldText` or from a `<fieldset disabled>`.\n\nIt is an [Input](?path=/docs/components-input--docs) of `type=\"search\"`\ninside an [InputGroup](?path=/docs/components-inputgroup--docs) frame, so\nit is announced as a search box. `className` styles the frame. Every other\nprop goes to the `<input>`: the `ref`, `id`, `name`, `value`, `onChange`,\n`aria-*` and every other standard attribute. Only `type` is not accepted.\n`placeholder` defaults to `'Search'`. Inside a `FieldText` the input takes\nits label, messages and states from the field as a plain `Input` does. The\ninvalid state comes from `aria-invalid`, and the frame paints the\ndestructive border.\n\nDo not use it to pick a value from a list; that is\n[Combobox](?path=/docs/components-combobox--docs), whose `search` field is\ndrawn by InputSearch. For a filter that should\nrun only once the user pauses typing, use `DebouncedInputSearch`.",
|
|
6764
|
+
"jsDocTags": {
|
|
6765
|
+
"summary": [
|
|
6766
|
+
"Search input with a leading icon, a clear button and a loading slot"
|
|
6767
|
+
],
|
|
6768
|
+
"dataAttribute": [
|
|
6769
|
+
"{string} data-slot - Always set to \"input-search\" on the frame"
|
|
6770
|
+
],
|
|
6771
|
+
"example": [
|
|
6772
|
+
"<InputSearch\n aria-label=\"Search agencies\"\n value={query}\n onChange={event => setQuery(event.target.value)}\n isLoading={isFetching}\n/>"
|
|
6773
|
+
]
|
|
6774
|
+
},
|
|
6775
|
+
"props": {
|
|
6776
|
+
"size": {
|
|
6777
|
+
"name": "size",
|
|
6778
|
+
"required": false,
|
|
6779
|
+
"type": {
|
|
6780
|
+
"name": "enum",
|
|
6781
|
+
"raw": "\"sm\" | \"md\" | \"lg\"",
|
|
6782
|
+
"value": [
|
|
6783
|
+
{
|
|
6784
|
+
"value": "\"sm\""
|
|
6785
|
+
},
|
|
6786
|
+
{
|
|
6787
|
+
"value": "\"md\""
|
|
6788
|
+
},
|
|
6789
|
+
{
|
|
6790
|
+
"value": "\"lg\""
|
|
6791
|
+
}
|
|
6792
|
+
]
|
|
6793
|
+
},
|
|
6794
|
+
"description": "Control height. Defaults to `'md'`.\n- `sm` (32px) — dense layouts where vertical space is tight.\n- `md` (40px) — standard form density.\n- `lg` (48px) — low-density forms and larger touch targets. Also raises\n the text to `base` and the corner radius to `lg`.",
|
|
6795
|
+
"defaultValue": null,
|
|
6796
|
+
"parent": {
|
|
6797
|
+
"name": "InputProps",
|
|
6798
|
+
"fileName": "src/input/input.tsx"
|
|
6799
|
+
},
|
|
6800
|
+
"declarations": [
|
|
6801
|
+
{
|
|
6802
|
+
"name": "TypeLiteral",
|
|
6803
|
+
"fileName": "src/input/input.tsx"
|
|
6804
|
+
}
|
|
6805
|
+
]
|
|
6806
|
+
},
|
|
6807
|
+
"isLoading": {
|
|
6808
|
+
"name": "isLoading",
|
|
6809
|
+
"required": false,
|
|
6810
|
+
"type": {
|
|
6811
|
+
"name": "boolean"
|
|
6812
|
+
},
|
|
6813
|
+
"description": "Shows a spinner at the end of the frame, in place of the clear button,\nwhile the results for the current text are on their way. Defaults to\n`false`.",
|
|
6814
|
+
"defaultValue": {
|
|
6815
|
+
"value": "false"
|
|
6816
|
+
},
|
|
6817
|
+
"parent": {
|
|
6818
|
+
"name": "InputSearchProps",
|
|
6819
|
+
"fileName": "src/input-search/input-search.tsx"
|
|
6820
|
+
},
|
|
6821
|
+
"declarations": [
|
|
6822
|
+
{
|
|
6823
|
+
"name": "TypeLiteral",
|
|
6824
|
+
"fileName": "src/input-search/input-search.tsx"
|
|
6825
|
+
}
|
|
6826
|
+
]
|
|
6827
|
+
},
|
|
6828
|
+
"clearLabel": {
|
|
6829
|
+
"name": "clearLabel",
|
|
6830
|
+
"required": false,
|
|
6831
|
+
"type": {
|
|
6832
|
+
"name": "string"
|
|
6833
|
+
},
|
|
6834
|
+
"description": "Accessible name of the clear button. Defaults to `'Clear search'`; name it\nafter what is searched (`'Clear agency search'`) when a page carries\nseveral search fields.",
|
|
6835
|
+
"defaultValue": {
|
|
6836
|
+
"value": "'Clear search'"
|
|
6837
|
+
},
|
|
6838
|
+
"parent": {
|
|
6839
|
+
"name": "InputSearchProps",
|
|
6840
|
+
"fileName": "src/input-search/input-search.tsx"
|
|
6841
|
+
},
|
|
6842
|
+
"declarations": [
|
|
6843
|
+
{
|
|
6844
|
+
"name": "TypeLiteral",
|
|
6845
|
+
"fileName": "src/input-search/input-search.tsx"
|
|
6846
|
+
}
|
|
6847
|
+
]
|
|
6848
|
+
}
|
|
6849
|
+
}
|
|
6850
|
+
},
|
|
6851
|
+
"stories": [
|
|
6852
|
+
{
|
|
6853
|
+
"id": "components-inputsearch--default",
|
|
6854
|
+
"name": "Default",
|
|
6855
|
+
"snippet": "const Default = () => {\n const [query, setQuery] = useState('');\n\n return (\n <InputSearch\n aria-label=\"Search agencies\"\n value={query}\n onChange={event => {\n setQuery(event.target.value);\n args.onChange?.(event);\n }} />\n );\n};",
|
|
6856
|
+
"description": "A controlled search. The clear button appears once there is text; pressing\nit calls `onChange` with an empty `event.target.value`, so the state that\nowns the query empties too, and focus goes back to the input. The browser's\nown cancel button is hidden.",
|
|
6857
|
+
"summary": "Controlled search with a clear button that empties the query"
|
|
6858
|
+
},
|
|
6859
|
+
{
|
|
6860
|
+
"id": "components-inputsearch--loading",
|
|
6861
|
+
"name": "Loading",
|
|
6862
|
+
"snippet": "const Loading = () => <InputSearch\n aria-label=\"Search agencies\"\n onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}\n isLoading\n defaultValue=\"Acme\" />;",
|
|
6863
|
+
"description": "While `isLoading` is set a spinner takes the clear button's place, even with\ntext in the field.",
|
|
6864
|
+
"summary": "Spinner in place of the clear button while results load"
|
|
6865
|
+
},
|
|
6866
|
+
{
|
|
6867
|
+
"id": "components-inputsearch--uncontrolled",
|
|
6868
|
+
"name": "Uncontrolled",
|
|
6869
|
+
"snippet": "const Uncontrolled = () => <InputSearch\n aria-label=\"Search agencies\"\n onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}\n defaultValue=\"Acme Insurance\" />;",
|
|
6870
|
+
"description": "An uncontrolled search with a `defaultValue`. The clear button follows what\nis in the field, and clearing still calls `onChange` with an empty value.",
|
|
6871
|
+
"summary": "Uncontrolled search starting from a default value"
|
|
6872
|
+
},
|
|
6873
|
+
{
|
|
6874
|
+
"id": "components-inputsearch--disabled",
|
|
6875
|
+
"name": "Disabled",
|
|
6876
|
+
"snippet": "const Disabled = () => <div style={{ display: 'grid', gap: '1rem' }}>\n <InputSearch\n aria-label=\"Search agencies\"\n onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}\n disabled\n defaultValue=\"Acme\" />\n <fieldset disabled style={{ border: 0, margin: 0, padding: 0 }}>\n <InputSearch\n onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}\n aria-label=\"Search carriers\"\n defaultValue=\"Travelers\" />\n </fieldset>\n</div>;",
|
|
6877
|
+
"description": "A disabled search has no clear button, whether `disabled` is set on the\ninput itself or comes from a `<fieldset disabled>` around it.",
|
|
6878
|
+
"summary": "Disabled search with the clear button removed"
|
|
6879
|
+
},
|
|
6880
|
+
{
|
|
6881
|
+
"id": "components-inputsearch--all-sizes",
|
|
6882
|
+
"name": "All Sizes",
|
|
6883
|
+
"snippet": "const AllSizes = () => <div style={{ display: 'grid', gap: '1rem' }}>\n <InputSearch\n onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}\n size=\"sm\"\n aria-label=\"Small\"\n defaultValue=\"Acme\" />\n <InputSearch\n onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}\n size=\"md\"\n aria-label=\"Medium\"\n defaultValue=\"Acme\" />\n <InputSearch\n onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}\n size=\"lg\"\n aria-label=\"Large\"\n defaultValue=\"Acme\" />\n</div>;",
|
|
6884
|
+
"description": "The three sizes match Input's: the frame is 32, 40 or 48px tall.",
|
|
6885
|
+
"summary": "The three sizes side by side"
|
|
6886
|
+
},
|
|
6887
|
+
{
|
|
6888
|
+
"id": "components-inputsearch--inside-field-text",
|
|
6889
|
+
"name": "Inside Field Text",
|
|
6890
|
+
"snippet": "const InsideFieldText = () => (\n <div style={{ display: 'grid', gap: '1.5rem' }}>\n <FieldText>\n <Label>Agency</Label>\n <InputSearch defaultValue=\"Acme\" />\n <Field.Description>Search by agency name or NPN.</Field.Description>\n </FieldText>\n <FieldText disabled>\n <Label>Carrier</Label>\n <InputSearch defaultValue=\"Travelers\" />\n </FieldText>\n </div>\n);",
|
|
6891
|
+
"description": "Inside a `FieldText` the input takes its label, description and states from\nthe field through the frame. A disabled field removes the clear button too.",
|
|
6892
|
+
"summary": "Label and disabled state reaching the input through the frame"
|
|
6893
|
+
},
|
|
6894
|
+
{
|
|
6895
|
+
"id": "components-inputsearch--clear-label",
|
|
6896
|
+
"name": "Clear Label",
|
|
6897
|
+
"snippet": "const ClearLabel = () => <InputSearch\n aria-label=\"Search agencies\"\n onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}\n defaultValue=\"Acme\"\n clearLabel=\"Clear agency search\" />;",
|
|
6898
|
+
"description": "`clearLabel` names the clear button after what is searched, so a page with\nseveral search fields does not read \"Clear search\" twice.",
|
|
6899
|
+
"summary": "Clear button named after what the field searches"
|
|
6900
|
+
}
|
|
6901
|
+
],
|
|
6902
|
+
"import": "import { Field, FieldText, InputSearch, Label } from \"@agentero/design-system\";"
|
|
6903
|
+
},
|
|
6733
6904
|
"components-input": {
|
|
6734
6905
|
"id": "components-input",
|
|
6735
6906
|
"name": "Input",
|
|
@@ -9696,6 +9867,6 @@
|
|
|
9696
9867
|
},
|
|
9697
9868
|
"meta": {
|
|
9698
9869
|
"docgen": "react-component-meta",
|
|
9699
|
-
"durationMs":
|
|
9870
|
+
"durationMs": 3754
|
|
9700
9871
|
}
|
|
9701
9872
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentero/design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "A React component library built with Tailwind CSS v4 and Radix UI primitives",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -101,6 +101,10 @@
|
|
|
101
101
|
"types": "./src/input-password/index.d.ts",
|
|
102
102
|
"import": "./src/input-password/index.js"
|
|
103
103
|
},
|
|
104
|
+
"./input-search": {
|
|
105
|
+
"types": "./src/input-search/index.d.ts",
|
|
106
|
+
"import": "./src/input-search/index.js"
|
|
107
|
+
},
|
|
104
108
|
"./label": {
|
|
105
109
|
"types": "./src/label/index.d.ts",
|
|
106
110
|
"import": "./src/label/index.js"
|
|
@@ -145,7 +145,8 @@ type InputProps = Omit<ComponentPropsWithRef<typeof ComboboxPrimitive.Input>, 's
|
|
|
145
145
|
*/
|
|
146
146
|
variant?: 'search' | 'plain' | 'select';
|
|
147
147
|
/**
|
|
148
|
-
* Whether a clear button follows the input once
|
|
148
|
+
* Whether a clear button follows the input: on `search` once there is text,
|
|
149
|
+
* on the others once an option is picked.
|
|
149
150
|
* Defaults to `true` for `search` and `false` for `plain` and `select`; pass
|
|
150
151
|
* it to override the variant. On a `select` it replaces the chevron while
|
|
151
152
|
* there is a value. Ignored under a `multiple` root, which never
|
|
@@ -185,11 +186,13 @@ type InputProps = Omit<ComponentPropsWithRef<typeof ComboboxPrimitive.Input>, 's
|
|
|
185
186
|
* the user may want to browse before typing.
|
|
186
187
|
*
|
|
187
188
|
* Only `search` carries a clear button by default; `showClear` adds it to the
|
|
188
|
-
* other two or drops it from `search`.
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
189
|
+
* other two or drops it from `search`. The `search` field is an
|
|
190
|
+
* [InputSearch](?path=/docs/components-inputsearch--docs): its clear button
|
|
191
|
+
* shows as soon as there is text, typed or picked, and pressing it empties the
|
|
192
|
+
* text, which drops the picked option and closes the list. On a `select`, the
|
|
193
|
+
* clear button takes the chevron's place once an option is picked; the list
|
|
194
|
+
* still opens from the input. Name it with `clearLabel`, and the chevron with
|
|
195
|
+
* `triggerLabel`, when a page has more than one combobox.
|
|
193
196
|
*
|
|
194
197
|
* Under a `multiple` root there is neither: the list stays open between picks,
|
|
195
198
|
* so a chevron has nothing to toggle, and Base UI's clear button would drop the
|
|
@@ -198,7 +201,9 @@ type InputProps = Omit<ComponentPropsWithRef<typeof ComboboxPrimitive.Input>, 's
|
|
|
198
201
|
* remove each entry.
|
|
199
202
|
*
|
|
200
203
|
* Every native input attribute is accepted and forwarded to the `<input>` —
|
|
201
|
-
* `placeholder`, `disabled`, `autoComplete`
|
|
204
|
+
* `placeholder`, `disabled`, `autoComplete`. `className` styles the `<input>`
|
|
205
|
+
* too, except on the `search` field with a clear button, where it styles the
|
|
206
|
+
* frame, as on InputSearch.
|
|
202
207
|
*
|
|
203
208
|
* @summary Search, plain or select field that opens and filters the list
|
|
204
209
|
* @dataAttribute {string} data-slot - Always set to "combobox-input"
|