From cb1125f4012e54ff2e6f149c755accd48c07917b Mon Sep 17 00:00:00 2001 From: tszhong0411 Date: Thu, 16 Jan 2025 21:33:56 +0800 Subject: [PATCH] feat(ui): add Combobox component with demo and documentation --- .changeset/cool-birds-vanish.md | 5 + apps/docs/src/app/ui/components/combobox.mdx | 48 +++++++ .../components/demos/combobox/combobox.tsx | 93 ++++++++++++ apps/docs/src/config/links.ts | 4 + packages/ui/src/combobox.tsx | 136 ++++++++++++++++++ packages/ui/src/index.ts | 1 + 6 files changed, 287 insertions(+) create mode 100644 .changeset/cool-birds-vanish.md create mode 100644 apps/docs/src/app/ui/components/combobox.mdx create mode 100644 apps/docs/src/components/demos/combobox/combobox.tsx create mode 100644 packages/ui/src/combobox.tsx diff --git a/.changeset/cool-birds-vanish.md b/.changeset/cool-birds-vanish.md new file mode 100644 index 00000000..84bd1fc6 --- /dev/null +++ b/.changeset/cool-birds-vanish.md @@ -0,0 +1,5 @@ +--- +'@tszhong0411/ui': patch +--- + +Add Combobox component diff --git a/apps/docs/src/app/ui/components/combobox.mdx b/apps/docs/src/app/ui/components/combobox.mdx new file mode 100644 index 00000000..4d280a21 --- /dev/null +++ b/apps/docs/src/app/ui/components/combobox.mdx @@ -0,0 +1,48 @@ +--- +title: Combobox +description: Autocomplete input and command palette with a list of suggestions. +--- + + + +## Usage + +```tsx +import { + Combobox, + ComboboxContent, + ComboboxControl, + ComboboxInput, + ComboboxItem, + ComboboxItemGroup, + ComboboxItemGroupLabel, + ComboboxItemIndicator, + ComboboxItemText, + ComboboxTrigger +} from '@tszhong0411/ui' +``` + +```tsx + + Framework + + + + + + + + + Frameworks + {['React', 'Vue'].map((item) => ( + + {item} + + + + + ))} + + + +``` diff --git a/apps/docs/src/components/demos/combobox/combobox.tsx b/apps/docs/src/components/demos/combobox/combobox.tsx new file mode 100644 index 00000000..a3fef291 --- /dev/null +++ b/apps/docs/src/components/demos/combobox/combobox.tsx @@ -0,0 +1,93 @@ +'use client' + +import { + type ComboboxInputValueChangeDetails, + ComboboxLabel, + createListCollection +} from '@tszhong0411/ui' +import { + Combobox, + ComboboxContent, + ComboboxControl, + ComboboxInput, + ComboboxItem, + ComboboxItemGroup, + ComboboxItemGroupLabel, + ComboboxItemIndicator, + ComboboxItemText, + ComboboxTrigger +} from '@tszhong0411/ui' +import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' +import { useState } from 'react' + +const frameworks = [ + { + value: 'next.js', + label: 'Next.js' + }, + { + value: 'sveltekit', + label: 'SvelteKit', + disabled: true + }, + { + value: 'nuxt.js', + label: 'Nuxt.js' + }, + { + value: 'remix', + label: 'Remix' + }, + { + value: 'astro', + label: 'Astro' + } +] + +const initialCollection = createListCollection({ items: frameworks }) + +const ComboboxDemo = () => { + const [collection, setCollection] = useState(initialCollection) + const handleInputChange = (details: ComboboxInputValueChangeDetails) => { + const filtered = frameworks.filter((item) => + item.label.toLowerCase().includes(details.inputValue.toLowerCase()) + ) + if (filtered.length > 0) setCollection(createListCollection({ items: filtered })) + } + + const handleOpenChange = () => { + setCollection(initialCollection) + } + + return ( + + Framework + + + + + + + + + Frameworks + {collection.items.map((item) => ( + + {item.label} + + + + + ))} + + + + ) +} + +export default ComboboxDemo diff --git a/apps/docs/src/config/links.ts b/apps/docs/src/config/links.ts index b742ef5b..0829d9d3 100644 --- a/apps/docs/src/config/links.ts +++ b/apps/docs/src/config/links.ts @@ -74,6 +74,10 @@ const COMPONENT_LINKS = [ href: '/ui/components/collapsible', text: 'Collapsible' }, + { + href: '/ui/components/combobox', + text: 'Combobox' + }, { href: '/ui/components/command', text: 'Command' diff --git a/packages/ui/src/combobox.tsx b/packages/ui/src/combobox.tsx new file mode 100644 index 00000000..85b387ae --- /dev/null +++ b/packages/ui/src/combobox.tsx @@ -0,0 +1,136 @@ +'use client' + +import { Portal } from '@ark-ui/react' +import { Combobox as ComboboxPrimitive } from '@ark-ui/react/combobox' +import { cn } from '@tszhong0411/utils' + +const ComboboxContext = ComboboxPrimitive.Context +const ComboboxItemContext = ComboboxPrimitive.ItemContext +const ComboboxControl = ComboboxPrimitive.Control +const ComboboxItemText = ComboboxPrimitive.ItemText +const ComboboxItemIndicator = ComboboxPrimitive.ItemIndicator +const ComboboxTrigger = ComboboxPrimitive.Trigger +const ComboboxClearTrigger = ComboboxPrimitive.ClearTrigger +const ComboboxList = ComboboxPrimitive.List +const ComboboxItemGroup = ComboboxPrimitive.ItemGroup + +type ComboboxProps = React.ComponentProps + +const Combobox = (props: ComboboxProps) => { + const { openOnClick = true, ...rest } = props + + return +} + +type ComboboxInputProps = React.ComponentProps + +const ComboboxInput = (props: ComboboxInputProps) => { + const { className, ...rest } = props + + return ( + + ) +} + +type ComboboxLabelProps = React.ComponentProps + +const ComboboxLabel = (props: ComboboxLabelProps) => { + const { className, ...rest } = props + + return ( + + ) +} + +type ComboboxContentProps = React.ComponentProps + +const ComboboxContent = (props: ComboboxContentProps) => { + const { className, ...rest } = props + + return ( + + + + + + ) +} + +type ComboboxItemGroupLabelProps = React.ComponentProps + +const ComboboxItemGroupLabel = (props: ComboboxItemGroupLabelProps) => { + const { className, ...rest } = props + + return ( + + ) +} + +type ComboboxItemProps = React.ComponentProps + +const ComboboxItem = (props: ComboboxItemProps) => { + const { className, ...rest } = props + + return ( + + ) +} + +export { + Combobox, + ComboboxClearTrigger, + ComboboxContent, + ComboboxContext, + ComboboxControl, + ComboboxInput, + ComboboxItem, + ComboboxItemContext, + ComboboxItemGroup, + ComboboxItemGroupLabel, + ComboboxItemIndicator, + ComboboxItemText, + ComboboxLabel, + ComboboxList, + ComboboxTrigger +} + +export type { + CollectionItem, + ComboboxHighlightChangeDetails, + ComboboxInputValueChangeDetails, + ComboboxOpenChangeDetails, + ComboboxValueChangeDetails, + ListCollection +} from '@ark-ui/react/combobox' +export { createListCollection } from '@ark-ui/react/combobox' diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 84d2528b..bedda43e 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -13,6 +13,7 @@ export * from './carousel' export * from './checkbox' export * from './code-block' export * from './collapsible' +export * from './combobox' export * from './command' export * from './context-menu' export * from './data-table'