diff --git a/apps/www/src/content/docs/components/combobox/demo.ts b/apps/www/src/content/docs/components/combobox/demo.ts index 39c350ea7..362b75aef 100644 --- a/apps/www/src/content/docs/components/combobox/demo.ts +++ b/apps/www/src/content/docs/components/combobox/demo.ts @@ -78,13 +78,13 @@ export const groupDemo = { - Fruits + Fruits Apple Banana - Vegetables + Vegetables Carrot Broccoli @@ -92,6 +92,40 @@ export const groupDemo = { ` }; +export const labelDemo = { + type: 'code', + code: ` + + + Fruits + + + + + + + Apple + Banana + Grape + Orange + + ` +}; + +export const emptyDemo = { + type: 'code', + code: ` + + + + No fruit matches your search + Apple + Banana + Grape + + ` +}; + export const iconDemo = { type: 'code', code: ` @@ -149,3 +183,40 @@ export const controlledDemo = { ); }` }; + +export const createItemsDemo = { + type: 'code', + code: ` + function CreateItemsDemo() { + const users = [ + { id: "u1", name: "Jane Doe" }, + { id: "u2", name: "John Smith" }, + { id: "u3", name: "Ada Lovelace" } + ]; + const items = React.useMemo( + () => + Combobox.createItems(users, { + getValue: user => user.id, + getLabel: user => user.name + }), + [] + ); + const [value, setValue] = React.useState(null); + + return ( + + Selected ID: {value || "None"} + + + + {user => ( + + {user.name} + + )} + + + + ); + }` +}; diff --git a/apps/www/src/content/docs/components/combobox/index.mdx b/apps/www/src/content/docs/components/combobox/index.mdx index d30e80a97..4b6c7d84b 100644 --- a/apps/www/src/content/docs/components/combobox/index.mdx +++ b/apps/www/src/content/docs/components/combobox/index.mdx @@ -12,6 +12,9 @@ import { iconDemo, withFieldDemo, controlledDemo, + createItemsDemo, + labelDemo, + emptyDemo, } from "./demo.ts"; @@ -24,8 +27,18 @@ Import and assemble the component: import { Combobox } from "@raystack/apsara"; + - + + + + + + + + + + ``` @@ -53,7 +66,7 @@ Wrap the Combobox with [Field](/docs/components/field) to add a label, descripti ### Groups and separators -Organize items into groups with labels and visual separators. Groups and labels are automatically hidden when the user is searching. +Organize items into groups with `Combobox.GroupLabel` and separators. Groups, group labels, and separators are hidden while the user is searching. @@ -61,14 +74,36 @@ Organize items into groups with labels and visual separators. Groups and labels Pass the `multiple` prop to enable multi-select. Selected values appear as chips in the input. Items display checkboxes in multiple mode. +The input shows the first two chips and a "+N" count for the rest. Press Backspace in an empty input to remove the last value. Press Left Arrow at the start of the input to move focus to the chips. On a focused chip, press Backspace or Delete to remove it. + +### Label and clear button + +`Combobox.Label` renders a visible label linked to the input. `Combobox.Clear` renders a button that clears the value. It shows only when there is a value or input text. Place both anywhere inside `Combobox`. + + + +### Empty state + +`Combobox.Content` shows "No results" when no item matches the input. To change the text, add `Combobox.Empty` as a direct child of `Combobox.Content`. + + + ### Controlled Use `value` and `onValueChange` for controlled behavior. +### Using IDs as values + +When your app stores IDs instead of item objects, wrap the data with `Combobox.createItems`. `getValue` returns the value that `value` and `onValueChange` use. `getLabel` returns the text shown in the input and used for filtering. Pass a function as the child of `Combobox.Content` to render each item that matches the input. + +Create the collection at module scope for static data. For data that changes, wrap it in `React.useMemo` keyed by the data. + + + ## API Reference Root and input first, then the parts that make up the popup list. @@ -101,17 +136,41 @@ When no `value` prop is provided, the text content of `children` is used as the +### Label Props + +A visible label for the input. It renders a `