# Introduction
Vuzeno is a complete design system for Vue, built on [Ark UI](https://ark-ui.com/){rel=""nofollow""}. You install production-ready, Tailwind-styled components into your repo with the shadcn-vue CLI, then own and customize the source. Unlike shadcn-vue (Reka UI), Vuzeno’s interactive behavior is Ark-native.
## Why Vuzeno?
The Vue ecosystem, while powerful, often lacks the breadth of ready-to-use components available in React. Vuzeno aims to change that by providing carefully crafted components that solve real-world problems — the kind of components you'd otherwise build from scratch or piece together from multiple libraries.
Every component is:
- **Composable** — Built with a slot-based architecture for maximum flexibility
- **Accessible** — Following WAI-ARIA guidelines with keyboard navigation
- **Styled with Tailwind** — Leveraging Tailwind CSS 4 for consistent, customizable design
- **TypeScript-first** — Full type safety out of the box
## Built On
Vuzeno builds on top of excellent open-source projects:
- [Ark UI](https://ark-ui.com/){rel=""nofollow""} — Headless, accessible UI primitives (the foundation of the design system)
- [Tailwind CSS](https://tailwindcss.com/){rel=""nofollow""} — Utility-first CSS framework
- [VueUse](https://vueuse.org/){rel=""nofollow""} — Essential Vue composition utilities
- [shadcn-vue CLI](https://www.shadcn-vue.com/){rel=""nofollow""} — Registry installer used to pull components into your project (CLI only — see below)
## Why Ark UI?
Ark UI powers the interactive behavior of Vuzeno components. It provides:
- **Broad coverage** — Primitives for complex UI patterns (dialogs, menus, date pickers, and more)
- **Accessibility** — Keyboard navigation and WAI-ARIA patterns built in
- **Part-based composition** — Clean APIs that scale in real apps
- **Framework-native Vue** — First-class Vue bindings with typed props and events
Vuzeno wraps these primitives with Tailwind styles and opinionated composition so you get production-ready components without giving up control of the source.
### Why not shadcn-vue components?
[shadcn-vue](https://www.shadcn-vue.com/){rel=""nofollow""} is built on [Reka UI](https://reka-ui.com/){rel=""nofollow""} and has no support for Ark UI. Vuzeno therefore stays detached from the shadcn-vue component library: we share only the **CLI and registry format** to install source into your project, while the design system itself is fully Ark UI-based.
## Philosophy
Vue deserves a richer ecosystem. While React developers enjoy an abundance of polished components and utilities, Vue developers often find themselves building complex UI patterns from scratch.
Vuzeno exists to close that gap — providing the same level of quality and developer experience that React developers take for granted, but built natively for Vue.
Our goal is simple: **build a complete design system on Ark UI** and make Vue more attractive by giving developers the tools they need to ship beautiful, functional applications faster.
# Getting Started
## Prerequisites
Before installing Vuzeno components, make sure you have:
- **Vue 3.5+** — Vuzeno uses the latest Vue features
- **Tailwind CSS 4** — For styling components
- **A `components.json` file** — Used by the [shadcn-vue CLI](https://www.shadcn-vue.com/){rel=""nofollow""} to know where to install files
:alert{description="shadcn-vue is built on Reka UI and has no Ark UI support. Vuzeno is therefore detached from the shadcn-vue component library — we use the CLI solely as the registry installer." title="Ark UI design system, shadcn-vue CLI only" variant="info"}
If you don't have a registry setup yet, run `bunx shadcn-vue@latest init` to create `components.json`, then add Vuzeno as a registry below.
## Registry setup
Add Vuzeno to your `components.json` registries so you can install components with the `@vuzeno/` shorthand:
```json
{
"registries": {
"@vuzeno": "https://vuzeno.com/r/{name}.json"
}
}
```
## Installation
Install components with the shadcn-vue CLI:
::installation-tabs{exec command="shadcn-vue@latest add @vuzeno/[component]"}
::
Replace `[component]` with the component name (e.g. `dialog`, `phone-field`, `autocomplete`). Without registry setup, you can also install by URL: `shadcn-vue add https://vuzeno.com/r/[component].json`
The CLI copies the component source and its registry dependencies into your project. Runtime packages such as `@ark-ui/vue` are installed as npm dependencies when needed. Some components also list extra npm packages on their docs (e.g. `libphonenumber-js` for Phone Field) — install those if prompted or as shown on the component page.
### Manual installation
You can also copy component source code from the docs into your project. Each component page includes dependencies, source snippets, and usage examples.
## TypeScript
Vuzeno is written in TypeScript and provides full type definitions. No additional configuration is required — types are inferred automatically.
## Next Steps
Ready to add your first component? Browse the [components](https://vuzeno.com/docs/components) catalog, or start with:
- [Dialog](https://vuzeno.com/docs/components/dialog) — Accessible modal dialogs on Ark UI
- [Phone Field](https://vuzeno.com/docs/components/phone-field) — Auto-formatting and validation for phone numbers
- [Autocomplete](https://vuzeno.com/docs/components/autocomplete) — Searchable combobox patterns
Each component page includes installation, source, props, and usage examples.
# Registries
Vuzeno is one of several third-party Vue component registries offering production-ready components you can install as source into your project.
Depending on your project, another registry may be a better fit — or a great complement to Vuzeno. The sections below detail each registry so you can pick the one that matches your needs.
## Inspira UI
- **Link:** [inspira-ui.com](https://inspira-ui.com){rel=""nofollow""}
- **Description:** Vue/Nuxt port of Aceternity UI and Magic UI — a large catalog of animated, marketing-grade components (marquees, hero effects, 3D cards, text animations, backgrounds).
Reach for Inspira UI when you need flashy, motion-heavy components for landing pages and marketing sites. It's the most popular community Vue registry in this ecosystem.
Install a component:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://registry.inspira-ui.com/[component].json
---
::
## UI Thing
- **Link:** [uithing.com](https://uithing.com){rel=""nofollow""}
- **Description:** Nuxt-first component library built on Reka UI and Tailwind, shipping an extended catalog of forms, charts, data tables, blocks, and starters.
Pick UI Thing when you're building a Nuxt app and want a broader, batteries-included component library. It ships its own CLI that mirrors the registry install model.
Install a component:
::installation-tabs{exec command="ui-thing@latest add [component]"}
::
## Neobrutalism Vue
- **Link:** [neobrutalism-vue.com](https://neobrutalism-vue.com){rel=""nofollow""}
- **Description:** 30+ neobrutalist-styled Vue components (bold borders, hard shadows, high contrast) built on Reka UI, tuned for Tailwind v4.
Use it when you want the distinctive neobrutalist look with a drop-in registry — no custom CLI required.
Install a component:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://neobrutalism-vue.com/r/[component].json
---
::
## ElevenLabs UI Vue
- **Link:** [elevenlabs-ui-vue.com](https://elevenlabs-ui-vue.com/){rel=""nofollow""}
- **Description:** Vue port of ElevenLabs UI — agent and audio components (orbs, waveforms, transcripts, voice buttons, conversation UIs) for multimodal AI apps.
Reach for ElevenLabs UI Vue when you're building voice agents, audio players, or conversational AI interfaces and want polished, domain-specific components out of the box.
Install a component:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://registry.elevenlabs-ui-vue.com/[component].json
---
::
## Using multiple registries
You can combine any of these with Vuzeno in your `components.json` to install components with short `@namespace/` aliases:
```json
{
"registries": {
"@vuzeno": "https://vuzeno.com/r/{name}.json",
"@inspira": "https://registry.inspira-ui.com/{name}.json",
"@neobrutalism": "https://neobrutalism-vue.com/r/{name}.json",
"@elevenlabs": "https://registry.elevenlabs-ui-vue.com/{name}.json"
}
}
```
Then add components from any registry with the CLI:
::installation-tabs{exec command="shadcn-vue@latest add @inspira/[component]"}
::
# Components
# Accordion
:component-preview{component="accordion" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/accordion.json
---
::
## Usage
```vue
```
## Composition
```text
Accordion.Root
├── Accordion.Context
├── Accordion.ItemContent
├── Accordion.ItemContext
├── Accordion.ItemIndicator
├── Accordion.ItemTrigger
├── Accordion.Item
├── Accordion.RootProvider
```
## Examples
### Default Value
Set the `defaultValue` prop to specify which item should be expanded by default.
:component-preview{component="accordion" name="default-value"}
### Controlled
Use the `value` and `onValueChange` props to control the expanded items.
:component-preview{component="accordion" name="controlled"}
### Root Provider
An alternative way to control the accordion is to use the `RootProvider` component and the `useAccordion` hook. This way you can access the state and methods from outside the component.
:component-preview{component="accordion" name="root-provider"}
### Collapsible
Use the `collapsible` prop to allow the user to collapse all panels.
:component-preview{component="accordion" name="collapsible"}
### Multiple
Use the `multiple` prop to allow multiple panels to be expanded simultaneously.
:component-preview{component="accordion" name="multiple"}
### Horizontal
By default, the Accordion is oriented vertically. Use the `orientation` prop to switch to a horizontal layout.
:component-preview{component="accordion" name="horizontal"}
### Lazy Mount
Use the `lazyMount` prop to defer rendering of accordion content until the item is expanded. Combine with `unmountOnExit` to unmount content when collapsed, freeing up resources.
:component-preview{component="accordion" name="lazy-mount"}
### Context
Use `Accordion.Context` or `useAccordionContext` to access the accordion state.
:component-preview{component="accordion" name="context"}
### Item State
Use `Accordion.ItemContext` or `useAccordionItemContext` to access the state of an accordion item.
:component-preview{component="accordion" name="item-context"}
## API
See [Ark UI Accordion docs](https://ark-ui.com/vue/docs/components/accordion){rel=""nofollow""} for full props and examples.
# ActionSheet
:component-preview{component="action-sheet" name="basic"}
## Features
- **Zag state machine** — Open/close, dismiss, option selection, and cancel are modeled with a custom `@zag-js` machine (not Ark Dialog)
- **Programmatic API** — Define the action sheet with `useActionSheet()`, pass it to `ActionSheet.Provider`, then `await show()` for a typed result (`ActionSheetStartResult`) when the user picks an option, cancels, or dismisses the sheet
- **Classic usage** — Control visibility with `v-model:open` and open via `ActionSheet.Trigger`
- **Composable layout** — Stack multiple `ActionSheet.Group` blocks for separated groups of actions
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/action-sheet.json
---
::
## Usage
```vue
Option 1Option 2Cancel
```
## Composition
```text
ActionSheet.Root
├── ActionSheet.Trigger
└── ActionSheet.Content
├── ActionSheet.Group
│ └── ActionSheet.Option
└── ActionSheet.Cancel
ActionSheet.Provider
└── ActionSheet.Content
├── ActionSheet.Group
│ └── ActionSheet.Option
└── ActionSheet.Cancel
```
## Examples
### Classic action sheet
Use `ActionSheet.Trigger` to open the sheet and `ActionSheet.Option` for each choice. `ActionSheet.Cancel` fires the cancel path (and closes the sheet).
:component-preview{component="action-sheet" name="basic"}
### Provider API
Define the action sheet with `useActionSheet()`, then pass it to `ActionSheet.Provider` to drive it programmatically. Call `show()` and `await` the result — the promise resolves when the user selects an option, taps cancel, or closes the overlay (when `closeOnClickOutside` is enabled).
```vue showLineNumbers
Option 1Option 2Cancel
```
### Multiple option groups
Compose several `ActionSheet.Group` components inside `ActionSheet.Content` to separate primary actions from secondary ones.
```vue showLineNumbers
EditDuplicateArchiveDeleteCancel
```
## API Reference
### ActionSheet.Root
| Prop | Type | Default |
| --------------------- | --------- | ------- |
| `open` | `boolean` | `false` |
| `closeOnClickOutside` | `boolean` | `true` |
| `showOverlay` | `boolean` | `true` |
| `closeOnEscape` | `boolean` | `true` |
### ActionSheet.Provider
| Prop | Type | Default |
| ------- | ---------------- | ------- |
| `value` | `ActionSheetApi` | — |
Takes the object returned by `useActionSheet()` and drives the sheet's open state and callbacks from it.
### useActionSheet
```ts
function useActionSheet(props?: {
showOverlay?: boolean;
closeOnClickOutside?: boolean;
closeOnEscape?: boolean;
open?: boolean;
defaultOpen?: boolean;
onOpenChange?: (details: { open: boolean }) => void;
onSelectOption?: (details: { value: unknown }) => void;
onCancel?: () => void;
onDismiss?: () => void;
}): ComputedRef;
```
Returns a computed `ActionSheetApi` with:
| Member | Type | Description |
| --------------- | --------------------------------------- | -------------------------------------------------------------------------------------- |
| `show()` | `() => Promise` | Opens the sheet and resolves when the user selects an option, cancels, or dismisses it |
| `close()` | `() => void` | Closes the sheet |
| `setOpen(open)` | `(open: boolean) => void` | Opens or closes the sheet |
| `open` | `boolean` | Current open state |
### ActionSheetStartResult
```ts
type ActionSheetStartResult =
| { cancelled: false; cancelledReason: null; selectedOption: O }
| { cancelled: true; cancelledReason: "cancel" | "close"; selectedOption: null }
```
# Alert
:component-preview{component="alert" name="basic"}
## Features
- **Composable** — Flexible slot-based layout with `Alert.Icon`, `Alert.Title`, and `Alert.Description`
- **Variants** — `default`, `info`, `success`, `warning`, and `destructive` styles
- **Accessible** — Uses `role="alert"` for screen reader announcements
- **Icon support** — `Alert.Icon` renders a variant-aware icon automatically
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/alert.json
---
::
## Usage
```vue
Heads up!
You can add components to your app using the CLI.
```
## Composition
```text
Alert.Root
├── Alert.Icon
├── Alert.Title
└── Alert.Description
```
## Examples
### With icon
`Alert.Icon` picks the icon from the root `variant`.
:component-preview{component="alert" name="with-icon"}
### Variants
All semantic variants with their default icons.
:component-preview{component="alert" name="variants"}
### Destructive
Use `variant="destructive"` for error or critical messages.
:component-preview{component="alert" name="destructive"}
## API
| Part | Description |
| ------------------- | ------------------------------------------------------------- |
| `Alert.Root` | Root container with `role="alert"`. Supports `variant` prop |
| `Alert.Icon` | Variant-aware icon (`size-3.5`). Inherits `variant` from root |
| `Alert.Title` | Alert heading |
| `Alert.Description` | Supporting text or rich content |
### Variants
| Variant | Icon | Description |
| ------------- | -------------- | ----------------------------------------- |
| `default` | Bell | Neutral callout for general information |
| `info` | Info | Informational message with blue styling |
| `success` | Circle check | Positive confirmation or completed action |
| `warning` | Triangle alert | Caution or attention needed |
| `destructive` | Circle alert | Error or critical failure state |
# Alert Dialog
:component-preview{component="alert-dialog" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/alert-dialog.json
---
::
## Usage
```vue
```
Alert Dialog is a pre-configured variant of [Dialog](https://vuzeno.com/docs/components/dialog) with `role="alertdialog"`. It hides the close button in the content panel and is intended for confirmations where the user must explicitly choose an action.
Compared to a regular dialog:
- **Automatic focus** — the cancel/close action receives focus when opened, prioritizing the safest choice
- **Explicit dismissal** — cannot be closed by clicking outside; only button clicks or the Escape key dismiss it
## Composition
```text
AlertDialog.Root
├── AlertDialog.Trigger
└── AlertDialog.Content
├── AlertDialog.Header
│ ├── AlertDialog.Title
│ └── AlertDialog.Description
└── AlertDialog.Footer
├── AlertDialog.Cancel
└── AlertDialog.Confirm
```
## API
Props, events, and hooks match Ark UI Dialog. See [Ark UI Dialog docs](https://ark-ui.com/vue/docs/components/dialog){rel=""nofollow""} for the full API.
```ts
import {
AlertDialog,
useDialog,
useDialogContext,
dialogAnatomy,
} from "@/components/ui/alert-dialog";
```
# Angle Slider
:component-preview{component="angle-slider" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/angle-slider.json
---
::
## Usage
```vue
```
## Composition
```text
AngleSlider.Root
├── AngleSlider.Context
├── AngleSlider.Control
├── AngleSlider.HiddenInput
├── AngleSlider.Label
├── AngleSlider.MarkerGroup
├── AngleSlider.Marker
├── AngleSlider.RootProvider
├── AngleSlider.Thumb
├── AngleSlider.ValueText
```
## Examples
### Controlled
Use the `value` and `onValueChange` props to control the value of the Angle Slider.
:component-preview{component="angle-slider" name="controlled"}
### Steps
Use the `step` prop to set the discrete steps of the Angle Slider.
:component-preview{component="angle-slider" name="steps"}
## API
See [Ark UI Angle Slider docs](https://ark-ui.com/vue/docs/components/angle-slider){rel=""nofollow""} for full props and examples.
# Autocomplete
:component-preview{component="autocomplete" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/autocomplete.json
---
::
## Usage
```vue
```
## Composition
```text
Autocomplete.Root
├── Autocomplete.Label
├── Autocomplete.Control
│ ├── Autocomplete.Input
│ ├── Autocomplete.Indicators
│ │ ├── Autocomplete.ClearTrigger
│ │ └── Autocomplete.Trigger
│ └── Autocomplete.Tags
├── Autocomplete.Content
│ ├── Autocomplete.Empty
│ ├── Autocomplete.Status
│ ├── Autocomplete.ItemGroup
│ │ ├── Autocomplete.ItemGroupLabel
│ │ └── Autocomplete.Item
│ └── Autocomplete.Scroller
├── Autocomplete.Context
└── Autocomplete.RootProvider
```
## Examples
### Auto Highlight
Automatically highlight the first matching item as the user types by setting `inputBehavior="autohighlight"`.
:component-preview{component="autocomplete" name="auto-highlight"}
### Inline Autocomplete
Complete the input value with the first matching item by setting `inputBehavior="autocomplete"`. Use with `startsWith` filter for best results.
:component-preview{component="autocomplete" name="inline-autocomplete"}
### Grouping
To group related autocomplete items, use the `groupBy` prop on the collection and `collection.group()` to iterate the groups.
:component-preview{component="autocomplete" name="grouping"}
### Field
The `Field` component helps manage form-related state and accessibility attributes of an autocomplete. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.
:component-preview{component="autocomplete" name="field"}
### Context
Access the autocomplete's state with `Autocomplete.Context` or the `useAutocompleteContext` hook—useful for displaying the selected value or building custom UI.
:component-preview{component="autocomplete" name="context"}
### Root Provider
An alternative way to control the autocomplete is to use the `RootProvider` component and the `useAutocomplete` hook. This way you can access the state and methods from outside the component.
:component-preview{component="autocomplete" name="root-provider"}
### Links
Use the `asChild` prop to render the autocomplete items as links.
:component-preview{component="autocomplete" name="links"}
### Rehydrate
When an autocomplete has a `defaultValue` or `value` but the `collection` is not loaded yet, you can rehydrate the value to populate the input.
:component-preview{component="autocomplete" name="rehydrate"}
### Highlight Text
Highlight the matching search text in autocomplete items based on the user's input.
:component-preview{component="autocomplete" name="highlight-text"}
### Dynamic
Generate autocomplete items dynamically based on user input. This is useful for creating suggestions or autocomplete functionality.
:component-preview{component="autocomplete" name="dynamic"}
### Creatable
Allow users to create new options when their search doesn't match any existing items. This is useful for tags, categories, or other custom values.
:component-preview{component="autocomplete" name="creatable"}
### Multiple Selection
Enable multiple selection by setting the `multiple` prop. Selected items can be displayed as tags above the input.
:component-preview{component="autocomplete" name="multiple-selection"}
### Async Search
Load options asynchronously based on user input using the `useAsyncList` hook. This is useful for searching large datasets or fetching data from an API.
:component-preview{component="autocomplete" name="async-search"}
### Virtualized
For very large lists, use virtualization with `@tanstack/virtual` to render only the visible items. Pass the `scrollToIndexFn` prop to enable keyboard navigation within the virtualized list.
:component-preview{component="autocomplete" name="virtualized"}
### Custom Object
Use the `itemToString` and `itemToValue` props to map custom objects to the required interface.
:component-preview{component="autocomplete" name="custom-object"}
### Limit Results
Use the `limit` property on `useListCollection` to limit the number of rendered items in the DOM.
:component-preview{component="autocomplete" name="limit-results"}
## API
See [Ark UI Combobox docs](https://ark-ui.com/vue/docs/components/combobox){rel=""nofollow""} for full props and examples.
# Avatar
:component-preview{component="avatar" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/avatar.json
---
::
## Usage
```vue
CN
```
## Composition
```text
Avatar.Group
└── Avatar.Root
├── Avatar.Fallback
└── Avatar.Image
Avatar.Root
├── Avatar.Context
├── Avatar.Fallback
├── Avatar.Image
├── Avatar.RootProvider
```
## Examples
### Sizes
Use the `size` prop on `Avatar.Root` to change the size of the avatar.
:component-preview{component="avatar" name="sizes"}
### Group
Stack multiple avatars using `Avatar.Group`. Apply negative spacing and ring utilities on each `Avatar.Root` to create an overlapping effect.
:component-preview{component="avatar" name="group"}
## API
See [Ark UI Avatar docs](https://ark-ui.com/vue/docs/components/avatar){rel=""nofollow""} for full props and examples.
### Avatar.Root
| Prop | Type | Default | Description |
| ------- | ------------------------- | ----------- | ---------------------- |
| `size` | `"sm" | "default" | "lg"` | `"default"` | Size of the avatar |
| `class` | `string` | — | Additional CSS classes |
### Avatar.Group
| Prop | Type | Default | Description |
| ------------- | --------------------------- | -------------- | ----------------------------- |
| `orientation` | `"horizontal" | "vertical"` | `"horizontal"` | Layout direction of the group |
| `class` | `string` | — | Additional CSS classes |
# Badge
:component-preview{component="badge" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/badge.json
---
::
## Usage
```vue
Badge
```
## Examples
### Variants
Use the `variant` prop to change the visual style of the badge.
:component-preview{component="badge" name="variants"}
# Breadcrumb
:component-preview{component="breadcrumb" name="basic"}
## Features
- **Composable** — Flexible slot-based layout with `Breadcrumb.List`, `Breadcrumb.Item`, `Breadcrumb.Link`, `Breadcrumb.Page`, and `Breadcrumb.Separator`
- **Accessible** — Semantic navigation with `aria-current` on the current page
- **Customizable** — Override separators, compose with menus, or collapse long paths with `Breadcrumb.Ellipsis`
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/breadcrumb.json
---
::
## Usage
```vue
Home
Components
Breadcrumb
```
## Composition
```text
Breadcrumb.Root
└── Breadcrumb.List
├── Breadcrumb.Item
│ └── Breadcrumb.Link
├── Breadcrumb.Separator
├── Breadcrumb.Item
│ └── Breadcrumb.Link
├── Breadcrumb.Separator
└── Breadcrumb.Item
└── Breadcrumb.Page
```
## Examples
### Custom separator
Use a custom icon or character inside `Breadcrumb.Separator`.
:component-preview{component="breadcrumb" name="custom-separator"}
### Dropdown
Compose `Breadcrumb.Item` with `Menu` to create a dropdown for nested navigation.
:component-preview{component="breadcrumb" name="dropdown"}
### Collapsed
Use `Breadcrumb.Ellipsis` to collapse intermediate path segments.
:component-preview{component="breadcrumb" name="ellipsis"}
## API
| Part | Description |
| ---------------------- | ---------------------------------------------------------- |
| `Breadcrumb.Root` | Root `nav` element with `aria-label="breadcrumb"` |
| `Breadcrumb.List` | Ordered list of breadcrumb items |
| `Breadcrumb.Item` | List item wrapping a link or page label |
| `Breadcrumb.Link` | Navigable link. Supports `as-child` for router links |
| `Breadcrumb.Page` | Current page label with `aria-current="page"` |
| `Breadcrumb.Separator` | Visual separator between items. Defaults to a chevron icon |
| `Breadcrumb.Ellipsis` | Collapsed path indicator with screen-reader text |
# Button
:component-preview{component="button" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/button.json
---
::
## Usage
```vue
```
## Examples
### Variants
Use the `variant` prop to change the visual style of the button.
:component-preview{component="button" name="variants"}
### Sizes
Use the `size` prop to change the size of the button.
:component-preview{component="button" name="sizes"}
### Disabled
Use the native `disabled` attribute to disable the button.
:component-preview{component="button" name="disabled"}
# Button Group
:component-preview{component="button-group" name="basic"}
## Features
- **Grouped layout** — Visually connects adjacent buttons by removing inner border radii
- **Orientation** — Horizontal (default) or vertical layout via the `orientation` prop
- **Composable** — Nest groups or combine with inputs and other controls
- **Accessible** — Renders as a semantic `fieldset` via Ark UI's polymorphic factory
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/button-group.json
---
::
## Usage
```vue
```
## Composition
```text
ButtonGroup
└── Button
```
## Accessibility
- The component renders as a `fieldset` element.
- Use Tab to navigate between focusable elements in the group.
- Label the group with `aria-label` or `aria-labelledby`.
```vue
```
## Button Group vs Toggle Group
- Use **Button Group** when buttons perform independent actions.
- Use [Toggle Group](https://vuzeno.com/docs/components/toggle-group) when buttons toggle a shared state.
## Examples
### Orientation
Set the `orientation` prop to change the layout.
:component-preview{component="button-group" name="orientation"}
### Sizes
Control the size of buttons using the `size` prop on individual buttons.
:component-preview{component="button-group" name="sizes"}
### Nested
Nest `ButtonGroup` components to create groups with spacing between them.
:component-preview{component="button-group" name="nested"}
### Input
Combine an input with action buttons in a single group.
:component-preview{component="button-group" name="input"}
### Select
Pair a select with an input and submit button — useful for amount or unit pickers.
:component-preview{component="button-group" name="select"}
### Dropdown
Create a split button group with a [Menu](https://vuzeno.com/docs/components/menu) for secondary actions.
:component-preview{component="button-group" name="dropdown"}
## API
### ButtonGroup
| Prop | Type | Default | Description |
| ------------- | --------------------------- | -------------- | ---------------------------------- |
| `orientation` | `"horizontal" | "vertical"` | `"horizontal"` | Layout direction of the group |
| `asChild` | `boolean` | `false` | Merge props onto the child element |
| `class` | `string` | — | Additional CSS classes |
The component also exports `buttonGroupVariants` and `ButtonGroupVariants` for building custom styled wrappers.
See [Ark UI composition guide](https://ark-ui.com/docs/guides/composition){rel=""nofollow""} for polymorphic usage with `asChild`.
# Card
:component-preview{component="card" name="basic"}
## Features
- **Composable** — Flexible slot-based layout with `Card.Header`, `Card.Title`, `Card.Description`, `Card.Content`, and `Card.Footer`
- **Styled primitives** — Opinionated defaults for borders, spacing, and typography
- **Customizable** — Override any part with the `class` prop
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/card.json
---
::
## Composition
```text
Card.Root
├── Card.Header
│ ├── Card.Title
│ └── Card.Description
├── Card.Content
└── Card.Footer
```
## Usage
```vue
Create projectDeploy your new project in one click.
Start from a template or import an existing repository.
```
## Examples
### With form
Use a card to group related form fields and actions.
:component-preview{component="card" name="form"}
# Carousel
:component-preview{component="carousel" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/carousel.json
---
::
## Usage
```vue
```
## Composition
```text
Carousel.Root
├── Carousel.AutoplayIndicator
├── Carousel.ProgressText
├── Carousel.AutoplayTrigger
├── Carousel.Context
├── Carousel.Control
├── Carousel.IndicatorGroup
├── Carousel.Indicator
├── Carousel.ItemGroup
├── Carousel.Item
├── Carousel.NextTrigger
├── Carousel.PrevTrigger
├── Carousel.RootProvider
```
## Examples
### Controlled
To create a controlled Carousel component, you can manage the state of the carousel using the `page` prop and update it when the `onPageChange` event handler is called:
:component-preview{component="carousel" name="controlled"}
### Root Provider
An alternative way to control the carousel is to use the `RootProvider` component and the `useCarousel` hook. This way you can access the state and methods from outside the component.
:component-preview{component="carousel" name="root-provider"}
### Autoplay
Pass the `autoplay` and `loop` props to `Carousel.Root` to make the carousel play automatically.
:component-preview{component="carousel" name="autoplay"}
### Pause on Hover
This feature isn't built-in, but you can use the `play()` and `pause()` methods from `Carousel.Context` to implement pause on hover.
:component-preview{component="carousel" name="pause-on-hover"}
### Thumbnail Indicators
Replace default indicator dots with image thumbnails. Render each thumbnail inside `Carousel.Indicator` to create a visual preview of each slide:
:component-preview{component="carousel" name="thumbnail-indicators"}
### Vertical
Add the `orientation="vertical"` prop to `Carousel.Root` to switch the carousel to vertical scrolling. This can be helpful for displaying vertical galleries or content feeds.
:component-preview{component="carousel" name="vertical"}
### Dynamic
Manage slides dynamically by storing them in state and syncing the carousel page. Pass the `page` prop and `onPageChange` handler to `Carousel.Root`, and update `slideCount` when slides are added or removed. This demonstrates bidirectional state synchronization between your component state and the carousel.
:component-preview{component="carousel" name="dynamic"}
### Scroll to Slide
Use `Carousel.Context` to access the carousel API and call `api.scrollToIndex(index)` to programmatically navigate to a specific slide. This is useful for creating custom navigation or jump-to-slide functionality.
:component-preview{component="carousel" name="scroll-to-slide"}
### Slides Per Page
Display multiple slides simultaneously by setting the `slidesPerPage` prop on `Carousel.Root`. Use `api.pageSnapPoints` from `Carousel.Context` to render the correct number of indicators based on pages rather than individual slides. Add the `spacing` prop to control the gap between slides.
:component-preview{component="carousel" name="slides-per-page"}
### Spacing
Control the gap between slides using the `spacing` prop on `Carousel.Root`. Combine it with `slidesPerPage` to create layouts that show partial previews of adjacent slides.
:component-preview{component="carousel" name="spacing"}
### Variable Sizes
To allow slides with different widths, set the `autoSize` prop on `Carousel.Root`. This lets each `Carousel.Item` define its own width, and the carousel will adjust automatically. You can also use the `snapAlign` prop on individual items to control where each one snaps into view.
:component-preview{component="carousel" name="variable-sizes"}
## API
See [Ark UI Carousel docs](https://ark-ui.com/vue/docs/components/carousel){rel=""nofollow""} for full props and examples.
# Checkbox
:component-preview{component="checkbox" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/checkbox.json
---
::
## Usage
```vue
```
## Composition
```text
Checkbox.Root
├── Checkbox.Context
├── Checkbox.Control
├── Checkbox.Group
├── Checkbox.GroupProvider
├── Checkbox.HiddenInput
├── Checkbox.Indicator
├── Checkbox.Label
├── Checkbox.RootProvider
```
## Examples
### Default Checked
Use the `defaultChecked` prop to set the initial checked state in an uncontrolled manner. The checkbox will manage its own state internally.
:component-preview{component="checkbox" name="default-checked"}
### Controlled
Use the `checked` and `@checked-change` props to programmatically control the checkbox's state.
:component-preview{component="checkbox" name="controlled"}
### Root Provider
An alternative way to control the checkbox is to use the `RootProvider` component and the `useCheckbox` hook. This way you can access the state and methods from outside the component.
:component-preview{component="checkbox" name="root-provider"}
### Disabled
Use the `disabled` prop to make the checkbox non-interactive.
:component-preview{component="checkbox" name="disabled"}
### Indeterminate
Use the `indeterminate` prop to create a checkbox in an indeterminate state (partially checked).
:component-preview{component="checkbox" name="indeterminate"}
### Checkbox Group
Use the `Checkbox.Group` component to manage a group of checkboxes. The `Checkbox.Group` component manages the state of the checkboxes and provides a way to access the checked values.
:component-preview{component="checkbox" name="group"}
### Group Controlled
Use `v-model` (or the `model-value` prop with the `@value-change` event) to programmatically control the checkbox group's state. This example demonstrates how to manage selected checkboxes in an array and display the current selection.
:component-preview{component="checkbox" name="group-controlled"}
### Group Provider
Use the `useCheckboxGroup` hook to create the checkbox group store and pass it to the `Checkbox.GroupProvider` component. This provides maximum control over the group programmatically, similar to how `RootProvider` works for individual checkboxes.
:component-preview{component="checkbox" name="group-provider"}
### Invalid
Use the `invalid` prop on `Checkbox.Group` to mark the entire group as invalid for validation purposes. This applies the invalid state to all checkboxes within the group.
:component-preview{component="checkbox" name="group-invalid"}
### Max Selected
Use the `maxSelectedValues` prop to limit the number of checkboxes that can be selected at once. Once the maximum is reached, remaining checkboxes become disabled.
:component-preview{component="checkbox" name="group-max-selected"}
### Select All
Implement a "select all" checkbox that controls all checkboxes within a group. The parent checkbox automatically shows an indeterminate state when some (but not all) items are selected, and becomes fully checked when all items are selected.
:component-preview{component="checkbox" name="select-all"}
## API
See [Ark UI Checkbox docs](https://ark-ui.com/vue/docs/components/checkbox){rel=""nofollow""} for full props and examples.
# Clipboard
:component-preview{component="clipboard" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/clipboard.json
---
::
## Usage
```vue
```
## Composition
```text
Clipboard.Root
├── Clipboard.Label
├── Clipboard.Control
│ ├── Clipboard.Input
│ └── Clipboard.Trigger
│ └── Clipboard.Indicator
├── Clipboard.Context
├── Clipboard.RootProvider
└── Clipboard.ValueText
```
## Examples
### Controlled
Control the clipboard value externally by managing the state yourself and using `onValueChange` to handle updates.
:component-preview{component="clipboard" name="controlled"}
### Root Provider
An alternative way to control the clipboard is to use the `RootProvider` component and the `useClipboard` hook. This way you can access the state and methods from outside the component.
:component-preview{component="clipboard" name="root-provider"}
### Context
Access the clipboard's state with `Clipboard.Context` or the `useClipboardContext` hook. You get properties like `copied`, `value`, and `setValue`.
:component-preview{component="clipboard" name="context"}
### Copy Status
Use the `onStatusChange` prop to listen for copy operations. It exposes a `copied` property that you can use to display a success message.
:component-preview{component="clipboard" name="copy-status"}
### Timeout
Configure the copy status timeout duration using the `timeout` prop. Default is 3000ms (3 seconds).
:component-preview{component="clipboard" name="timeout"}
### Value Text
Use `Clipboard.ValueText` to display the current clipboard value.
:component-preview{component="clipboard" name="value-text"}
## API
See [Ark UI Clipboard docs](https://ark-ui.com/vue/docs/components/clipboard){rel=""nofollow""} for full props and examples.
# Collapsible
:component-preview{component="collapsible" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/collapsible.json
---
::
## Usage
```vue
```
## Composition
```text
Collapsible.Root
├── Collapsible.Trigger
│ └── Collapsible.Indicator
├── Collapsible.Content
│ └── Collapsible.Body
├── Collapsible.Context
└── Collapsible.RootProvider
```
## Examples
### Disabled
Use the `disabled` prop to disable the collapsible and prevent it from being toggled.
:component-preview{component="collapsible" name="disabled"}
### Partial Collapse
Use the `collapsedHeight` or `collapsedWidth` props to create a "show more/less" pattern. When set, the content maintains the specified dimensions when collapsed instead of collapsing to 0px.
We expose the `--collapsed-height` or `--collapsed-width` variables to use in your CSS animations.
:component-preview{component="collapsible" name="partial-collapse"}
### Nested Collapsibles
You can nest collapsibles within collapsibles to create hierarchical content structures.
:component-preview{component="collapsible" name="nested"}
### Lazy Mount
Use `lazyMount` to delay mounting the content until first opened, and `unmountOnExit` to remove it from the DOM when collapsed. Combining both ensures the component is only in the DOM while expanded.
:component-preview{component="collapsible" name="lazy-mount"}
### Root Provider
An alternative way to control the collapsible is to use the `RootProvider` component and the `useCollapsible` hook. This way you can access the state and methods from outside the component.
:component-preview{component="collapsible" name="root-provider"}
## API
See [Ark UI Collapsible docs](https://ark-ui.com/vue/docs/components/collapsible){rel=""nofollow""} for full props and examples.
# Color Picker
:component-preview{component="color-picker" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/color-picker.json
---
::
## Usage
```vue
```
## Composition
```text
ColorPicker.Root
├── ColorPicker.AreaBackground
├── ColorPicker.AreaThumb
├── ColorPicker.Area
├── ColorPicker.ChannelInput
├── ColorPicker.ChannelSliderLabel
├── ColorPicker.ChannelSliderThumb
├── ColorPicker.ChannelSliderTrack
├── ColorPicker.ChannelSliderValueText
├── ColorPicker.ChannelSlider
├── ColorPicker.Content
├── ColorPicker.Context
├── ColorPicker.Control
├── ColorPicker.EyeDropperTrigger
├── ColorPicker.FormatSelect
├── ColorPicker.FormatTrigger
├── ColorPicker.HiddenInput
├── ColorPicker.Label
├── ColorPicker.Positioner
├── ColorPicker.RootProvider
├── ColorPicker.SwatchGroup
├── ColorPicker.SwatchIndicator
├── ColorPicker.SwatchTrigger
├── ColorPicker.Swatch
├── ColorPicker.TransparencyGrid
├── ColorPicker.Trigger
├── ColorPicker.ValueSwatch
├── ColorPicker.ValueText
├── ColorPicker.View
```
## Examples
### Controlled
Use the `value` and `onValueChange` props to programatically control the color picker's state.
:component-preview{component="color-picker" name="controlled"}
### Open Controlled
Control the open state of the color picker popover programmatically using the `open` and `onOpenChange` props.
:component-preview{component="color-picker" name="open-controlled"}
### Root Provider
An alternative way to control the color picker is to use the `RootProvider` component and the `useColorPicker` hook. This way you can access the state and methods from outside the component.
:component-preview{component="color-picker" name="root-provider"}
### Disabled
Use the `disabled` prop to disable the color picker.
:component-preview{component="color-picker" name="disabled"}
### Inline
Render the color picker inline without a popover by using the `inline` prop.
:component-preview{component="color-picker" name="inline"}
### Input Only
A minimal color picker with just an input field, value swatch, and eye dropper trigger.
:component-preview{component="color-picker" name="input-only"}
### Slider Only
Display only the channel sliders for RGB color selection.
:component-preview{component="color-picker" name="slider-only"}
### Swatch Only
A simple color picker with only preset color swatches.
:component-preview{component="color-picker" name="swatch-only"}
### Swatches
Include preset color swatches in the color picker content for quick color selection.
:component-preview{component="color-picker" name="swatches"}
### Value Swatch
Display the current color value as a swatch alongside the color area and sliders.
:component-preview{component="color-picker" name="value-swatch"}
### Field
The `Field` component helps manage form-related state and accessibility attributes of a color picker. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.
:component-preview{component="color-picker" name="field"}
### Form Usage
Integrate the color picker with form libraries like React Hook Form using the `HiddenInput` component.
:component-preview{component="color-picker" name="form-usage"}
### Inside Dialog
Here's an example of how to use the color picker inside a dialog.
:component-preview{component="color-picker" name="inside-dialog"}
## API
See [Ark UI Color Picker docs](https://ark-ui.com/vue/docs/components/color-picker){rel=""nofollow""} for full props and examples.
# Date Input
:component-preview{component="date-input" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/date-input.json
---
::
## Usage
```vue
```
## Composition
```text
DateInput.Root
├── DateInput.Label
├── DateInput.Control
│ └── DateInput.SegmentGroup
│ └── DateInput.Segment
├── DateInput.HiddenInput
├── DateInput.Context
├── DateInput.SegmentContext
└── DateInput.RootProvider
```
## Examples
### Default Value
Use the `defaultValue` prop with `parseDate` to set the initial date value.
:component-preview{component="date-input" name="default-value"}
### Controlled
Use the `value` and `onValueChange` props to control the date input's value programmatically.
:component-preview{component="date-input" name="controlled"}
### Root Provider
An alternative way to control the date input is to use the `RootProvider` component and the `useDateInput` hook. This way you can access the state and methods from outside the component.
:component-preview{component="date-input" name="root-provider"}
### Granularity
Use the `granularity` prop to control which date fields are displayed. Supported values are `day`, `hour`, `minute`, and `second`.
:component-preview{component="date-input" name="granularity"}
### Time Only
To create a time-only input, set `granularity` to `minute` (or `second`) and provide a `formatter` that only includes time fields. Use the `hourCycle` prop to switch between 12 and 24 hour formats.
:component-preview{component="date-input" name="time-only"}
### Range
To create a date input that allows a range selection, set the `selectionMode` prop to `range` and render two `SegmentGroup` components with `index` props set to `0` and `1`.
:component-preview{component="date-input" name="range"}
### Min and Max
Use the `min` and `max` props with `parseDate` to restrict the selectable date range. Dates outside this range will be marked as invalid.
:component-preview{component="date-input" name="min-max"}
### Disabled
Use the `disabled` prop to prevent user interaction with the date input.
:component-preview{component="date-input" name="disabled"}
### Read Only
Use the `readOnly` prop to make the date input non-editable while still being focusable.
:component-preview{component="date-input" name="read-only"}
### Invalid
Use the `invalid` prop to indicate an error state on the date input.
:component-preview{component="date-input" name="invalid"}
### Leading Zeros
Use the `shouldForceLeadingZeros` prop to toggle whether numeric segments are padded with a leading zero.
:component-preview{component="date-input" name="leading-zeros"}
### Localized
Use the `locale` prop to set the language and regional formatting of the date segments.
:component-preview{component="date-input" name="localized"}
### RTL
Set the `dir` prop to `rtl` for right-to-left language support.
:component-preview{component="date-input" name="rtl"}
### With Clear Button
Use `useDateInput` via `RootProvider` to access the `clearValue` method and render a clear button alongside the input.
:component-preview{component="date-input" name="with-clear-button"}
### With Date Picker
Combine `DateInput` with `DatePicker` by syncing their values using `onValueChange` to provide both typed and calendar-based date selection.
:component-preview{component="date-input" name="with-date-picker"}
## API
See [Ark UI Date Input docs](https://ark-ui.com/vue/docs/components/date-input){rel=""nofollow""} for full props and examples.
# Date Picker
:component-preview{component="date-picker" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/date-picker.json
---
::
## Usage
```vue
Label
```
Use `DatePicker.Calendar` for the default day / month / year views, or compose `DatePicker.DayView`, `DatePicker.MonthView`, and `DatePicker.YearView` individually. All Ark UI primitives remain available for custom layouts.
## Composition
```text
DatePicker.Root
├── DatePicker.ClearTrigger
├── DatePicker.Content
│ └── DatePicker.Calendar
│ ├── DatePicker.DayView
│ ├── DatePicker.MonthView
│ └── DatePicker.YearView
├── DatePicker.Context
├── DatePicker.Control
├── DatePicker.Input
├── DatePicker.Label
├── DatePicker.MonthSelect
├── DatePicker.NextTrigger
├── DatePicker.Positioner
├── DatePicker.PresetTrigger
├── DatePicker.PrevTrigger
├── DatePicker.RangeText
├── DatePicker.ValueText
├── DatePicker.RootProvider
├── DatePicker.TableBody
├── DatePicker.TableCellTrigger
├── DatePicker.TableCell
├── DatePicker.TableHead
├── DatePicker.TableHeader
├── DatePicker.TableRow
├── DatePicker.Table
├── DatePicker.Trigger
├── DatePicker.ViewControl
├── DatePicker.ViewNav
├── DatePicker.ViewTrigger
├── DatePicker.View
├── DatePicker.WeekNumberHeaderCell
├── DatePicker.WeekNumberCell
├── DatePicker.YearSelect
```
## Examples
### Default Value
Use the `defaultValue` prop with `parseDate` to set the initial date value.
:component-preview{component="date-picker" name="default-value"}
### Controlled
Use the `value` and `onValueChange` props to control the date picker's value programmatically.
:component-preview{component="date-picker" name="controlled"}
### Root Provider
An alternative way to control the date picker is to use the `RootProvider` component and the `useDatePicker` hook. This
way you can access the state and methods from outside the component.
:component-preview{component="date-picker" name="root-provider"}
### Default View
Use the `defaultView` prop to set which view (day, month, or year) the calendar opens to initially.
:component-preview{component="date-picker" name="default-view"}
### Month and Year Select
Use `MonthSelect` and `YearSelect` components to create a header with dropdown selects for quick month/year navigation,
alongside the prev/next triggers.
:component-preview{component="date-picker" name="month-and-year-select"}
### Range
To create a date picker that allows a range selection, you need to:
- Set the `selectionMode` prop to `range`.
- Render multiple inputs with the `index` prop set to `0` and `1`.
:component-preview{component="date-picker" name="range"}
### Multiple
Use the `selectionMode="multiple"` prop to allow selecting multiple dates. This example also shows how to display
selected dates as removable tags.
:component-preview{component="date-picker" name="multiple"}
### Max Selected Dates
Use the `maxSelectedDates` prop with `selectionMode="multiple"` to limit the number of dates that can be selected. In
this example, users can select up to 3 dates.
:component-preview{component="date-picker" name="max-selected-dates"}
### Multiple Months
To create a date picker that displays multiple months side by side:
- Set the `numOfMonths` prop to the number of months you want to display.
- Use the `datePicker.getOffset({ months: 1 })` to get data for the next month.
:component-preview{component="date-picker" name="multiple-months"}
### Presets
Use the `DatePicker.PresetTrigger` component to add quick-select preset options like "Last 7 days" or "This month".
:component-preview{component="date-picker" name="presets"}
### Min and Max
Use the `min` and `max` props with `parseDate` to restrict the selectable date range. Dates outside this range will be
disabled.
:component-preview{component="date-picker" name="min-and-max"}
### Unavailable
Use the `isDateUnavailable` prop to mark specific dates as unavailable. This example disables weekends.
:component-preview{component="date-picker" name="unavailable"}
### Locale
Use the `locale` prop to set the language and formatting, and `startOfWeek` to set the first day of the week (0 =
Sunday, 1 = Monday, etc.).
:component-preview{component="date-picker" name="locale"}
### Month Picker
Create a month-only picker by setting `defaultView="month"` and `minView="month"`. Use custom `format` and `parse`
functions to handle month/year input format.
:component-preview{component="date-picker" name="month-picker"}
### Year Picker
Create a year-only picker by setting `defaultView="year"` and `minView="year"`. Use custom `format` and `parse`
functions to handle year-only input format.
:component-preview{component="date-picker" name="year-picker"}
### Inline
Use the `inline` prop to display the date picker directly on the page, without a popup.
> When using the `inline` prop, omit the `Portal`, `Positioner`, and `Content` components to render the calendar inline
> within your layout.
:component-preview{component="date-picker" name="inline"}
### Custom Parsing
Use the `parse` prop to implement custom date parsing logic. This allows users to enter dates in flexible formats like
"25/12" or "25/12/24" which are automatically converted to valid dates.
:component-preview{component="date-picker" name="custom-parsing"}
### Month Picker Range
Create a month range picker by combining `selectionMode="range"` with `defaultView="month"` and `minView="month"`. This
is useful for selecting billing periods or date ranges by month.
:component-preview{component="date-picker" name="month-picker-range"}
### Year Range
Create a year range picker by combining `selectionMode="range"` with `defaultView="year"` and `minView="year"`. This is
useful for selecting multi-year periods.
:component-preview{component="date-picker" name="year-range"}
### Select Today
Use the `selectToday` method from the date picker context to add a "Today" button that quickly selects the current date.
:component-preview{component="date-picker" name="select-today"}
### Fixed Weeks
Use the `fixedWeeks` prop to always display 6 weeks in the calendar, preventing layout shifts when navigating between
months.
:component-preview{component="date-picker" name="fixed-weeks"}
### Form
Use the `name` prop to integrate the date picker with native HTML forms. The selected date value will be submitted as
form data. This example also uses `isDateUnavailable` to disable weekends.
:component-preview{component="date-picker" name="form"}
### With Time
Integrate a time input with the date picker using `CalendarDateTime` from `@internationalized/date`. The time input
updates the hour and minute of the selected date value.
:component-preview{component="date-picker" name="with-time"}
## API
See [Ark UI Date Picker docs](https://ark-ui.com/vue/docs/components/date-picker){rel=""nofollow""} for full props and examples.
# Dialog
:component-preview{component="dialog" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/dialog.json
---
::
## Usage
```vue
```
## Composition
```text
Dialog.Root
├── Dialog.Body
├── Dialog.Actions
├── Dialog.CloseTrigger
├── Dialog.Content
├── Dialog.Context
├── Dialog.Description
├── Dialog.RootProvider
├── Dialog.ScrollContainer
├── Dialog.ScrollSection
├── Dialog.Title
├── Dialog.Trigger
```
## Examples
### Controlled
Manage the dialog state using the `open` and `onOpenChange` props.
:component-preview{component="dialog" name="controlled"}
### Root Provider
An alternative way to control the dialog is to use the `RootProvider` component and the `useDialog` hook. This way you can access the state and methods from outside the component.
:component-preview{component="dialog" name="root-provider"}
### Alert Dialog
For critical confirmations or destructive actions, use `role="alertdialog"`. Alert dialogs differ from regular dialogs in important ways:
- **Automatic focus**: The close/cancel button receives focus when opened, prioritizing the safest action
- **Requires explicit dismissal**: Cannot be closed by clicking outside, only via button clicks or Escape key
:component-preview{component="dialog" name="alert-dialog"}
### Lazy Mount
Use `lazyMount` to render dialog content only when first opened. Combine with `unmountOnExit` to unmount when closed, freeing up resources. Prefer this over conditionally rendering `Dialog.Root`—see **Conditional Rendering** in the [Ark UI docs](https://ark-ui.com/vue/docs/components/dialog){rel=""nofollow""}.
:component-preview{component="dialog" name="lazy-mount"}
### Initial Focus
Use `initialFocusEl` to control which element receives focus when the dialog opens.
:component-preview{component="dialog" name="initial-focus"}
### Final Focus
Use `finalFocusEl` to control which element receives focus when the dialog closes. Defaults to the trigger element.
:component-preview{component="dialog" name="final-focus"}
### Non-Modal
Use `modal={false}` to allow interaction with elements outside the dialog. Disables focus trapping and scroll prevention.
:component-preview{component="dialog" name="non-modal"}
### Inside Scroll
Make the content area scrollable while keeping header and footer fixed using `maxHeight` and `overflow: auto`.
:component-preview{component="dialog" name="inside-scroll"}
### Outside Scroll
Make the positioner scrollable so the dialog can extend beyond the viewport.
:component-preview{component="dialog" name="outside-scroll"}
### Context
Access the dialog's state and methods with `Dialog.Context` or the `useDialogContext` hook.
:component-preview{component="dialog" name="context"}
### Open from Menu
Open a dialog imperatively from a menu item using the `onClick` handler.
:component-preview{component="dialog" name="open-from-menu"}
### Nested
Nest dialogs within one another. The parent receives `data-has-nested` and `--nested-layer-count` CSS variable for styling effects like zoom-out.
:component-preview{component="dialog" name="nested"}
### Multiple Triggers
Share a single dialog across multiple trigger elements. Pass a `value` to each `Dialog.Trigger` and use `onTriggerValueChange` to update the dialog content based on which trigger was clicked.
:component-preview{component="dialog" name="multiple-triggers"}
### Confirmation
Intercept close attempts to show confirmation prompts, preventing data loss from unsaved changes.
:component-preview{component="dialog" name="confirmation"}
## API
See [Ark UI Dialog docs](https://ark-ui.com/vue/docs/components/dialog){rel=""nofollow""} for full props and examples.
# DialogCaller
:component-preview{component="dialog-caller" name="basic"}
## Features
- **Programmatic API** — Register a component once with `useDialogCaller()`, then `await caller.call(props)` from any handler
- **Promise-based results** — Components finish calls with `call.resolve()` or `call.reject()`; the outer promise always resolves (shape configurable)
- **Stack support** — Nested and concurrent dialogs mount as separate stack entries with automatic z-index layering
- **Optional dialog shell** — `DialogCaller.DialogShell` wires open state and external dismiss for Ark UI dialogs
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/dialog-caller.json
---
::
## Setup
Mount the host once in your app root:
```vue
```
## Usage
Register a dialog component once, then call it imperatively:
```vue
```
Inside the called component, use `useDialogCallerContext()` and assign it to `call`:
```vue
Delete {{ props.name }}?
```
## Composition
```text
DialogCaller.Host
└── (dynamic stack entries)
DialogCaller.Provider
└── custom host wiring via useDialogCallerHost()
DialogCaller.DialogShell
└── Dialog.Content
└── your dialog UI
```
## Examples
### Delete confirmation
Use a single `useDialogCaller` registration for the whole table — no dialog duplicated per row:
:component-preview{component="dialog-caller" name="basic"}
### Nested dialogs
Edit the form, then cancel with unsaved changes. The confirmation dialog stacks on top while the form stays mounted:
:component-preview{component="dialog-caller" name="nested"}
## API
### `useDialogCaller(component, options?)`
Returns `{ call(props), reject() }`.
| Option | Type | Default | Description |
| -------------------- | ------------------------------ | -------------- | ------------------------------------------------------------------------------- |
| `id` | `string` | component name | Registry key for idempotent registration |
| `exitDuration` | `number` | `200` | Milliseconds to keep the instance mounted after resolve/reject (exit animation) |
| `resultShape` | `"cancelled" | "data" | "raw"` | `"cancelled"` | Shape of the value returned by `call()` |
| `defaultRejectValue` | `unknown` | `null` | Value returned on reject when `resultShape` is `"raw"` |
### `useDialogCallerContext()`
Returns `{ props, phase, resolve, reject, id }`. Assign to `call` and use `call.resolve()` / `call.reject()` without destructuring.
### Result shapes
| `resultShape` | After `call.resolve(data)` | After `call.reject(reason?)` |
| ------------- | ------------------------------------------ | ------------------------------------------ |
| `"cancelled"` | `{ cancelled: false, data, reason: null }` | `{ cancelled: true, data: null, reason? }` |
| `"data"` | `{ data }` | `{ data: null }` |
| `"raw"` | `data` | `defaultRejectValue` |
## Notes
- Each `call()` mounts a new stack entry. For HTTP-heavy dialogs, fetch data from props (e.g. with `watch`) rather than in `onMounted`.
- `DialogCaller.Host` must be mounted before calling `call()` — otherwise an error is thrown.
# Drawer
:component-preview{component="drawer" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/drawer.json
---
::
## Usage
```vue
```
## Composition
```text
Drawer.Root
├── Drawer.CloseTrigger
├── Drawer.Content
├── Drawer.Description
├── Drawer.Context
├── Drawer.Grabber
├── Drawer.GrabberIndicator
├── Drawer.Indent
├── Drawer.IndentBackground
├── Drawer.RootProvider
├── Drawer.Stack
├── Drawer.SwipeArea
├── Drawer.Title
├── Drawer.Trigger
```
## Examples
### Swipe Direction
Use the `swipeDirection` prop to control which edge the drawer slides in from.
:component-preview{component="drawer" name="swipe-direction"}
### Snap Points
Use the `snapPoints` prop to define intermediate positions the drawer can snap to.
:component-preview{component="drawer" name="snap-points"}
### Modal
Set `modal` to `false` to allow interaction with the rest of the page while the drawer is open.
:component-preview{component="drawer" name="modal"}
### Controlled
Use the `open` and `onOpenChange` props to control the drawer state.
:component-preview{component="drawer" name="controlled"}
### Scrollable
:component-preview{component="drawer" name="scrollable"}
### No Drag Area
Apply the `data-no-drag` attribute to any element inside the drawer to prevent dragging from starting on it.
:component-preview{component="drawer" name="no-drag-area"}
### Non Draggable
Set `draggable` to `false` to disable drag-to-dismiss entirely.
:component-preview{component="drawer" name="non-draggable"}
### Indent Background
Use `Drawer.IndentBackground` to create a visual indent effect on the page behind the drawer.
:component-preview{component="drawer" name="indent-background"}
### Multiple Triggers
Use the `value` prop on `Drawer.Trigger` to share a single drawer across multiple trigger elements. The `onTriggerValueChange` callback fires when a different trigger is activated.
:component-preview{component="drawer" name="multiple-triggers"}
### Using the Root Provider
Use the `useDrawer` hook and `Drawer.RootProvider` to control the drawer from outside the component tree.
:component-preview{component="drawer" name="root-provider"}
## API
See [Ark UI Drawer docs](https://ark-ui.com/vue/docs/components/drawer){rel=""nofollow""} for full props and examples.
# Editable
:component-preview{component="editable" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/editable.json
---
::
## Usage
Wrap `Editable` in `Field` and use `Field.Label` instead of a dedicated editable label.
```vue
Label
```
## Examples
### Controlled
Use the `value` and `onValueChange` props to control the editable state.
:component-preview{component="editable" name="controlled"}
### Root Provider
An alternative way to control the editable is to use the `RootProvider` component and the `useEditable` hook. This way you can access the state and methods from outside the component.
:component-preview{component="editable" name="root-provider"}
### Context
Access the editable's state with `Editable.Context` or the `useEditableContext` hook—great for showing keyboard hints when editing.
:component-preview{component="editable" name="context"}
### Controls
In some cases, you might need to use custom controls to toggle the edit and read mode. We use the render prop pattern to provide access to the internal state of the component.
:component-preview{component="editable" name="controls"}
### Textarea
Use the `asChild` prop on `Editable.Input` to render a textarea for multi-line editing.
:component-preview{component="editable" name="textarea"}
### Field
The `Field` component helps manage form-related state and accessibility attributes of an editable. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.
:component-preview{component="editable" name="field"}
## Composition
```text
Field.Root
├── Field.Label
├── Editable.Root
│ ├── Editable.Area
│ │ ├── Editable.Input
│ │ └── Editable.Preview
│ ├── Editable.Control
│ │ ├── Editable.EditTrigger
│ │ ├── Editable.SubmitTrigger
│ │ └── Editable.CancelTrigger
│ └── Editable.Context
└── Field.HelperText / Field.ErrorText
```
## API
See [Ark UI Editable docs](https://ark-ui.com/vue/docs/components/editable){rel=""nofollow""} for full props and examples.
# Empty
:component-preview{component="empty" name="basic"}
## Features
- **Composable** — Flexible slot-based layout with `Empty.Header`, `Empty.Media`, `Empty.Title`, `Empty.Description`, and `Empty.Content`
- **Styled primitives** — Opinionated defaults for spacing, typography, and icon media
- **Customizable** — Override any part with the `class` prop
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/empty.json
---
::
## Usage
```vue
No dataNo data found
```
## Composition
```text
Empty.Root
├── Empty.Header
│ ├── Empty.Media
│ ├── Empty.Title
│ └── Empty.Description
└── Empty.Content
```
## Examples
### Outline
Use the `border` utility class to create an outline empty state.
:component-preview{component="empty" name="outline"}
### Background
Use the `bg-*` utilities to add a background to the empty state.
:component-preview{component="empty" name="muted"}
### Avatar
Use `Empty.Media` to display an avatar in the empty state.
:component-preview{component="empty" name="avatar"}
### Avatar Group
Use `Empty.Media` to display an avatar group in the empty state.
:component-preview{component="empty" name="avatar-group"}
### Input Group
Add an `InputGroup` component to `Empty.Content`.
:component-preview{component="empty" name="input-group"}
## API
### Empty.Media
| Prop | Type | Default | Description |
| --------- | -------------------- | ----------- | ----------------------------------- |
| `variant` | `"default" | "icon"` | `"default"` | Visual style of the media container |
| `class` | `string` | — | Additional CSS classes |
# Field
:component-preview{component="field" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/field.json
---
::
## Usage
```vue
```
## Examples
The `Field` component provides contexts such as `invalid`, `disabled`, `required`, and `readOnly` for form elements. While most Ark UI components natively support these contexts, you can also use the `Field` component with standard HTML form elements.
### Input
This example shows how to use the `Field` component with a standard input field.
:component-preview{component="field" name="basic"}
### Textarea
This example illustrates how to use the `Field` component with a textarea element.
:component-preview{component="field" name="textarea"}
### Textarea Autoresize
Pass the `autoresize` prop to the `Textarea` component to enable automatic resizing as the user types.
:component-preview{component="field" name="textarea-autoresize"}
### Select
This example demonstrates how to integrate the `Field` component with a select dropdown.
:component-preview{component="field" name="select"}
### Root Provider
An alternative way to control the field is to use the `RootProvider` component and the `useField` hook. This way you can access the state and methods from outside the component.
:component-preview{component="field" name="root-provider"}
### Custom Control
Use the `Field.Context` or `useFieldContext` hook to access the internal state of the field. This can help you wire up custom controls with the `Field` component.
:component-preview{component="field" name="custom-control"}
## Composition
```text
Field.Root
├── Field.Context
├── Field.ErrorText
├── Field.HelperText
├── Field.Input
├── Field.Item
├── Field.Label
├── Field.RequiredIndicator
├── Field.RootProvider
├── Field.Select
├── Field.Textarea
```
## API
See [Ark UI Field docs](https://ark-ui.com/vue/docs/components/field){rel=""nofollow""} for full props and examples.
# Fieldset
:component-preview{component="fieldset" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/fieldset.json
---
::
## Usage
```vue
```
## Composition
```text
Fieldset.Root
├── Fieldset.Context
├── Fieldset.ErrorText
├── Fieldset.HelperText
├── Fieldset.Legend
├── Fieldset.RootProvider
```
## Examples
The `Fieldset` component provides contexts such as `invalid` and `disabled` for form elements. While most Ark UI components natively support these contexts, you can also use the `Field` component with standard HTML form elements.
### Field
This example demonstrates how to use the `Field` component with a standard input field within a `Fieldset`.
:component-preview{component="fieldset" name="field"}
### Checkbox
This example shows how to use the `Fieldset` component with other Ark UI form elements like `Checkbox`.
:component-preview{component="fieldset" name="checkbox"}
### Root Provider
An alternative way to control the fieldset is to use the `RootProvider` component and the `useFieldset` hook. This way you can access the state and methods from outside the component.
:component-preview{component="fieldset" name="root-provider"}
### Input with Select
This example shows how to use the `Fieldset` component with `Field.Input` and `Select` to create a interactive phone input component.
:component-preview{component="fieldset" name="input-with-select"}
## API
See [Ark UI Fieldset docs](https://ark-ui.com/vue/docs/components/fieldset){rel=""nofollow""} for full props and examples.
# File Upload
:component-preview{component="file-upload" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/file-upload.json
---
::
## Usage
```vue
File UploadChoose file(s)X
```
## Composition
```text
FileUpload.Root
├── FileUpload.Label
├── FileUpload.Dropzone
│ └── FileUpload.Trigger
├── FileUpload.ItemGroup
│ └── FileUpload.Item
│ ├── FileUpload.ItemPreview
│ │ └── FileUpload.ItemPreviewImage
│ ├── FileUpload.ItemName
│ ├── FileUpload.ItemSizeText
│ └── FileUpload.ItemDeleteTrigger
├── FileUpload.ClearTrigger
├── FileUpload.HiddenInput
├── FileUpload.Context
└── FileUpload.RootProvider
```
## Examples
### Initial Files
Use the `defaultAcceptedFiles` prop to set the initial files in the file upload component.
:component-preview{component="file-upload" name="initial-files"}
### Clear Trigger
Use the `ClearTrigger` to remove all uploaded files at once.
:component-preview{component="file-upload" name="clear-trigger"}
### Dropzone
Use the `Dropzone` to enable drag-and-drop. It exposes a `data-dragging` attribute for styling.
:component-preview{component="file-upload" name="dropzone"}
### Directory Upload
Use the `directory` prop to upload entire folders. Access file paths through `file.webkitRelativePath`.
:component-preview{component="file-upload" name="directory-upload"}
> When uploading directories with many files, set `maxFiles` to a higher value or remove it entirely to prevent rejections.
### Accepted File Types
Use the `accept` prop to restrict file types. Accepts MIME types (`image/png`) or extensions (`.pdf`).
:component-preview{component="file-upload" name="accepted-file-types"}
### Error Handling
Set constraints with `maxFiles`, `maxFileSize`, `minFileSize`, and `accept`. Rejected files include error codes like `TOO_MANY_FILES`, `FILE_INVALID_TYPE`, `FILE_TOO_LARGE`, or `FILE_EXISTS`.
:component-preview{component="file-upload" name="error-handling"}
### File Transformations
Use `transformFiles` to process files before they're added. Useful for image compression, format conversion, or resizing.
:component-preview{component="file-upload" name="file-transformations"}
### Field
Use `Field` to add helper text and error handling.
:component-preview{component="file-upload" name="field"}
### Root Provider
An alternative way to control the file upload is to use the `RootProvider` component and the `useFileUpload` hook. This way you can access the state and methods from outside the component.
:component-preview{component="file-upload" name="root-provider"}
### Pasting Files
Use `setClipboardFiles` to enable pasting images from the clipboard.
:component-preview{component="file-upload" name="pasting-files"}
### Media Capture
Use `capture` to access the device camera. Set to `"environment"` for back camera or `"user"` for front camera.
:component-preview{component="file-upload" name="media-capture"}
### Rejected Files
Access `rejectedFiles` from the context to display validation errors.
:component-preview{component="file-upload" name="rejected-files"}
## API
See [Ark UI File Upload docs](https://ark-ui.com/vue/docs/components/file-upload){rel=""nofollow""} for full props and examples.
# Filters
:component-preview{component="filters" name="basic"}
## Features
- Typed field factories.
- Text, number, date, boolean, select, and multi-select values.
- Long or short filter chips.
- Groups and nested menus.
- `outline` and `secondary` variants.
- `sm`, `md`, and `lg` sizes.
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/filters.json
---
::
## Usage
```vue
```
## Composition
Use the following composition to build a Filters setup:
```text
Filters.Provider
├── Filters.Menu
│ ├── Filters.MenuTrigger
│ └── Filters.MenuContent
├── Filters.Group
│ └── Filters.Item
└── Filters.Clear
```
## Examples
### Sizes and variants
Set `variant` and `size` on `Filters.Provider`, use `filter-style="short"` on `Filters.Group` to show only values.
:component-preview{component="filters" name="short"}
### Custom menu trigger
Provide a custom trigger via the `Filters.MenuTrigger` slot.
:component-preview{component="filters" name="custom-menu"}
## API Reference
### Components
| Component | Use |
| --------------------- | --------------------------------- |
| `Filters.Provider` | Root state and context. |
| `Filters.Menu` | Add-filter dropdown. |
| `Filters.MenuTrigger` | Default trigger, or custom slot. |
| `Filters.MenuContent` | Field list, groups, and submenus. |
| `Filters.Group` | Chip wrapper. |
| `Filters.Item` | One filter chip. |
| `Filters.Clear` | Clears all filters. |
### Filters.Provider
| Prop | Type | Default |
| --------- | ------------------------- | ----------- |
| `filters` | `Filter[]` | `[]` |
| `fields` | `FilterFieldItem[]` | - |
| `variant` | `"outline" | "secondary"` | `"outline"` |
| `size` | `"sm" | "md" | "lg"` | `"md"` |
### Filters.Group
| Prop | Type | Default |
| ------------- | ------------------ | -------- |
| `filterStyle` | `"long" | "short"` | `"long"` |
### Fields
Build fields with `Field.*`.
| Helper | Extra options |
| -------------------- | ------------------------------------ |
| `Field.TextField` | `minLength`, `maxLength` |
| `Field.NumberField` | `min`, `max`, `step`, `numberFormat` |
| `Field.DateField` | `min`, `max` |
| `Field.BooleanField` | `trueValue`, `falseValue` |
| `Field.Group` | `label`, `fields` |
| `Field.Submenu` | `label`, `icon`, `fields` |
Common field options: `key`, `label`, `icon`, `operators`.
```ts
const fields = [
Field.TextField({
key: "name",
label: "Name",
operators: [
Operator.Contain({ label: "contains" })
],
}),
];
```
### Operators
Build operators with `Operator.*`.
| Helper | Value | Input |
| --------------------- | -------------- | ------------------- |
| `Operator.Eq` | `eq` | `input` or `select` |
| `Operator.Neq` | `neq` | `input` or `select` |
| `Operator.Contain` | `contains` | `input` |
| `Operator.NotContain` | `not_contains` | `input` |
| `Operator.In` | `in` | `multi-select` |
| `Operator.Nin` | `nin` | `multi-select` |
| `Operator.Btw` | `btw` | `range` |
| `Operator.Null` | `is_null` | `none` |
| `Operator.NotNull` | `not_null` | `none` |
| `Operator.Gt` | `gt` | `input` |
| `Operator.Lt` | `lt` | `input` |
Common operator options: `label`, `default`, `defaultValue`, `options`.
```ts
Operator.In({
label: "any of",
options: {
items: [
{ label: "Active", value: "active" },
{ label: "Pending", value: "pending" },
],
},
});
```
### Filter
Active filters are plain objects.
```ts
const filters: Filter[] = [
{ field: "status", operator: "in", value: ["active", "pending"] },
{ field: "price", operator: "btw", value: [100, 500] },
];
```
`FilterValue` can be `string`, `string[]`, `number`, `number[]`, `boolean`, `CalendarDate`, `CalendarDate[]`, `{ start, end }`, or `null`.
# Floating Panel
:component-preview{component="floating-panel" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/floating-panel.json
---
::
## Usage
```vue
```
## Composition
```text
FloatingPanel.Root
├── FloatingPanel.Body
├── FloatingPanel.CloseTrigger
├── FloatingPanel.Content
├── FloatingPanel.Context
├── FloatingPanel.DragTrigger
├── FloatingPanel.Header
├── FloatingPanel.Positioner
├── FloatingPanel.ResizeTrigger
├── FloatingPanel.StageTrigger
├── FloatingPanel.RootProvider
├── FloatingPanel.Title
├── FloatingPanel.Trigger
├── FloatingPanel.Control
```
## Examples
### Controlled size
To control the size of the floating panel programmatically, you can pass the `size` `onResize` prop to the machine.
:component-preview{component="floating-panel" name="controlled-size"}
### Controlled position
To control the position of the floating panel programmatically, you can pass the `position` and `onPositionChange` prop to the machine.
:component-preview{component="floating-panel" name="controlled-position"}
### Anchor Position
Use the `getAnchorPosition` function to compute the initial position of the floating panel. This function is called when the panel is opened and receives the `triggerRect` and `boundaryRect`.
:component-preview{component="floating-panel" name="anchor-position"}
### Open State
To control the open state of the floating panel programmatically, you can pass the `open` and `onOpenChange` prop to the machine.
:component-preview{component="floating-panel" name="open-state"}
### Lazy Mount
To lazy mount the floating panel, you can pass the `lazyMount` prop to the machine.
:component-preview{component="floating-panel" name="lazy-mount"}
### Context
To access the context of the floating panel, you can use the `useFloatingPanelContext` hook or the `FloatingPanel.Context` component.
:component-preview{component="floating-panel" name="context"}
## API
See [Ark UI Floating Panel docs](https://ark-ui.com/vue/docs/components/floating-panel){rel=""nofollow""} for full props and examples.
# Hover Card
:component-preview{component="hover-card" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/hover-card.json
---
::
## Usage
```vue
```
## Composition
```text
HoverCard.Root
├── HoverCard.ArrowTip
├── HoverCard.Arrow
├── HoverCard.Content
├── HoverCard.Context
├── HoverCard.Positioner
├── HoverCard.RootProvider
├── HoverCard.Trigger
```
## Examples
### Controlled
The controlled `HoverCard` component provides an interface for managing the state of the hover card using the `open` and `onOpenChange` props:
:component-preview{component="hover-card" name="controlled"}
### Root Provider
An alternative way to control the hover card is to use the `RootProvider` component and the `useHoverCard` hook. This way you can access the state and methods from outside the component.
:component-preview{component="hover-card" name="root-provider"}
### Delay
Control the open and close delay of the hover card using the `openDelay` and `closeDelay` props:
:component-preview{component="hover-card" name="delay"}
### Positioning
The `HoverCard` component can be customized in its placement and distance from the trigger element through the `positioning` prop:
:component-preview{component="hover-card" name="positioning"}
### Context
Access the hover card's state with `HoverCard.Context` or the `useHoverCardContext` hook:
:component-preview{component="hover-card" name="context"}
### Multiple Triggers
Share a single hover card across multiple trigger elements. Pass a `value` to each `HoverCard.Trigger` — the card repositions to the active trigger without closing.
:component-preview{component="hover-card" name="multiple-triggers"}
## API
See [Ark UI Hover Card docs](https://ark-ui.com/vue/docs/components/hover-card){rel=""nofollow""} for full props and examples.
# Image
:component-preview{component="image" name="basic"}
## Features
- **Loading states** — Automatic detection of loading, error, and success states
- **Fallback support** — Display placeholder content during loading or on error
- **Composable** — Flexible slot-based architecture with `Image.Source`, `Image.Loading`, `Image.Error`, and `Image.Fallback`
- **Zag-powered** — State machine API via `useImage` and `Image.Provider`
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/image.json
---
::
## Usage
```vue
An error occurred while loading the image.
```
## Composition
```text
Image.Root
├── Image.Source
├── Image.Loading
├── Image.Error
└── Image.Fallback
```
## Examples
### Fallback
Use `Image.Fallback` to display a placeholder while the image is loading or when it fails to load.
:component-preview{component="image" name="fallback"}
### Loading
Use `Image.Loading` to show a dedicated loading indicator.
:component-preview{component="image" name="loading"}
### Controlled
For a controlled image, manage the state with `v-model:state`. When controlled, image load and error events no longer update the state automatically — use `setState` from `useImage` or bind the model yourself.
:component-preview{component="image" name="controlled"}
## API
Built with a custom Zag.js state machine. Use `useImage()` with `Image.Provider` for imperative control (`api.value.setState(...)`, `api.value.state`). Polymorphic parts use Ark UI `ark` / `as-child`.
# Image Cropper
:component-preview{component="image-cropper" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/image-cropper.json
---
::
## Usage
```vue
```
## Composition
```text
ImageCropper.Root
├── ImageCropper.Context
├── ImageCropper.Grid
├── ImageCropper.Handle
├── ImageCropper.Image
├── ImageCropper.RootProvider
├── ImageCropper.Selection
└── ImageCropper.Viewport
```
## Examples
### Aspect Ratio
Lock the crop area to a specific aspect ratio. Use the `aspectRatio` prop—pass a number like `16/9` for widescreen or `1` for square.
:component-preview{component="image-cropper" name="aspect-ratio"}
### Circle Crop
Use `cropShape="circle"` for profile pictures or avatars. The selection becomes a circle instead of a rectangle.
:component-preview{component="image-cropper" name="circle-crop"}
### Initial Crop
Start with a pre-defined crop area using the `initialCrop` prop. Pass an object with `x`, `y`, `width`, and `height` in pixels.
:component-preview{component="image-cropper" name="initial-crop"}
### Controlled Zoom
Control zoom programmatically with the `zoom` and `onZoomChange` props. Useful when you want external buttons to zoom in and out.
:component-preview{component="image-cropper" name="controlled-zoom"}
### Zoom Limits
Set `minZoom` and `maxZoom` to constrain how far users can zoom. Prevents over-zooming or zooming out past the image bounds.
:component-preview{component="image-cropper" name="zoom-limits"}
### Rotation
Rotate the image with the `rotation` and `onRotationChange` props. Values are in degrees—common increments are 90 or 180.
:component-preview{component="image-cropper" name="rotation"}
### Flip
Flip the image horizontally or vertically using the `flip` prop. Pass an object with `horizontal` and `vertical` booleans.
:component-preview{component="image-cropper" name="flip"}
### Min and Max Size
Constrain the crop area size with `minWidth`, `minHeight`, `maxWidth`, and `maxHeight`. Keeps the selection within sensible bounds.
:component-preview{component="image-cropper" name="min-and-max-size"}
### Fixed Crop Area
Set `fixedCropArea` to `true` when the crop area should stay fixed while the image moves underneath. Useful for overlay-style cropping.
:component-preview{component="image-cropper" name="fixed-crop-area"}
### Crop Preview
Use `getCroppedImage()` from the context to get the cropped result. Call it with `{ output: 'dataUrl' }` for a base64 string you can use in an `img` src.
:component-preview{component="image-cropper" name="crop-preview"}
### Reset
The context exposes a `reset()` method that restores the image to its initial state. Handy for an "undo" or "start over" button.
:component-preview{component="image-cropper" name="reset"}
### Events
Listen to `onCropChange` and `onZoomChange` to track crop position and zoom level. Use these to sync with external state or show live previews.
:component-preview{component="image-cropper" name="events"}
### Context
Use `ImageCropper.Context` to access the cropper API from anywhere inside the root. You get methods like `zoomBy`, `rotateBy`, and `setZoom`.
:component-preview{component="image-cropper" name="context"}
### Root Provider
Use `RootProvider` with `useImageCropper` when you need to control the cropper from outside the component tree. Build custom toolbars or integrate with form state.
:component-preview{component="image-cropper" name="root-provider"}
## API
See [Ark UI Image Cropper docs](https://ark-ui.com/vue/docs/components/image-cropper){rel=""nofollow""} for full props and examples.
# Input
:component-preview{component="input" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/input.json
---
::
## Usage
```vue
```
## Examples
### Sizes
Use the `size` prop to change the height of the input.
:component-preview{component="input" name="sizes"}
### Field
Combine the `Input` component with `Field` to add a label, helper text, and validation context.
:component-preview{component="input" name="field"}
See [Ark UI Field docs](https://ark-ui.com/vue/docs/components/field){rel=""nofollow""} for field composition patterns.
# Input Group
:component-preview{component="input-group" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/input-group.json
---
::
## Usage
```vue
```
## Composition
```text
InputGroup.Root
├── InputGroup.Input or InputGroup.Textarea
├── InputGroup.Addon
├── InputGroup.Button
└── InputGroup.Text
```
For proper focus management, `InputGroupAddon` should always be placed after `InputGroupInput` or `InputGroupTextarea` in the DOM. Use the `align` prop to visually position the addon.
## Examples
### Icon
Add icons inside `InputGroupAddon` to decorate the input.
:component-preview{component="input-group" name="icon"}
### Text
Use `InputGroupText` for inline prefixes, suffixes, and helper labels.
:component-preview{component="input-group" name="text"}
### Button
Add action buttons with `InputGroupButton` inside an addon.
:component-preview{component="input-group" name="button"}
### Tooltip
Wrap `InputGroupButton` with `Tooltip.Trigger` and `as-child` to add contextual help on hover.
:component-preview{component="input-group" name="tooltip"}
### Menu
Use `Menu.Trigger` with `as-child` on `InputGroupButton` to attach a dropdown menu to the input.
:component-preview{component="input-group" name="menu"}
## Align
Use the `align` prop on `InputGroupAddon` to position the addon relative to the input:
| Value | Description |
| -------------- | ---------------------------- |
| `inline-start` | Start of the input (default) |
| `inline-end` | End of the input |
| `block-start` | Above the input |
| `block-end` | Below the input |
Works with both `InputGroupInput` and `InputGroupTextarea`.
# Json Tree View
:component-preview{component="json-tree-view" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/json-tree-view.json
---
::
## Usage
```vue
```
## Composition
```text
JsonTreeView.Root
├── JsonTreeView.RootProvider
└── JsonTreeView.Tree
```
## Examples
### Different Data Types
The JSON tree view can display various JavaScript data types including objects, arrays, primitives, and special values:
:component-preview{component="json-tree-view" name="array-data"}
### Functions and Methods
Display JavaScript functions, async functions, and generators in your JSON tree:
:component-preview{component="json-tree-view" name="functions"}
### Regular Expressions
Regular expressions are displayed with their pattern and flags:
:component-preview{component="json-tree-view" name="regex"}
### Error Objects
Error objects and their stack traces can be visualized:
:component-preview{component="json-tree-view" name="errors"}
### Map and Set Objects
Native JavaScript Map and Set objects are supported:
:component-preview{component="json-tree-view" name="map-and-set"}
### Controlling Expand Level
Use the `defaultExpandedDepth` prop to control how many levels are expanded by default:
:component-preview{component="json-tree-view" name="expand-level"}
### Custom Value Rendering
You can customize how specific values are rendered using the `renderValue` prop. This example shows how to make email addresses clickable:
:component-preview{component="json-tree-view" name="render-value"}
### Configuration Options
The JSON tree view supports several configuration options to customize the display:
```vue
```
**Configuration Options:**
- **`quotesOnKeys`**: Whether to show quotes around object keys
- **`showNonenumerable`**: Whether to show non-enumerable properties
- **`maxPreviewItems`**: Maximum number of items to show in object/array previews
- **`collapseStringsAfterLength`**: Collapse strings longer than this length
- **`groupArraysAfterLength`**: Group array items when array is longer than this length
### Using the Root Provider
The `RootProvider` component provides a context for the JSON tree view. It accepts the value of the `useJsonTreeView` hook. You can leverage it to access the component state and methods from outside the JSON tree view.
:component-preview{component="json-tree-view" name="root-provider"}
> If you're using the `RootProvider` component, you don't need to use the `Root` component.
## API
See [Ark UI Json Tree View docs](https://ark-ui.com/vue/docs/utilities/json-tree-view){rel=""nofollow""} for full props and examples.
# Kbd
:component-preview{component="kbd" name="basic"}
## Features
- **Semantic** — Renders as a native `kbd` element
- **Composable** — Pair `Kbd.Item` with `Kbd.Group` for key combinations
- **Context-aware** — Adapts contrast when used inside tooltip content
- **Customizable** — Override styles with the `class` prop
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/kbd.json
---
::
## Usage
```vue
Ctrl
```
## Composition
```text
Kbd.Item
Kbd.Group
├── Kbd.Item
└── Kbd.Item
```
## Examples
### Group
Use `Kbd.Group` to group keyboard keys together.
:component-preview{component="kbd" name="group"}
### Button
Use `Kbd.Item` inside a `Button` to show a keyboard shortcut.
:component-preview{component="kbd" name="button"}
### Tooltip
Use `Kbd.Item` inside a `Tooltip` to show a keyboard shortcut on hover.
:component-preview{component="kbd" name="tooltip"}
### Input Group
Use `Kbd.Item` inside an `InputGroup.Addon` to hint at a keyboard shortcut.
:component-preview{component="kbd" name="input-group"}
## API
### Kbd.Item
| Prop | Type | Default | Description |
| ------- | -------- | ------- | ---------------------- |
| `class` | `string` | — | Additional CSS classes |
### Kbd.Group
| Prop | Type | Default | Description |
| ------- | -------- | ------- | ---------------------- |
| `class` | `string` | — | Additional CSS classes |
# Listbox
:component-preview{component="listbox" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/listbox.json
---
::
## Usage
```vue
```
## Examples
### Controlled
The Listbox component can be controlled by using the `value` and `onValueChange` props. This allows you to manage the selected value externally.
:component-preview{component="listbox" name="controlled"}
### Root Provider
An alternative way to control the listbox is to use the `RootProvider` component and the `useListbox` hook. This way you can access the state and methods from outside the component.
:component-preview{component="listbox" name="root-provider"}
### Disabled Item
Listbox items can be disabled using the `disabled` prop on the collection item.
:component-preview{component="listbox" name="disabled-item"}
### Multiple
You can set the `selectionMode` property as `multiple` to allow the user to select multiple items at a time.
:component-preview{component="listbox" name="multiple"}
### Grouping
The Listbox component supports grouping items. You can use the `groupBy` function to group items based on a specific property.
:component-preview{component="listbox" name="grouping"}
### Extended Selection
The extended selection mode allows users to select multiple items using keyboard modifiers like `Cmd` (Mac) or `Ctrl` (Windows/Linux).
:component-preview{component="listbox" name="extended-selection"}
### Horizontal
Use the `orientation` prop to display the listbox items horizontally.
:component-preview{component="listbox" name="horizontal"}
### Grid Layout
Use `createGridCollection` to display items in a grid layout with keyboard navigation support.
:component-preview{component="listbox" name="grid-layout"}
### Filtering
Use `useListCollection` with the `filter` function to enable filtering of items.
:component-preview{component="listbox" name="filtering"}
### Select All
Use `useListboxContext` to implement a "Select All" functionality that allows users to select or deselect all items at once.
:component-preview{component="listbox" name="select-all"}
### Value Text
Use `Listbox.ValueText` to display the selected values as a comma-separated string.
:component-preview{component="listbox" name="value-text"}
## Composition
```text
Listbox.Root
├── Listbox.Context
├── Listbox.Content
├── Listbox.Empty
├── Listbox.Input
├── Listbox.Item
├── Listbox.ItemContext
├── Listbox.ItemGroup
├── Listbox.ItemGroupLabel
├── Listbox.ItemIndicator
├── Listbox.ItemText
├── Listbox.Label
├── Listbox.RootProvider
├── Listbox.ValueText
```
## API
See [Ark UI Listbox docs](https://ark-ui.com/vue/docs/components/listbox){rel=""nofollow""} for full props and examples.
# Marquee
:component-preview{component="marquee" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/marquee.json
---
::
## Usage
```vue
```
## Composition
```text
Marquee.Root
├── Marquee.Edge
├── Marquee.Viewport
│ └── Marquee.Content
│ └── Marquee.Item
├── Marquee.Context
└── Marquee.RootProvider
```
## Examples
### Auto Fill
Use the `autoFill` prop to automatically duplicate content to fill the viewport. The `spacing` prop controls the gap between duplicated content instances:
:component-preview{component="marquee" name="auto-fill"}
### Reverse
Set the `reverse` prop to reverse the scroll direction:
:component-preview{component="marquee" name="reverse"}
### Vertical
Set `side="bottom"` (or `side="top"`) to create a vertical marquee:
:component-preview{component="marquee" name="vertical"}
### Speed
Control the animation speed using the `speed` prop, which accepts values in pixels per second:
:component-preview{component="marquee" name="speed"}
### Pause on Interaction
Enable `pauseOnInteraction` to pause the marquee when users hover or focus on it, improving accessibility:
:component-preview{component="marquee" name="pause-on-interaction"}
### Programmatic Control
Use the `useMarquee` hook with `Marquee.RootProvider` to access the marquee API and control playback programmatically:
:component-preview{component="marquee" name="programmatic-control"}
> If you're using the `Marquee.RootProvider` component, you don't need to use the `Marquee.Root` component.
### Loops
Set the `loopCount` prop to run the marquee a specific number of times. Use `onLoopComplete` to track each loop iteration and `onComplete` to know when all loops finish:
:component-preview{component="marquee" name="finite-loops"}
### Edges
Add `Marquee.Edge` components to create fade effects at the start and end of the scrolling area:
:component-preview{component="marquee" name="with-edges"}
## API
See [Ark UI Marquee docs](https://ark-ui.com/vue/docs/components/marquee){rel=""nofollow""} for full props and examples.
# Menu
:component-preview{component="menu" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/menu.json
---
::
## Usage
```vue
```
## Composition
```text
Menu.Root
├── Menu.ArrowTip
├── Menu.Arrow
├── Menu.CheckboxItem
├── Menu.Content
├── Menu.ContextTrigger
├── Menu.Context
├── Menu.Empty
├── Menu.Filter
│ └── Menu.FilterInput
├── Menu.Indicator
├── Menu.ItemContext
├── Menu.ItemGroupLabel
├── Menu.ItemGroup
├── Menu.ItemIndicator
├── Menu.ItemText
├── Menu.Item
├── Menu.RadioItemGroup
├── Menu.RadioItem
├── Menu.RootProvider
├── Menu.Separator
├── Menu.TriggerItem
├── Menu.Trigger
```
## Examples
### Item Selection
Use `onSelect` to handle item selection. The callback receives the item's `id`.
:component-preview{component="menu" name="controlled"}
### Root Provider
An alternative way to control the menu is to use the `RootProvider` component and the `useMenu` hook. This way you can access the state and methods from outside the component.
:component-preview{component="menu" name="root-provider"}
### Grouping
Use `Menu.ItemGroup` and `Menu.ItemGroupLabel` to organize related menu items.
:component-preview{component="menu" name="grouping"}
### Links
To render menu items as links, use the `asChild` prop to replace the default element with an anchor tag.
:component-preview{component="menu" name="links"}
### Checkbox
To add a checkbox to a menu item, use the `Menu.CheckboxItem` component.
:component-preview{component="menu" name="checkbox"}
### Radio Group
To group radio option items, use the `Menu.RadioItemGroup` component.
:component-preview{component="menu" name="radio-group"}
### Context Menu
To show the menu when a trigger element is right-clicked, use the `Menu.ContextTrigger` component.
Context menus are also opened during a long-press of roughly `700ms` when the pointer is pen or touch.
:component-preview{component="menu" name="context"}
### Nested
To show a nested menu, render another `Menu` component and use the `Menu.TriggerItem` component to open the submenu.
:component-preview{component="menu" name="nested"}
### Menu in Dialog
When rendering a menu inside a dialog, use `lazyMount` and `unmountOnExit` to ensure proper cleanup when the dialog closes.
:component-preview{component="menu" name="in-dialog"}
### Menu Item Dialog
Open a confirmation dialog from a menu item. This pattern is useful for destructive actions like delete that require user confirmation.
:component-preview{component="menu" name="item-dialog"}
### Multiple Triggers
Share a single menu across multiple trigger elements. Pass a `value` to each `Menu.Trigger` — the menu repositions to whichever trigger is activated.
:component-preview{component="menu" name="multiple-triggers"}
### Filterable
Use `Menu.Filter` and `Menu.FilterInput` with `useMenuFilterCollection` to filter menu items. Set `:typeahead="false"` on `Menu.Root` so typing goes to the search field instead of menu typeahead.
:component-preview{component="menu" name="filterable"}
### Filterable Multiple
Combine a filterable menu with `Menu.CheckboxItem` and `:close-on-select="false"` for multi-select.
:component-preview{component="menu" name="filterable-multiple"}
## API
See [Ark UI Menu docs](https://ark-ui.com/vue/docs/components/menu){rel=""nofollow""} for full props and examples.
# Number Input
:component-preview{component="number-input" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/number-input.json
---
::
## Usage
```vue
```
## Composition
```text
NumberInput.Root
├── NumberInput.Label
├── NumberInput.Control layout="inset" | "segmented"
│ ├── NumberInput.Scrubber optional
│ ├── NumberInput.Input
│ ├── NumberInput.TriggerGroup optional — stacked steppers (inset only)
│ │ ├── NumberInput.IncrementTrigger
│ │ └── NumberInput.DecrementTrigger
│ ├── NumberInput.IncrementTrigger split steppers — left (+)
│ └── NumberInput.DecrementTrigger split steppers — right (−)
├── NumberInput.Context
├── NumberInput.RootProvider
└── NumberInput.ValueText
```
### Layout
`NumberInput.Control` accepts a `layout` prop to coordinate styles across parts:
- **`inset`** (default) — bordered input with steppers overlaid inside the field. Use `TriggerGroup` to stack increment/decrement on the right.
- **`segmented`** — flex row with a shared border on `Control`. Order: optional `Scrubber`, `IncrementTrigger` (+), `Input`, `DecrementTrigger` (−). The value is centered between the two triggers.
Padding and focus rings are derived from the chosen layout and child parts — no manual attributes on `Input` are required.
## Examples
### Split Controls
Use `layout="segmented"` on `Control`. Place `IncrementTrigger` on the left, `DecrementTrigger` on the right, and optionally add a `Scrubber` before the increment trigger.
:component-preview{component="number-input" name="split"}
### Min and Max
Pass the `min` prop or `max` prop to set an upper and lower limit for the input. By default, the input will restrict the value to stay within the specified range.
:component-preview{component="number-input" name="min-max"}
### Precision
In some cases, you might need the value to be rounded to specific decimal points. Set the `formatOptions` and provide `Intl.NumberFormatOptions` such as `maximumFractionDigits` or `minimumFractionDigits`.
:component-preview{component="number-input" name="precision"}
### Scrubbing
The NumberInput supports the scrubber interaction pattern. To use this pattern, render the `NumberInput.Scrubber` component. It uses the Pointer lock API and tracks the pointer movement. It also renders a virtual cursor which mimics the real cursor's pointer.
:component-preview{component="number-input" name="scrubbing"}
### Mouse Wheel
The NumberInput exposes a way to increment/decrement the value using the mouse wheel event. To activate this, set the `allowMouseWheel` prop to `true`.
:component-preview{component="number-input" name="mouse-wheel"}
### Formatting
To apply custom formatting to the input's value, set the `formatOptions` and provide `Intl.NumberFormatOptions` such as `style` and `currency`.
:component-preview{component="number-input" name="formatting"}
### Field
The `Field` component helps manage form-related state and accessibility attributes of a number input. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.
:component-preview{component="number-input" name="field"}
### Root Provider
An alternative way to control the number input is to use the `RootProvider` component and the `useNumberInput` hook. This way you can access the state and methods from outside the component.
:component-preview{component="number-input" name="root-provider"}
## API
See [Ark UI Number Input docs](https://ark-ui.com/vue/docs/components/number-input){rel=""nofollow""} for full props and examples.
# Pagination
:component-preview{component="pagination" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/pagination.json
---
::
## Usage
```vue
```
## Composition
```text
Pagination.Root
├── Pagination.Context
├── Pagination.Ellipsis
├── Pagination.FirstTrigger
├── Pagination.Item
├── Pagination.LastTrigger
├── Pagination.NextTrigger
├── Pagination.PrevTrigger
├── Pagination.RootProvider
```
## Examples
### Controlled
To create a controlled Pagination component, manage the state of the current page using the `page` prop and update it when the `onPageChange` event handler is called:
:component-preview{component="pagination" name="controlled"}
### Root Provider
An alternative way to control the pagination is to use the `RootProvider` component and the `usePagination` hook. This way you can access the state and methods from outside the component.
:component-preview{component="pagination" name="root-provider"}
### Customization
You can customize the Pagination component by setting various props such as `dir`, `pageSize`, `siblingCount`, and `translations`. Here's an example of a customized Pagination:
:component-preview{component="pagination" name="customized"}
### Context
Access pagination state and methods with `Pagination.Context` or the `usePaginationContext` hook. You get methods like `setPage`, `setPageSize`, `goToNextPage`, `goToPrevPage`, `goToFirstPage`, `goToLastPage`, as well as properties like `totalPages` and `pageRange`.
:component-preview{component="pagination" name="context"}
### Data Slicing
Use the `slice()` method to paginate actual data arrays. This method automatically slices your data based on the current page and page size.
:component-preview{component="pagination" name="data-slicing"}
### Page Range
Display the current page range information using the `pageRange` property. This shows which items are currently visible (e.g., "Showing 1-10 of 100 results").
:component-preview{component="pagination" name="page-range"}
### Page Size
Control the number of items per page dynamically using `setPageSize()`. This example shows how to integrate a native select element to change the page size.
> **Note:** For uncontrolled behavior, use `defaultPageSize` to set the initial value. For controlled behavior, use `pageSize` and `onPageSizeChange` to programmatically manage the page size.
:component-preview{component="pagination" name="page-size"}
### Links
Create pagination with link navigation for better SEO and accessibility. This example shows how to use the pagination component with anchor links instead of buttons.
:component-preview{component="pagination" name="links"}
## API
See [Ark UI Pagination docs](https://ark-ui.com/vue/docs/components/pagination){rel=""nofollow""} for full props and examples.
# Password Input
:component-preview{component="password-input" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/password-input.json
---
::
## Usage
```vue
```
## Composition
`PasswordInput.Root` wraps the control and input group internally. Compose the input and visibility trigger as direct children:
```text
PasswordInput.Root
├── PasswordInput.Input
└── PasswordInput.VisibilityTrigger
└── PasswordInput.Indicator
├── PasswordInput.Context
└── PasswordInput.RootProvider
```
Use [`Field`](https://vuzeno.com/docs/components/field) for labels, helper text, and validation context.
## Examples
### Sizes
Use the `size` prop on `PasswordInput.Root` to change the height of the input.
:component-preview{component="password-input" name="sizes"}
### Autocomplete
Use the `autoComplete` prop to manage autocompletion in the input.
- `new-password` — The user is creating a new password.
- `current-password` — The user is entering an existing password.
:component-preview{component="password-input" name="autocomplete"}
### Controlled Visibility
Use the `visible` and `onVisibilityChange` props to control the visibility of the password input.
:component-preview{component="password-input" name="controlled-visibility"}
### Root Provider
An alternative way to control the password input is to use the `RootProvider` component and the `usePasswordInput` hook. This way you can access the state and methods from outside the component.
:component-preview{component="password-input" name="root-provider"}
### Field
Combine `PasswordInput` with `Field` to add a label, helper text, and validation context.
:component-preview{component="password-input" name="field"}
### Password Managers
Use the `ignorePasswordManagers` prop to ignore password managers like 1Password, LastPass, etc. This is useful for non-login scenarios (e.g., "api keys", "secure notes", "temporary passwords").
:component-preview{component="password-input" name="ignore-password-manager"}
### Strength Meter
Combine the `PasswordInput` with password strength logic to show visual feedback about password strength.
:component-preview{component="password-input" name="strength-meter"}
### Validation
Combine with custom validation logic to show real-time feedback. Use the `invalid` prop to indicate validation errors.
:component-preview{component="password-input" name="validation"}
## API
See [Ark UI Password Input docs](https://ark-ui.com/vue/docs/components/password-input){rel=""nofollow""} for full props and examples.
# PhoneField
:component-preview{component="phone-field" name="basic"}
## Features
- **Auto-formatting** — Phone numbers are formatted in real-time as the user types
- **Country selector** — Searchable dropdown with flag display
- **Multiple formats** — International, national, or E.164 output
- **Country filtering** — Preferred, available, and ignored country lists
- **Localization** — Country names displayed in any locale
- **Validation utilities** — Ready-to-use validation functions
- **Composable** — Flexible slot-based architecture
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/phone-field.json
---
::
## Usage
```vue
```
## Composition
```text
PhoneField.Root
├── PhoneField.CountrySelect
├── PhoneField.Input
└── PhoneField.Indicator
```
## Dependencies
This component is built on top of `libphonenumber-js`, for manual installation:
::installation-tabs{:exec='false' command="libphonenumber-js"}
::
## Examples
### With indicator
:component-preview{component="phone-field" name="with-indicator"}
### Sizes
:component-preview{component="phone-field" name="sizes"}
### Formats
The `format` prop controls how the phone number is displayed:
:component-preview{component="phone-field" name="formats"}
> **Note:** The `modelValue` always stores the full E.164 number regardless of display format.
## Country Filtering
Control which countries appear in the selector:
| Prop | Purpose |
| -------------------- | -------------------------------- |
| `preferredCountries` | Shown at the top of the list |
| `availableCountries` | Restrict to only these countries |
| `ignoredCountries` | Hide specific countries |
Countries in `preferredCountries` appear first, followed by remaining `availableCountries`. Any country in `ignoredCountries` is excluded.
## Localization
Country names are formatted using `Intl.DisplayNames`. Set the `locale` prop to display names in any language:
| Locale | Value |
| ------ | ------------------------------------------- |
| `en` | United States, France, Germany |
| `fr` | États-Unis, France, Allemagne |
| `de` | Vereinigte Staaten, Frankreich, Deutschland |
## Validation
### Validation Utilities
Three validation functions are exported for different use cases:
#### `validatePhoneNumber(phone, country?)`
Returns a detailed result object:
```ts
type PhoneValidationResult =
| { success: true }
| { success: false; error: PhoneValidationError }
type PhoneValidationError =
| "TOO_SHORT"
| "TOO_LONG"
| "INVALID_COUNTRY"
| "INVALID_NUMBER"
| "INVALID_FORMAT"
```
#### `isValidPhoneNumber(phone)`
Simple boolean check. Returns `true` if the phone number is valid.
#### `isValidPhoneNumberForCountry(phone, country)`
Boolean check for a specific country. Useful when validating national format numbers.
### Integration with TanStack Form
The validation utilities can be used with `@tanstack/vue-form` by calling them inside a field validator:
```vue {9-14} showLineNumbers
Phone number
```
# Pin Input
:component-preview{component="pin-input" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/pin-input.json
---
::
## Usage
```vue
```
## Composition
```text
PinInput.Root
├── PinInput.Label
├── PinInput.Control
│ └── PinInput.Input
└── PinInput.HiddenInput
```
## Examples
### Placeholder
To customize the default pin input placeholder `○` for each input, pass the placeholder prop and set it to your desired value.
:component-preview{component="pin-input" name="placeholder"}
### Blur on Complete
By default, the last input maintains focus when filled, and we invoke the `onValueComplete` callback. To blur the last input when the user completes the input, set the prop `blurOnComplete` to `true`.
:component-preview{component="pin-input" name="blur-on-complete"}
### OTP Mode
To trigger smartphone OTP auto-suggestion, it is recommended to set the `autocomplete` attribute to "one-time-code". The pin input component provides support for this automatically when you set the `otp` prop to `true`.
:component-preview{component="pin-input" name="otp-mode"}
### Masking
When collecting private or sensitive information using the pin input, you might need to mask the value entered, similar to ``. Pass the `mask` prop to `true`.
:component-preview{component="pin-input" name="mask"}
### Field
The `Field` component helps manage form-related state and accessibility attributes of a pin input. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.
:component-preview{component="pin-input" name="field"}
### Root Provider
An alternative way to control the pin input is to use the `RootProvider` component and the `usePinInput` hook. This way you can access the state and methods from outside the component.
:component-preview{component="pin-input" name="root-provider"}
## API
See [Ark UI Pin Input docs](https://ark-ui.com/vue/docs/components/pin-input){rel=""nofollow""} for full props and examples.
# Popover
:component-preview{component="popover" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/popover.json
---
::
## Usage
```vue
```
## Composition
```text
Popover.Root
├── Popover.Anchor
├── Popover.ArrowTip
├── Popover.Arrow
├── Popover.CloseTrigger
├── Popover.Content
├── Popover.Context
├── Popover.Description
├── Popover.Indicator
├── Popover.RootProvider
├── Popover.Title
├── Popover.Trigger
```
## Examples
### Controlled
Use the `open` and `onOpenChange` props to control the open state of the popover.
:component-preview{component="popover" name="controlled"}
### Root Provider
An alternative way to control the popover is to use the `RootProvider` component and the `usePopover` hook. This way you can access the state and methods from outside the component.
:component-preview{component="popover" name="root-provider"}
### Arrow
Use `Popover.Arrow` and `Popover.ArrowTip` to render an arrow pointing to the trigger.
:component-preview{component="popover" name="arrow"}
### Placement
To change the placement of the popover, set the `positioning` prop.
:component-preview{component="popover" name="placement"}
### Close Behavior
The popover is designed to close on blur and when the esc key is pressed.
- To prevent it from closing on blur (clicking or focusing outside), pass the `closeOnInteractOutside` prop and set it to `false`.
- To prevent it from closing when the esc key is pressed, pass the `closeOnEsc` prop and set it to `false`.
:component-preview{component="popover" name="close-behavior"}
### Modality
In some cases, you might want the popover to be modal. This means that it'll trap focus within its content, block scrolling on the body, disable pointer interactions outside the popover, and hide content behind the popover from screen readers.
:component-preview{component="popover" name="modality"}
### Anchor
Use `Popover.Anchor` to position the popover relative to a different element than the trigger.
:component-preview{component="popover" name="anchor"}
### Same Width
Use `positioning.sameWidth` to make the popover match the width of its trigger element.
:component-preview{component="popover" name="same-width"}
### Dialog Integration
When rendering a popover inside a dialog, use `lazyMount` and `unmountOnExit` on the popover root so it is properly unmounted when the dialog closes.
:component-preview{component="popover" name="dialog-integration"}
### Nested
Popovers can be nested within each other. Each nested popover maintains its own open state and positioning.
:component-preview{component="popover" name="nested"}
### Multiple Triggers
Share a single popover across multiple trigger elements. Pass a `value` to each `Popover.Trigger` — the popover repositions to whichever trigger is activated without closing.
:component-preview{component="popover" name="multiple-triggers"}
## API
See [Ark UI Popover docs](https://ark-ui.com/vue/docs/components/popover){rel=""nofollow""} for full props and examples.
# Progress Circular
:component-preview{component="progress-circular" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/progress-circular.json
---
::
## Usage
```vue
```
## Composition
```text
Progress.Root
├── Progress.Label
├── Progress.CircleContainer
│ ├── Progress.Circle
│ │ ├── Progress.CircleTrack
│ │ └── Progress.CircleRange
│ └── Progress.ValueText
├── Progress.Context
├── Progress.RootProvider
├── Progress.Range
├── Progress.Track
└── Progress.View
```
## Examples
### Min and Max
By default, the maximum is `100`. If that's not what you want, you can easily specify a different bound by changing the value of the `max` prop. You can do the same with the minimum value by setting the `min` prop.
For example, to show the user a progress from `10` to `30`, you can use:
:component-preview{component="progress-circular" name="min-max"}
### Indeterminate
The progress component is determinate by default, with the value and max set to 50 and 100 respectively. To render an indeterminate progress, you will have to set the `value` to `null`.
:component-preview{component="progress-circular" name="indeterminate"}
### Label
Add a label to provide additional context for the progress indicator.
:component-preview{component="progress-circular" name="label"}
### Root Provider
An alternative way to control the progress is to use the `RootProvider` component and the `useProgress` hook. This way you can access the state and methods from outside the component.
:component-preview{component="progress-circular" name="root-provider"}
## API
See [Ark UI Progress - Circular docs](https://ark-ui.com/vue/docs/components/progress-circular){rel=""nofollow""} for full props and examples.
# Progress Linear
:component-preview{component="progress-linear" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/progress-linear.json
---
::
## Usage
```vue
Label
```
## Composition
```text
ProgressLinear.Root
├── ProgressLinear.Label
├── ProgressLinear.ValueText
├── ProgressLinear.Track
│ └── ProgressLinear.Range
└── ProgressLinear.RootProvider
```
## Examples
### Min and Max
By default, the maximum is `100`. If that's not what you want, you can easily specify a different bound by changing the value of the `max` prop. You can do the same with the minimum value by setting the `min` prop.
For example, to show the user a progress from `10` to `30`, you can use:
:component-preview{component="progress-linear" name="min-max"}
### Indeterminate
The progress component is determinate by default, with the value and max set to 50 and 100 respectively. To render an indeterminate progress, you will have to set the `value` to `null`.
:component-preview{component="progress-linear" name="indeterminate"}
### Value Text
Progress bars can only be interpreted by sighted users. To include a text description to support assistive technologies like screen readers, use the `value` part in `translations`.
:component-preview{component="progress-linear" name="value-text"}
### Orientation
By default, the progress is assumed to be horizontal. To change the orientation to vertical, set the orientation property in the machine's context to vertical.
> Don't forget to change the styles of the vertical progress by specifying its height
:component-preview{component="progress-linear" name="vertical"}
### Root Provider
An alternative way to control the progress is to use the `RootProvider` component and the `useProgress` hook. This way you can access the state and methods from outside the component.
:component-preview{component="progress-linear" name="root-provider"}
## API
See [Ark UI Progress - Linear docs](https://ark-ui.com/vue/docs/components/progress-linear){rel=""nofollow""} for full props and examples.
# Qr Code
:component-preview{component="qr-code" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/qr-code.json
---
::
## Usage
```vue
```
## Composition
```text
QrCode.Root
├── QrCode.Frame
│ └── QrCode.Pattern
├── QrCode.Overlay
├── QrCode.DownloadTrigger
├── QrCode.Context
└── QrCode.RootProvider
```
## Examples
### With Overlay
You can also add a logo or overlay to the QR code. This is useful when you want to brand the QR code.
:component-preview{component="qr-code" name="overlay"}
### Error Correction
In cases where the link is too long or the logo overlay covers a significant area, the error correction level can be increased.
Use the `encoding.ecc` or `encoding.boostEcc` property to set the error correction level:
- `L`: Allows recovery of up to 7% data loss (default)
- `M`: Allows recovery of up to 15% data loss
- `Q`: Allows recovery of up to 25% data loss
- `H`: Allows recovery of up to 30% data loss
:component-preview{component="qr-code" name="error-correction"}
### Root Provider
An alternative way to control the QR code is to use the `RootProvider` component and the `useQrCode` hook. This way you can access the state and methods from outside the component.
:component-preview{component="qr-code" name="root-provider"}
### Download
Use the `QrCode.DownloadTrigger` component to allow users to download the QR code as an image. Specify the `fileName` and `mimeType` props for the downloaded file.
:component-preview{component="qr-code" name="download"}
## API
See [Ark UI Qr Code docs](https://ark-ui.com/vue/docs/components/qr-code){rel=""nofollow""} for full props and examples.
# Radio Group
:component-preview{component="radio-group" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/radio-group.json
---
::
## Usage
```vue
```
## Composition
```text
RadioGroup.Root
├── RadioGroup.Label
├── RadioGroup.Indicator
└── RadioGroup.Item
├── RadioGroup.ItemControl
├── RadioGroup.ItemText
└── RadioGroup.ItemHiddenInput
```
## Examples
### Initial Value
To set the radio group's initial value, set the `defaultValue` prop to the value of the radio item to be selected by default.
:component-preview{component="radio-group" name="initial-value"}
### Controlled
For a controlled Radio Group, the state is managed using the `value` prop, and updates when the `onValueChange` event handler is called:
:component-preview{component="radio-group" name="controlled"}
### Root Provider
An alternative way to control the radio group is to use the `RootProvider` component and the `useRadioGroup` hook. This way you can access the state and methods from outside the component.
:component-preview{component="radio-group" name="root-provider"}
### Disabled
To make a radio group disabled, set the `disabled` prop to `true`.
:component-preview{component="radio-group" name="disabled"}
## API
See [Ark UI Radio Group docs](https://ark-ui.com/vue/docs/components/radio-group){rel=""nofollow""} for full props and examples.
# Rating Group
:component-preview{component="rating-group" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/rating-group.json
---
::
## Usage
```vue
```
## Composition
```text
RatingGroup.Root
├── RatingGroup.Label
└── RatingGroup.Control
├── RatingGroup.Context
├── RatingGroup.Item
│ ├── RatingGroup.ItemContext
│ └── RatingGroup.ItemIndicator
└── RatingGroup.HiddenInput
```
## Examples
### Controlled
When using the `RatingGroup` component, you can use the `value` and `onValueChange` props to control the state.
:component-preview{component="rating-group" name="controlled"}
### Root Provider
An alternative way to control the rating group is to use the `RootProvider` component and the `useRatingGroup` hook. This way you can access the state and methods from outside the component.
:component-preview{component="rating-group" name="root-provider"}
### Field
The `Field` component helps manage form-related state and accessibility attributes of a rating group. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.
:component-preview{component="rating-group" name="field"}
### Half Rating
Allow `0.5` value steps by setting the `allowHalf` prop to `true`. Ensure to render the correct icon if the `half` value is set in the Rating components render callback.
:component-preview{component="rating-group" name="half-rating"}
### Forms
To use the rating group within forms, pass the prop `name`. It will render a hidden input and ensure the value changes get propagated to the form correctly.
:component-preview{component="rating-group" name="forms"}
### Disabled
To make the rating group disabled, set the `disabled` prop to `true`.
:component-preview{component="rating-group" name="disabled"}
## API
See [Ark UI Rating Group docs](https://ark-ui.com/vue/docs/components/rating-group){rel=""nofollow""} for full props and examples.
# Scroll Area
:component-preview{component="scroll-area" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/scroll-area.json
---
::
## Usage
```vue
```
## Composition
```text
ScrollArea.Root
├── ScrollArea.Shadow
├── ScrollArea.Viewport
│ └── ScrollArea.Content
├── ScrollArea.Scrollbar
│ └── ScrollArea.Thumb
└── ScrollArea.Corner
```
## Examples
### Horizontal
Configure the scroll area for horizontal scrolling only.
:component-preview{component="scroll-area" name="horizontal"}
### Both Directions
Enable scrolling in both horizontal and vertical directions.
:component-preview{component="scroll-area" name="both-directions"}
### Nested
Scroll areas can be nested within each other for complex layouts.
:component-preview{component="scroll-area" name="nested"}
### Shadow
Add scroll shadows to indicate hidden content. Place `ScrollArea.Shadow` inside `ScrollArea.Root` with a `side` of `top`, `bottom`, `left`, or `right`. The root needs `relative` positioning.
:component-preview{component="scroll-area" name="shadow"}
## API
See [Ark UI Scroll Area docs](https://ark-ui.com/vue/docs/components/scroll-area){rel=""nofollow""} for full props and examples.
# ScrollSpy
:component-preview{component="scroll-spy" name="basic"}
## Features
- **Active tracking** — Scroll position updates `v-model` from a configurable top offset threshold
- **Viewport** — `ScrollSpy.Viewport` is the scroll container that drives tracking
- **Zag machine** — Behavior is owned by a Zag.js state machine (`useScrollSpy`, Provider)
- **Composable** — Provide active state to Toc (or custom UI) through context
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/scroll-spy.json
---
::
## Usage
```vue
Intro
...
Usage
...
```
### Root provider
Drive the machine yourself with `useScrollSpy` and mount parts under `ScrollSpy.Provider`:
```vue
Intro
```
## Composition
```text
ScrollSpy.Root / ScrollSpy.Provider
├── ScrollSpy.Viewport
│ └── ScrollSpy.Item
└── ScrollSpy.Target
```
## API Reference
### ScrollSpy.Root
| Prop | Type | Default |
| ------------- | --------------------------- | ------------ |
| `v-model` | `string` | `""` |
| `offset` | `number` | `0.25` |
| `orientation` | `"vertical" | "horizontal"` | `"vertical"` |
`offset` accepts a ratio (`0`–`1`) of the scroll root size, or an absolute pixel value.
### ScrollSpy.Item
| Prop | Type | Default |
| ------- | -------- | ------- |
| `value` | `string` | — |
### ScrollSpy.Target
| Prop | Type | Default |
| ------- | -------- | ------- |
| `value` | `string` | — |
Registers an existing document element by id (`document.getElementById(value)`). Use this when sections are rendered outside `ScrollSpy.Viewport` — for example a page sidebar TOC watching article headings. Without a viewport, `ScrollSpy.Root` tracks against the window.
## Notes
- Pair with [Toc](https://vuzeno.com/docs/components/toc) for a sidebar rail that follows the active section.
- Prefer `ScrollSpy.Viewport` as the scroll container so tracking binds reliably.
- Use `ScrollSpy.Target` when you cannot wrap the scrolled content in `ScrollSpy.Item`.
- Export `useScrollSpy`, `machine`, `connect`, and `anatomy` for headless composition.
# Segment Group
:component-preview{component="segment-group" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/segment-group.json
---
::
## Usage
```vue
{{ framework }}
```
## Composition
```text
SegmentGroup.Root
├── SegmentGroup.Indicator
└── SegmentGroup.Item
└── SegmentGroup.ItemText
```
## Examples
### Controlled
To create a controlled SegmentGroup component, manage the current selected segment using the `value` prop and update it when the `onValueChange` event handler is called:
:component-preview{component="segment-group" name="controlled"}
### Root Provider
An alternative way to control the segment group is to use the `RootProvider` component and the `useSegmentGroup` hook. This way you can access the state and methods from outside the component.
:component-preview{component="segment-group" name="root-provider"}
### Disabled
To disable a segment, simply pass the `disabled` prop to the `SegmentGroup.Item` component:
:component-preview{component="segment-group" name="disabled"}
## API
See [Ark UI Segment Group docs](https://ark-ui.com/vue/docs/components/segment-group){rel=""nofollow""} for full props and examples.
# Select
:component-preview{component="select" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/select.json
---
::
## Usage
```vue
LabelOption 1Option 2Option 3
```
## Composition
```text
Select.Root
├── Select.Label
├── Select.Trigger
│ └── Select.Value
├── Select.Indicators
│ ├── Select.ClearTrigger
│ └── Select.Indicator
├── Select.Content
│ └── Select.ItemGroup
│ ├── Select.ItemGroupLabel
│ └── Select.Item
│ ├── Select.ItemText
│ └── Select.ItemIndicator
├── Select.Context
└── Select.RootProvider
```
## Examples
### Controlled
Use the `value` and `onValueChange` props to control the selected items.
:component-preview{component="select" name="controlled"}
### Root Provider
An alternative way to control the select is to use the `RootProvider` component and the `useSelect` hook. This way you can access the state and methods from outside the component.
:component-preview{component="select" name="root-provider"}
### Multiple
To enable `multiple` item selection:
:component-preview{component="select" name="multiple"}
### Grouping
Grouping related options can be useful for organizing options into categories.
- Use the `groupBy` prop to configure the grouping of the items.
- Use the `collection.group()` method to get the grouped items.
- Use the `Select.ItemGroup` and `Select.ItemGroupLabel` components to render the grouped items.
:component-preview{component="select" name="grouping"}
### Field
Use `Field` to manage form state, ARIA labels, helper text, and error text.
:component-preview{component="select" name="field"}
### Form Usage
Here's an example of integrating the `Select` component with a form.
:component-preview{component="select" name="form-usage"}
### Async Loading
Here's an example of how to load the items asynchronously when the select is opened.
:component-preview{component="select" name="async-loading"}
### Lazy Mount
Use `lazyMount` and `unmountOnExit` to control when content is mounted, improving performance.
:component-preview{component="select" name="lazy-mount"}
### Select on Highlight
Here's an example of automatically selecting items when they are highlighted (hovered or navigated to with keyboard).
:component-preview{component="select" name="select-on-highlight"}
### Max Selection
Here's an example of limiting the number of items that can be selected in a multiple select.
:component-preview{component="select" name="max-selection"}
### Select All
Use `selectAll()` from the select context to select all items at once.
:component-preview{component="select" name="select-all"}
### Overflow
For selects with many items, use `positioning.fitViewport` to ensure the dropdown fits within the viewport. Combine with a max-height on the content to enable scrolling.
:component-preview{component="select" name="overflow"}
## API
See [Ark UI Select docs](https://ark-ui.com/vue/docs/components/select){rel=""nofollow""} for full props and examples.
# Separator
:component-preview{component="separator" name="basic"}
## Features
- **Horizontal or vertical** — Use the `orientation` prop to switch layout direction
- **Styled default** — A subtle `bg-border` line that adapts to orientation
- **Customizable** — Override with the `class` prop
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/separator.json
---
::
## Usage
```vue
```
## Examples
### Vertical
Use `orientation="vertical"` for a vertical separator.
:component-preview{component="separator" name="vertical"}
### Menu
Vertical separators between menu items with descriptions.
:component-preview{component="separator" name="menu"}
### List
Horizontal separators between list items.
:component-preview{component="separator" name="list"}
## API
### Separator
| Prop | Type | Default | Description |
| ------------- | --------------------------- | -------------- | --------------------------------- |
| `orientation` | `"horizontal" | "vertical"` | `"horizontal"` | Layout direction of the separator |
| `class` | `string` | — | Additional CSS classes |
# Sidebar
:component-preview{component="sidebar" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/sidebar.json
---
::
## Overview
The Sidebar is a composite layout component built on Ark UI primitives. It supports classic and inset variants, icon collapse with hover flyout submenus, responsive mobile drawer, multiple independent sidebars, and nested usage inside dialogs.
## Composition
```text
Sidebar.Provider
├── Sidebar.Root
│ ├── Sidebar.Header
│ ├── Sidebar.Content
│ │ └── Sidebar.Group
│ │ ├── Sidebar.GroupLabel
│ │ └── Sidebar.GroupContent
│ │ └── Sidebar.Menu
│ │ ├── Sidebar.MenuItem
│ │ │ └── Sidebar.MenuButton
│ │ └── Sidebar.MenuSub
│ │ ├── Sidebar.MenuSubTrigger
│ │ └── Sidebar.MenuSubContent
│ ├── Sidebar.Footer
│ └── Sidebar.Rail
└── Sidebar.Inset
└── Sidebar.Trigger
```
## Theming
Sidebar colors use the design system CSS variables:
- `--sidebar`, `--sidebar-foreground`
- `--sidebar-primary`, `--sidebar-primary-foreground`
- `--sidebar-accent`, `--sidebar-accent-foreground`
- `--sidebar-border`, `--sidebar-ring`
Layout variables are set per sidebar instance:
- `--sidebar-width` (default `16rem`)
- `--sidebar-width-icon` (default `3rem`)
- `--sidebar-width-mobile` (default `18rem` on mobile drawer)
Use Tailwind utilities such as `bg-sidebar`, `text-sidebar-foreground`, and `border-sidebar-border`.
By default, `Sidebar.Provider` is container-relative (`h-full min-h-0`) and fits inside bounded layouts such as demo cards or dialogs. Pass `full-height` for page-level layouts that should fill the viewport (`min-h-svh`).
## useSidebar
`useSidebar(id?)` returns a `ComputedRef`. Access the resolved sidebar with `.value`, or pass an `id` when multiple sidebars are registered.
| Property | Type | Description |
| --------------- | ---------------------------------- | ------------------------------ |
| `state` | `"expanded" | "collapsed"` | Derived open state for styling |
| `open` | `Ref` | Desktop expanded state |
| `setOpen` | `(boolean) => void` | Set desktop open state |
| `openMobile` | `Ref` | Mobile drawer open state |
| `setOpenMobile` | `(boolean) => void` | Set mobile drawer state |
| `isMobile` | `Ref` | Whether viewport is mobile |
| `toggleSidebar` | `() => void` | Toggle desktop or mobile state |
| `id` | `string` | Sidebar instance id |
| `side` | `"left" | "right"` | Sidebar side |
| `variant` | `"sidebar" | "floating" | "inset"` | Visual variant |
| `collapsible` | `"offcanvas" | "icon" | "none"` | Collapse behavior |
Pass an `id` to `useSidebar("left")` when multiple sidebars are registered.
```ts
const sidebar = useSidebar();
sidebar.value?.toggleSidebar();
```
## Examples
### Inset variant
Visual variant where the main content is wrapped in a padded, rounded container.
:component-preview{component="sidebar" name="inset"}
### Icon collapse with hover flyout
When collapsed to icon mode, submenus with children open a hover flyout menu instead of hiding nested items.
:component-preview{component="sidebar" name="icon"}
### Multiple sidebars
Register left and right sidebars with independent state using the `id` prop and `Sidebar.Trigger target`.
:component-preview{component="sidebar" name="multiple"}
### Nested in a dialog
`Sidebar.Provider` is container-relative by default and fits inside dialogs or other bounded layouts. Pass `full-height` for page-level layouts.
:component-preview{component="sidebar" name="dialog"}
### Controlled
Control sidebar open state with `v-model:open` on `Sidebar.Root`.
:component-preview{component="sidebar" name="controlled"}
# Signature Pad
:component-preview{component="signature-pad" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/signature-pad.json
---
::
## Usage
```vue
```
## Composition
```text
SignaturePad.Root
├── SignaturePad.ClearTrigger
├── SignaturePad.Context
├── SignaturePad.Control
├── SignaturePad.Guide
├── SignaturePad.HiddenInput
├── SignaturePad.Label
├── SignaturePad.RootProvider
├── SignaturePad.Segment
```
## Examples
### Image Preview
After the user draws a signature, you can display a preview of the signature as an image. This is useful when you want to show the user a preview of the signature before saving it.
:component-preview{component="signature-pad" name="image-preview"}
### Field
The `Field` component helps manage form-related state and accessibility attributes of a signature pad. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.
:component-preview{component="signature-pad" name="field"}
### Root Provider
An alternative way to control the signature pad is to use the `RootProvider` component and the `useSignaturePad` hook. This way you can access the state and methods from outside the component.
:component-preview{component="signature-pad" name="root-provider"}
## API
See [Ark UI Signature Pad docs](https://ark-ui.com/vue/docs/components/signature-pad){rel=""nofollow""} for full props and examples.
# Skeleton
:component-preview{component="skeleton" name="basic"}
## Features
- **Shimmer** — Light sweep from left to right while content loads
- **Shape with classes** — Size and shape via Tailwind utilities (`rounded-full`, fixed width/height)
- **Customizable** — Override styles with the `class` prop
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/skeleton.json
---
::
## Usage
```vue
```
## Examples
### Card
Compose multiple skeletons to match a card layout.
:component-preview{component="skeleton" name="card"}
## API
### Skeleton
| Prop | Type | Default | Description |
| ------- | -------- | ------- | ---------------------- |
| `class` | `string` | — | Additional CSS classes |
# Slider
:component-preview{component="slider" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/slider.json
---
::
## Usage
```vue
```
## Composition
```text
Slider.Root
├── Slider.Context
├── Slider.Control
├── Slider.DraggingIndicator
├── Slider.HiddenInput
├── Slider.Label
├── Slider.MarkerGroup
├── Slider.Marker
├── Slider.Range
├── Slider.RootProvider
├── Slider.Thumb
├── Slider.Track
├── Slider.ValueText
```
## Examples
### Range
You can add multiple thumbs to the slider by adding multiple `Slider.Thumb`
:component-preview{component="slider" name="range"}
### Marks
You can add marks to the slider track by using the `Slider.MarkerGroup` and `Slider.Marker` components.
Position the `Slider.Marker` components relative to the track by providing the `value` prop.
:component-preview{component="slider" name="marks"}
### Min and Max
By default, the minimum is `0` and the maximum is `100`. If that's not what you want, you can easily specify different bounds by changing the values of the `min` and/or `max` props.
For example, to ask the user for a value between `-10` and `10`, you can use:
:component-preview{component="slider" name="min-max"}
### Granularity
By default, the granularity, is `1`, meaning that the value is always an integer. You can change the step attribute to control the granularity.
For example, If you need a value between `5` and `10`, accurate to two decimal places, you should set the value of step to `0.01`:
:component-preview{component="slider" name="granularity"}
### Change Events
When the slider value changes, the `onValueChange` and `onValueChangeEnd` callbacks are invoked. You can use this to set up custom behaviors in your app.
:component-preview{component="slider" name="change-events"}
### Orientation
By default, the slider is assumed to be horizontal. To change the orientation to vertical, set the orientation property in the machine's context to vertical.
In this mode, the slider will use the arrow up and down keys to increment/decrement its value.
> Don't forget to change the styles of the vertical slider by specifying its height
:component-preview{component="slider" name="orientation"}
### Origin
By default, the slider's origin is at the start of the track. To change the origin to the center of the track, set the `origin` prop to `center`.
:component-preview{component="slider" name="origin"}
### Root Provider
An alternative way to control the slider is to use the `RootProvider` component and the `useSlider` hook. This way you can access the state and methods from outside the component.
:component-preview{component="slider" name="root-provider"}
### Dragging Indicator
Use the `Slider.DraggingIndicator` component inside `Slider.Thumb` to show a visual indicator while the thumb is being dragged.
:component-preview{component="slider" name="dragging-indicator"}
### Thumb Overlap
Use the `minStepsBetweenThumbs` prop to prevent range slider thumbs from overlapping. This ensures a minimum gap between thumbs, which is useful for price range filters and similar use cases.
:component-preview{component="slider" name="thumb-overlap"}
### Thumb Collision
Use the `thumbCollisionBehavior` prop to control how thumbs behave when they collide during pointer interactions. Supported values are `push` (default), `swap`, and `none`.
:component-preview{component="slider" name="thumb-collision"}
## API
See [Ark UI Slider docs](https://ark-ui.com/vue/docs/components/slider){rel=""nofollow""} for full props and examples.
# Splitter
:component-preview{component="splitter" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/splitter.json
---
::
## Usage
```vue
```
## Composition
```text
Splitter.Root
├── Splitter.Context
├── Splitter.Panel
├── Splitter.ResizeTrigger
├── Splitter.ResizeTriggerIndicator
├── Splitter.RootProvider
```
## Examples
### Context
Access the splitter's API with `Splitter.Context` or the `useSplitterContext` hook. This lets you resize panels programmatically:
:component-preview{component="splitter" name="context"}
### Vertical
By default, the Splitter component is horizontal. If you need a vertical splitter, use the `orientation` prop:
:component-preview{component="splitter" name="vertical"}
### Collapsible Panels
To make a panel collapsible, set the `collapsible` prop to `true` on the panel you want to make collapsible. Additionally, you can use the `collapsedSize` prop to set the size of the panel when it's collapsed.
> This can be useful for building sidebar layouts.
:component-preview{component="splitter" name="collapsible"}
### Multiple Panels
Here's an example of how to use the `Splitter` component with multiple panels.
:component-preview{component="splitter" name="multiple-panels"}
### Root Provider
An alternative way to control the splitter is to use the `RootProvider` component and the `useSplitter` hook. This way you can access the state and methods from outside the component.
:component-preview{component="splitter" name="root-provider"}
### Resize Indicator
Use the `Splitter.ResizeTriggerIndicator` component to show a visual indicator on the resize handle.
:component-preview{component="splitter" name="resize-indicator"}
### Dynamic Collapsible
Use the `collapsePanel()` and `expandPanel()` methods to programmatically control panel collapse based on viewport size. This is useful for responsive sidebar layouts that collapse on smaller screens.
:component-preview{component="splitter" name="dynamic-collapsible"}
### Nested
Nest splitters to build grid-like layouts. Use `createSplitterRegistry()` to create a shared registry between splitter instances — this enables multi-drag at intersection points where horizontal and vertical splitters meet.
:component-preview{component="splitter" name="nested"}
## API
See [Ark UI Splitter docs](https://ark-ui.com/vue/docs/components/splitter){rel=""nofollow""} for full props and examples.
# Steps
:component-preview{component="steps" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/steps.json
---
::
## Usage
```vue
```
## Composition
```text
Steps.Root
├── Steps.CompletedContent
├── Steps.Content
├── Steps.Context
├── Steps.Indicator
├── Steps.ItemContext
├── Steps.Item
├── Steps.List
├── Steps.NextTrigger
├── Steps.PrevTrigger
├── Steps.Progress
├── Steps.RootProvider
├── Steps.Separator
├── Steps.Trigger
```
## Examples
### Controlled
Using the `RootProvider` component, you can control the active step by using the `step` prop and handling the `onStepChange` event.
:component-preview{component="steps" name="controlled"}
### Root Provider
An alternative way to control the steps is to use the `RootProvider` component and the `useSteps` hook. This way you can access the state and methods from outside the component.
:component-preview{component="steps" name="root-provider"}
### Vertical
Use the `orientation` prop to display the steps vertically.
:component-preview{component="steps" name="vertical"}
### Circular Progress
Show a circular progress indicator with the current step count (`X/X`), plus the title and description of the active step.
:component-preview{component="steps" name="circular-progress"}
### Linear Progress
Place a linear progress bar above the steps, synced to the completion percentage. The step list below omits separators.
:component-preview{component="steps" name="linear-progress"}
## API
See [Ark UI Steps docs](https://ark-ui.com/vue/docs/components/steps){rel=""nofollow""} for full props and examples.
# Switch
:component-preview{component="switch" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/switch.json
---
::
## Usage
```vue
```
## Composition
```text
Switch.Root
├── Switch.Context
├── Switch.Control
├── Switch.HiddenInput
├── Switch.Label
├── Switch.RootProvider
├── Switch.Thumb
```
## Examples
### Sizes
Use the `size` prop on `Switch.Root` to change the size of the switch.
:component-preview{component="switch" name="sizes"}
### Controlled
For a controlled Switch component, the state of the toggle is managed using the checked prop, and updates when the `onCheckedChange` event handler is called:
:component-preview{component="switch" name="controlled"}
### Root Provider
An alternative way to control the switch is to use the `RootProvider` component and the `useSwitch` hook. This way you can access the state and methods from outside the component.
:component-preview{component="switch" name="root-provider"}
### Field
The `Field` component helps manage form-related state and accessibility attributes of a switch. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.
:component-preview{component="switch" name="field"}
### Context
Access the switch's state with `Switch.Context` or the `useSwitchContext` hook. This lets you customize the component based on its current state:
:component-preview{component="switch" name="context"}
## API
See [Ark UI Switch docs](https://ark-ui.com/vue/docs/components/switch){rel=""nofollow""} for full props and examples.
# Table
:component-preview{component="table" name="basic"}
## Features
- **Composable** — Flexible slot-based layout with `Table.Header`, `Table.Body`, `Table.Footer`, `Table.Row`, `Table.Head`, and `Table.Cell`
- **Scrollable** — Root wraps the table in an overflow container for wide datasets
- **Empty state** — Built-in `Table.Empty` for zero-result views
- **Customizable** — Override any part with the `class` prop
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/table.json
---
::
## Composition
```text
Table.Root
├── Table.Caption
├── Table.Header
│ └── Table.Row
│ └── Table.Head
├── Table.Body
│ └── Table.Row
│ └── Table.Cell
└── Table.Footer
└── Table.Row
└── Table.Cell
```
## Usage
```vue
A list of your recent invoices.InvoiceStatusAmountINV001Paid$250.00
```
## Examples
### Empty state
Use `Table.Empty` when there are no rows to display.
:component-preview{component="table" name="empty"}
### With filters
Compose [Filters](https://vuzeno.com/docs/components/filters) above the table to narrow rows client-side. Use `Table.Empty` when nothing matches.
:component-preview{component="table" name="with-filters"}
# Tabs
:component-preview{component="tabs" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/tabs.json
---
::
## Usage
```vue
```
## Composition
```text
Tabs.Root
├── Tabs.TabList
│ ├── Tabs.TabTrigger
│ ├── Tabs.TabTriggerIndicator
│ └── Tabs.TabIndicator
├── Tabs.TabContent
├── Tabs.Context
└── Tabs.RootProvider
```
## Examples
### Controlled
To create a controlled Tabs component, manage the current selected tab using the `value` prop and update it when the `onValueChange` event handler is called.
:component-preview{component="tabs" name="controlled"}
### Root Provider
An alternative way to control the tabs is to use the `RootProvider` component and the `useTabs` hook. This way you can access the state and methods from outside the component.
:component-preview{component="tabs" name="root-provider"}
### Indicator
To provide a visual cue for the selected tab, use the `Tabs.TabIndicator` component with `Tabs.TabTriggerIndicator` triggers.
:component-preview{component="tabs" name="indicator"}
### Disabled
To disable a tab, pass the `disabled` prop to the `Tabs.TabTrigger` component.
:component-preview{component="tabs" name="disabled"}
### Vertical
The default orientation of the tabs is `horizontal`. To change the orientation, set the `orientation` prop to `vertical`.
:component-preview{component="tabs" name="vertical"}
### Lazy Mount
Lazy mounting renders tab content only when the tab is first activated. Use `lazy-mount` and `unmount-on-exit` on `Tabs.Root` to free resources when a tab is deactivated.
:component-preview{component="tabs" name="lazy-mount"}
### Manual Activation
By default, the tab can be selected when it receives focus from either the keyboard or pointer interaction. With `activation-mode="manual"`, the tab is selected with the Enter key or by clicking on the tab.
:component-preview{component="tabs" name="manual-activation"}
### Links
Use the `as-child` prop to render tab triggers as anchor links. This is useful for SEO and allows tabs to work with browser navigation.
:component-preview{component="tabs" name="links"}
## API
See [Ark UI Tabs docs](https://ark-ui.com/vue/docs/components/tabs){rel=""nofollow""} for full props and examples.
# Tags Input
:component-preview{component="tags-input" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/tags-input.json
---
::
## Usage
```vue
```
## Composition
```text
TagsInput.Root
├── TagsInput.ClearTrigger
├── TagsInput.Context
├── TagsInput.Control
├── TagsInput.HiddenInput
├── TagsInput.Input
├── TagsInput.ItemContext
├── TagsInput.ItemDeleteTrigger
├── TagsInput.ItemInput
├── TagsInput.ItemPreview
├── TagsInput.ItemText
├── TagsInput.Item
├── TagsInput.Label
├── TagsInput.RootProvider
```
## Examples
### Controlled
Use the `value` and `onValueChange` props to programmatically control the tags input's state. This allows you to manage the tags array externally and respond to changes.
:component-preview{component="tags-input" name="controlled"}
### Controlled Input Value
Use the `inputValue` and `onInputValueChange` props to control the text input field independently. This is useful for clearing the input or pre-filling it programmatically.
:component-preview{component="tags-input" name="controlled-input-value"}
### Root Provider
An alternative way to control the tags input is to use the `RootProvider` component and the `useTagsInput` hook. This way you can access the state and methods from outside the component.
:component-preview{component="tags-input" name="root-provider"}
### Field
The `Field` component helps manage form-related state and accessibility attributes of a tags input. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.
:component-preview{component="tags-input" name="field"}
### Max Tags
To limit the number of tags within the component, you can set the `max` property to the limit you want. The default value is `Infinity`.
:component-preview{component="tags-input" name="max-tags"}
### Custom Delimiter
Use the `delimiter` prop with a regex pattern to specify multiple characters that can separate tags. By default, only the Enter key creates tags.
:component-preview{component="tags-input" name="custom-delimiter"}
### Disabled
Use the `disabled` prop to make the tags input non-interactive. Users won't be able to add, remove, or edit tags.
:component-preview{component="tags-input" name="disabled"}
### Invalid
Use the `invalid` prop to mark the tags input as invalid for form validation purposes.
:component-preview{component="tags-input" name="invalid"}
### Max Length
Use the `maxLength` prop to limit the number of characters allowed per tag. This prevents users from creating overly long tags.
:component-preview{component="tags-input" name="max-length"}
### Read-only
Use the `readOnly` prop to make tags visible but not editable. Users can view tags but cannot add, remove, or modify them.
:component-preview{component="tags-input" name="read-only"}
### Validation
Before a tag is added, the `validate` function is called to determine whether to accept or reject a tag.
:component-preview{component="tags-input" name="validation"}
### Blur behavior
When the tags input is blurred, you can configure the action the component should take by passing the `blurBehavior` prop.
- `add` — Adds the tag to the list of tags.
- `clear` — Clears the tags input value.
:component-preview{component="tags-input" name="blur-behavior"}
### Paste behavior
To add a tag when a arbitrary value is pasted in the input element, pass the `addOnPaste` prop.
When a value is pasted, the component will:
- check if the value is a valid tag based on the `validate` option
- split the value by the `delimiter` option passed
:component-preview{component="tags-input" name="paste-behavior"}
### Disable Editing
by default the tags can be edited by double-clicking on the tag or focusing on them and pressing Enter. To disable this behavior, pass `editable={false}`
:component-preview{component="tags-input" name="disable-editing"}
### Programmatic Control
Use the `useTagsInput` hook with `RootProvider` to access the component's API methods like `addValue()`, `setValue()`, and `clearValue()` for full programmatic control.
:component-preview{component="tags-input" name="programmatic-control"}
### Sanitize Value
Use the `sanitizeValue` prop to normalize tag values before they're added. This runs on every new tag — useful for trimming whitespace, converting to lowercase, or any other formatting you need.
:component-preview{component="tags-input" name="sanitize-value"}
### Autocomplete
Combine TagsInput with Autocomplete to create an autocomplete tags input. This pattern uses shared IDs between both components and the `asChild` prop to compose the inputs together.
:component-preview{component="tags-input" name="autocomplete"}
## API
See [Ark UI Tags Input docs](https://ark-ui.com/vue/docs/components/tags-input){rel=""nofollow""} for full props and examples.
# Textarea
:component-preview{component="textarea" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/textarea.json
---
::
## Usage
```vue
```
## Examples
### Field
Use `Field` to add a label, helper text, and validation context around the textarea.
:component-preview{component="textarea" name="field"}
### Disabled
Use the `disabled` prop to disable the textarea. Wrap it in `Field.Root` with `disabled` to style the disabled state.
:component-preview{component="textarea" name="disabled"}
### Invalid
Use the `aria-invalid` prop to mark the textarea as invalid. Set `invalid` on `Field.Root` to style the invalid state.
:component-preview{component="textarea" name="invalid"}
Combine with [`Field`](https://vuzeno.com/docs/components/field) for labels, helper text, and validation. Use [`InputGroup`](https://vuzeno.com/docs/components/input-group) to add addons, text, or buttons around a textarea.
# Timeline
:component-preview{component="timeline" name="basic"}
## Features
- **Two directions** — Stack items top-to-bottom (`vertical`) or left-to-right (`horizontal`)
- **Side control** — Place content on either side of the thread (`left`/`right` for vertical, `top`/`bottom` for horizontal)
- **Centered thread** — Opt-in alternating layout with `align="center"` for zigzag timelines
- **Dot or icon markers** — Switch between a small dot or an icon slot via `Timeline.Media`'s `variant` prop
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/timeline.json
---
::
## Usage
```vue
TitleDescription
```
## Composition
```text
Timeline.Root
└── Timeline.Item
├── Timeline.Media
└── Timeline.Content
└── Timeline.Header
├── Timeline.Title
└── Timeline.Description
```
## Anatomy
```vue
```
## Examples
### Horizontal
Switch the orientation with `direction="horizontal"`. The thread runs left-to-right and content stacks above or below each marker.
:component-preview{component="timeline" name="horizontal"}
```vue showLineNumbers
DraftIdea captured
```
### Alternating sides
Use `align="center"` on `Timeline.Root` to center the thread, then set each `Timeline.Item`'s `side` to `left` or `right` (or `top`/`bottom` for horizontal) to build an alternating layout.
:component-preview{component="timeline" name="side"}
```vue showLineNumbers
Project kickoffMonday · 9:00 AMDesign reviewTuesday · 2:30 PM
```
## API Reference
### Timeline.Root
| Prop | Type | Default |
| ----------- | ------------------------------------- | ------------ |
| `direction` | `"vertical" | "horizontal"` | `"vertical"` |
| `side` | `"left" | "right" | "top" | "bottom"` | - |
| `align` | `"start" | "center"` | `"start"` |
### Timeline.Item
| Prop | Type | Default |
| ------ | ------------------------------------- | ------- |
| `side` | `"left" | "right" | "top" | "bottom"` | inherit |
### Timeline.Media
| Prop | Type | Default |
| --------- | ---------------- | ------- |
| `variant` | `"dot" | "icon"` | `"dot"` |
## Notes
- `align="start"` (the default) produces a thread on one side of each item. Mixing per-item `side` values in `start` mode will shift the thread between items — use `align="center"` for alternating layouts.
- The connector line is hidden on the last item via a `last:` variant, so a single-item timeline shows only the marker.
# Timer
:component-preview{component="timer" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/timer.json
---
::
## Usage
```vue
```
## Composition
```text
Timer.Root
├── Timer.Area
│ ├── Timer.ItemGroup
│ │ ├── Timer.Item
│ │ └── Timer.ItemLabel
│ └── Timer.Separator
├── Timer.Control
│ └── Timer.ActionTrigger
├── Timer.Context
└── Timer.RootProvider
```
## Examples
### Countdown
You can create a countdown timer by setting the `countdown` prop to `true` and `startMs` to the initial time:
:component-preview{component="timer" name="countdown"}
### Interval
Use the `interval` prop to control how frequently the timer updates. This is useful for displaying milliseconds:
:component-preview{component="timer" name="interval"}
### Events
The Timer component provides events that you can listen to for various timer-related actions.
- The `onComplete` event is triggered when the timer reaches its target time.
- The `onTick` event is called on each timer update, providing details about the current timer state.
:component-preview{component="timer" name="events"}
### Pomodoro
Here's an example of building a pomodoro timer that alternates between work and break sessions:
:component-preview{component="timer" name="pomodoro"}
### Root Provider
An alternative way to control the timer is to use the `RootProvider` component and the `useTimer` hook. This way you can access the state and methods from outside the component.
:component-preview{component="timer" name="root-provider"}
## API
See [Ark UI Timer docs](https://ark-ui.com/vue/docs/components/timer){rel=""nofollow""} for full props and examples.
# Toast
:component-preview{component="toast" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/toast.json
---
::
## Usage
```vue
{{ toast.title }}{{ toast.description }}
```
## Composition
```text
Toast.Toaster
└── Toast.Root
├── Toast.Indicator
├── Toast.Title
├── Toast.Description
├── Toast.ActionTrigger
└── Toast.CloseTrigger
```
## Examples
### Types
You can create different types of toasts (`success`, `error`, `warning`, `info`) with appropriate styling. For example, to create a success toast, you can do:
```ts
toaster.success({
title: "Success!",
description: "Your changes have been saved.",
});
```
:component-preview{component="toast" name="types"}
### Promise
You can use `toaster.promise()` to automatically handle the different states of an asynchronous operation. It provides options for the `success`, `error`, and `loading` states of the promise and will automatically update the toast when the promise resolves or rejects.
:component-preview{component="toast" name="promise"}
### Update
To update a toast, use the `toast.update` method.
:component-preview{component="toast" name="update"}
### Action
To add an action to a toast, use the `toast.action` property.
:component-preview{component="toast" name="action"}
### Duration
You can control how long a toast stays visible by setting a custom `duration` in milliseconds, or use `Infinity` to keep it visible until manually dismissed.
:component-preview{component="toast" name="duration"}
### Max Visible
Set the `max` prop on the `createToaster` function to define the maximum number of toasts that can be rendered at any one time. Any extra toasts will be queued and rendered when a toast has been dismissed.
:component-preview{component="toast" name="max-visible"}
### Placement
Configure where toasts appear on the screen using the `placement` option in `createToaster`. Options include `top-start`, `top-end`, `bottom-start`, `bottom-end`, and more.
:component-preview{component="toast" name="placement"}
## API
See [Ark UI Toast docs](https://ark-ui.com/vue/docs/components/toast){rel=""nofollow""} for full props and examples.
# Toc
:component-preview{component="toc" name="basic"}
## Features
- **Active highlight** — Primary mark on the rail for the current item
- **Indicator modes** — Pin the active item (`segment`) or fill the rail as progress (`fill`)
- **Three rail styles** — Continuous (`straight`), 45° circuit (`sharp`), or S-curve circuit (`rounded`)
- **ScrollSpy aware** — Reads active value from a parent ScrollSpy when present
- **Depth indent** — `depth` on items offsets labels and the path rail
- **Zag.js machine** — Headless state via `useToc` / `Toc.Provider`
## Installation
Install from the Vuzeno registry (includes ScrollSpy):
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/toc.json
---
::
## Usage
```vue
Intro
Usage
On this pageIntroUsage
```
## Composition
```text
Toc.Root / Toc.Provider
├── Toc.Title
└── Toc.List
├── Toc.Indicator
└── Toc.Item
└── Toc.Link
```
## Examples
### Straight rail
`turn="straight"` keeps a continuous vertical line. The active item is highlighted as a primary segment on that line.
:component-preview{component="toc" name="turn-straight"}
### Sharp path
`turn="sharp"` draws a circuit that follows nested depth offsets with straight 45° diagonal turns.
:component-preview{component="toc" name="turn-sharp"}
### Indicator modes
`indicator="segment"` (default) pins a short primary mark on the active item. `indicator="fill"` paints the rail from the start up to the active item — useful as reading progress. Toggle both modes and rail styles below.
:component-preview{component="toc" name="indicator-modes"}
## API Reference
### Toc.Root
| Prop | Type | Default |
| ---------------------- | ---------------------------------- | ---------------------------------- |
| `turn` | `"straight" | "sharp" | "rounded"` | `"rounded"` |
| `indicator` | `"segment" | "fill"` | `"segment"` |
| `v-model:active-value` | `string` | `""` (used when outside ScrollSpy) |
### useToc / Toc.Provider
Drive the machine imperatively and provide it to parts:
```vue
On this pageIntro
```
### Toc.Item
| Prop | Type | Default |
| ------- | -------- | ------- |
| `value` | `string` | — |
| `depth` | `number` | `2` |
### Toc.Link
| Prop | Type | Default |
| ------ | -------- | ------- |
| `href` | `string` | — |
## Notes
- Prefer nesting Toc under [ScrollSpy](https://vuzeno.com/docs/components/scroll-spy) so the active section stays in sync automatically.
- Without ScrollSpy, drive the rail with `v-model:active-value` on `Toc.Root`, or use `useToc` + `Toc.Provider`.
- `straight` is a continuous rail; `sharp` and `rounded` follow sub-item indents with 45° diagonals or S-curve turns. The active indicator rides that same path.
- `indicator="fill"` grows from the top of the rail to the active item; `indicator="segment"` only highlights the active item itself.
# Toggle
:component-preview{component="toggle" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/toggle.json
---
::
## Usage
```vue
```
## Composition
```text
Toggle.Root
├── Toggle.Indicator
├── Toggle.Context
```
## Examples
### Variants
Use the `variant` prop to change the visual style of the toggle.
:component-preview{component="toggle" name="variants"}
### Sizes
Use the `size` prop to change the size of the toggle.
:component-preview{component="toggle" name="sizes"}
### Controlled
Use the `pressed` and `onPressedChange` props to control the toggle's state.
:component-preview{component="toggle" name="controlled"}
### Disabled
Use the `disabled` prop to disable the toggle.
:component-preview{component="toggle" name="disabled"}
### Indicator
Use the `Toggle.Indicator` component to render different indicators based on the state of the toggle.
:component-preview{component="toggle" name="indicator"}
## API
See [Ark UI Toggle docs](https://ark-ui.com/vue/docs/components/toggle){rel=""nofollow""} for full props and examples.
# Toggle Group
:component-preview{component="toggle-group" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/toggle-group.json
---
::
## Composition
```text
ToggleGroup.Root
├── ToggleGroup.Context
├── ToggleGroup.Item
└── ToggleGroup.RootProvider
```
## Usage
```vue
```
## Examples
### Variants
Use the `variant` prop on `ToggleGroup.Root` to change the visual style of the group. Items inherit the variant from the root.
:component-preview{component="toggle-group" name="variants"}
### Sizes
Use the `size` prop on `ToggleGroup.Root` to change the size of the group and its items.
:component-preview{component="toggle-group" name="sizes"}
### Controlled
Use the `value` and `onValueChange` props to control the toggle group state.
:component-preview{component="toggle-group" name="controlled"}
### Root Provider
An alternative way to control the toggle group is to use the `RootProvider` component and the `useToggleGroup` hook. This way you can access the state and methods from outside the component.
:component-preview{component="toggle-group" name="root-provider"}
### Multiple
Demonstrates how to enable `multiple` selection within the group.
:component-preview{component="toggle-group" name="multiple"}
## API
See [Ark UI Toggle Group docs](https://ark-ui.com/vue/docs/components/toggle-group){rel=""nofollow""} for full props and examples.
# Tooltip
:component-preview{component="tooltip" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/tooltip.json
---
::
## Usage
```vue
Hover MeI am a tooltip!
```
## Composition
```text
Tooltip.Root
├── Tooltip.Trigger
└── Tooltip.Positioner
├── Tooltip.Arrow
│ └── Tooltip.ArrowTip
└── Tooltip.Content
```
## Examples
### Controlled
To create a controlled Tooltip component, manage the state of whether the tooltip is open using the `open` prop:
:component-preview{component="tooltip" name="controlled"}
### Root Provider
An alternative way to control the tooltip is to use the `RootProvider` component and the `useTooltip` hook. This way you can access the state and methods from outside the component.
:component-preview{component="tooltip" name="root-provider"}
### Arrow
To display an arrow pointing to the trigger from the tooltip, use the `Tooltip.Arrow` and `Tooltip.ArrowTip` components:
:component-preview{component="tooltip" name="arrow"}
### Delay
To configure the open and close delay for the Tooltip, use the `closeDelay` and `openDelay` props:
:component-preview{component="tooltip" name="delay"}
### Positioning
To customize the position of the Tooltip relative to the trigger, use the `positioning` prop:
:component-preview{component="tooltip" name="positioning"}
### Context
Access the tooltip's state and methods with `Tooltip.Context` or the `useTooltipContext` hook:
:component-preview{component="tooltip" name="context"}
### Within Fixed Containers
When rendering a tooltip inside a fixed-position container, set `positioning.strategy` to `"fixed"` to ensure proper positioning.
:component-preview{component="tooltip" name="within-fixed"}
### Multiple Triggers
Share a single tooltip across multiple trigger elements. Pass a `value` to each `Tooltip.Trigger` — the tooltip repositions to whichever trigger is hovered without closing.
:component-preview{component="tooltip" name="multiple-triggers"}
## API
See [Ark UI Tooltip docs](https://ark-ui.com/vue/docs/components/tooltip){rel=""nofollow""} for full props and examples.
# Tour
:component-preview{component="tour" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/tour.json
---
::
## Usage
```vue
```
## Composition
```text
Tour.Root
├── Tour.ActionTrigger
├── Tour.Actions
├── Tour.ArrowTip
├── Tour.Arrow
├── Tour.Backdrop
├── Tour.CloseTrigger
├── Tour.Content
├── Tour.Context
├── Tour.Control
├── Tour.Description
├── Tour.Positioner
├── Tour.ProgressText
├── Tour.Spotlight
├── Tour.Title
```
## Examples
### Step Types
Demonstrate all three step types in a single tour: `dialog` for welcome/completion, `tooltip` anchored to elements, and `floating` for fixed-position content.
:component-preview{component="tour" name="step-types"}
### Progress
Display a visual progress indicator at the bottom of the tour content showing how far along the user is.
:component-preview{component="tour" name="progress"}
### Skip
Allow users to skip the entire tour at any step by adding a skip action.
:component-preview{component="tour" name="skip"}
### Keyboard Navigation
Enable arrow key navigation between tour steps using the `keyboardNavigation` prop.
:component-preview{component="tour" name="keyboard-navigation"}
### Events
Listen to tour lifecycle events like `onStepChange` and `onStatusChange` to track user progress.
:component-preview{component="tour" name="events"}
### Wait for Click
Use the `effect` function with `waitForEvent` to wait for user interaction before proceeding to the next step.
:component-preview{component="tour" name="wait-for-click"}
### Wait for Input
Create form tutorials that wait for users to enter valid input before advancing.
:component-preview{component="tour" name="wait-for-input"}
### Wait for Element
Wait for dynamically rendered elements to appear in the DOM before showing a step.
:component-preview{component="tour" name="wait-for-element"}
### Async
Load data asynchronously and update step content before displaying it using the `effect` function with `show()` and `update()`.
:component-preview{component="tour" name="async"}
## API
See [Ark UI Tour docs](https://ark-ui.com/vue/docs/components/tour){rel=""nofollow""} for full props and examples.
# Tree View
:component-preview{component="tree-view" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/tree-view.json
---
::
## Usage
```vue
```
## Examples
### Controlled Expanded
Pass the `expandedValue` and `onExpandedChange` props to the `TreeView.Root` component to control the expanded state of the tree view.
:component-preview{component="tree-view" name="controlled-expanded"}
### Controlled Selection
Pass the `selectedValue` and `onSelectionChange` props to the `TreeView.Root` component to control the selected state of the tree view.
:component-preview{component="tree-view" name="controlled-selection"}
### Root Provider
An alternative way to control the tree view is to use the `RootProvider` component and the `useTreeView` hook. This way you can access the state and methods from outside the component.
:component-preview{component="tree-view" name="root-provider"}
### Lazy Loading
Lazy loading is a feature that allows the tree view to load children of a node on demand (or async). This helps to improve the initial load time and memory usage.
To use this, you need to provide the following:
- `loadChildren` — A function that is used to load the children of a node.
- `onLoadChildrenComplete` — A callback that is called when the children of a node are loaded. Used to update the tree collection.
- `childrenCount` — A number that indicates the number of children of a branch node.
:component-preview{component="tree-view" name="lazy-loading"}
### Lazy Mount
Lazy mounting is a feature that allows the content of a tree view to be rendered only when it is expanded. This is useful for performance optimization, especially when tree content is large or complex. To enable lazy mounting, use the `lazyMount` prop on the `TreeView.Root` component.
In addition, the `unmountOnExit` prop can be used in conjunction with `lazyMount` to unmount the tree view content when branches are collapsed, freeing up resources. The next time a branch is expanded, its content will be re-rendered.
:component-preview{component="tree-view" name="lazy-mount"}
### Filtering
Filtering is useful when you have a large tree and you want to filter the nodes to only show the ones that match the search query. Here's an example that composes the `filter` method from the `TreeCollection` and `useFilter` hook to filter the nodes.
:component-preview{component="tree-view" name="filtering"}
### Links
Tree items can be rendered as links to another page or website. This could be useful for documentation sites.
Here's an example that modifies the tree collection to represent an hierarchical link structure. It uses the `asChild` prop to render the tree items as links, passing the `href` prop to a `` element.
:component-preview{component="tree-view" name="links"}
### Virtualized
For large tree views with thousands of nodes, virtualization can significantly improve performance by only rendering visible nodes.
Key implementation details:
- Use `useTreeView` hook with `TreeView.RootProvider` for programmatic control
- Pass `scrollToIndexFn` to enable keyboard navigation within the virtualized list
- Use `getVisibleNodes()` to get the flattened list of currently visible nodes
:component-preview{component="tree-view" name="virtualized"}
### Checkbox Tree
Use the `defaultCheckedValue` prop to enable checkbox selection mode. This allows users to select multiple nodes with checkboxes, including parent-child selection relationships.
:component-preview{component="tree-view" name="checkbox-tree"}
### Expand and Collapse All
Use the `expand()` and `collapse()` methods from the tree view context to programmatically expand or collapse all branches.
:component-preview{component="tree-view" name="expand-collapse-all"}
### Mutation
Use the collection's `remove()` and `replace()` methods to dynamically add and remove nodes from the tree. This is useful for building file explorer interfaces where users can create and delete files.
:component-preview{component="tree-view" name="mutation"}
### Rename Node
Enable inline renaming of nodes using the `canRename` prop and `onRenameComplete` callback. Press F2 to activate rename mode on the focused node.
:component-preview{component="tree-view" name="rename-node"}
## Composition
```text
TreeView.Root
├── TreeView.Label
├── TreeView.Tree
│ └── TreeView.NodeProvider
│ ├── TreeView.Branch
│ │ ├── TreeView.BranchControl
│ │ │ ├── TreeView.BranchIndicator
│ │ │ └── TreeView.BranchText
│ │ └── TreeView.BranchContent
│ │ ├── TreeView.BranchIndentGuide
│ │ └── TreeView.Item
│ │ └── TreeView.ItemText
```
## API
See [Ark UI Tree View docs](https://ark-ui.com/vue/docs/components/tree-view){rel=""nofollow""} for full props and examples.
# Typography
:component-preview{component="typography" name="basic"}
## Installation
Install from the Vuzeno registry:
::installation-tabs
---
exec: true
command: shadcn-vue@latest add https://vuzeno.com/r/typography.json
---
::
## Usage
Import the `Typography` namespace and compose text elements with opinionated, responsive defaults:
```vue
Page titleA short introduction below the title.Body copy with comfortable line height.
```
## Composition
```text
Typography
├── H1, H2, H3, H4
├── P
├── Blockquote
├── List
├── InlineCode
├── Lead, Large, Small, Muted
└── TableContainer
└── Table
├── TableRow
├── TableHead
└── TableCell
```
All parts support the `class` prop for overrides and `as-child` for polymorphic composition via [Ark UI](https://ark-ui.com/docs/guides/composition){rel=""nofollow""}.
## Examples
### h1
:component-preview{component="typography" name="h1"}
### h2
:component-preview{component="typography" name="h2"}
### h3
:component-preview{component="typography" name="h3"}
### h4
:component-preview{component="typography" name="h4"}
### p
:component-preview{component="typography" name="p"}
### blockquote
:component-preview{component="typography" name="blockquote"}
### table
:component-preview{component="typography" name="table"}
### list
:component-preview{component="typography" name="list"}
### Inline code
:component-preview{component="typography" name="inline-code"}
### Lead
:component-preview{component="typography" name="lead"}
### Large
:component-preview{component="typography" name="large"}
### Small
:component-preview{component="typography" name="small"}
### Muted
:component-preview{component="typography" name="muted"}