# Colors (/docs/colors) ## Overview [#overview] Tokens mirror [Tailwind color conventions](https://tailwindcss.com/docs/colors#core-concepts), so names align with utility classes and stay predictable in your project. ## Core concepts [#core-concepts] The UI draws from one of nine neutral gray scales. The scale you choose sets backgrounds, borders, and muted tones for the whole theme. The default palette is `neutral`, anchored at `neutral-50` in light mode and `neutral-950` in dark mode. Preview another scale with the swatches below: Click a swatch to switch the neutral scale and preview the theme across the docs. Subtle differences between grays are easiest to judge in dark mode. Build your own color palette Try the [Theme editor](/themes) to visually customize primary, neutral colors and radius. ## Theme Tokens [#theme-tokens] These tokens live in your CSS file under `:root` and `.dark`. ### background / foreground [#background--foreground] The default app background and text color for the page shell, page sections, and default text. * `--background` * `--foreground` ### card [#card] Elevated surfaces and the content inside them, including Card, dashboard panels, and settings panels. * `--card` * `--card-foreground` ### popover [#popover] Floating surfaces and the content inside them, such as Popover, DropdownMenu, ContextMenu, and other overlays. * `--popover` * `--popover-foreground` ### primary [#primary] High-emphasis actions and brand surfaces, including the default Button, selected states, badges, and active accents. * `--primary` * `--primary-foreground` ### secondary [#secondary] Lower-emphasis filled actions and supporting surfaces, such as secondary buttons, secondary badges, and supporting UI. * `--secondary` * `--secondary-foreground` ### muted [#muted] Subtle surfaces and lower-emphasis content for descriptions, placeholders, empty states, helper text, and subdued surfaces. * `--muted` * `--muted-foreground` ### accent [#accent] Interactive hover, focus, and active surfaces for ghost buttons, menu highlight states, hovered rows, and selected items. * `--accent` * `--accent-foreground` ### destructive [#destructive] Destructive actions and error emphasis for destructive buttons, invalid states, and destructive menu items. * `--destructive` * `--destructive-foreground` ### info [#info] Informational actions and emphasis for informational buttons, badges, alerts, status, etc. * `--info` * `--info-foreground` ### success [#success] Success actions and emphasis for success buttons, badges, alerts, status, etc. * `--success` * `--success-foreground` ### warning [#warning] Warning actions and emphasis for warning buttons, badges, alerts, status, etc. * `--warning` * `--warning-foreground` ### border [#border] Default borders and separators on cards, menus, tables, separators, and layout dividers. * `--border` * `--border-foreground` ### input [#input] Form control borders and input surface treatment on Input, Textarea, Select, and outline-style controls. * `--input` * `--input-foreground` ### ring [#ring] Focus rings and outlines on buttons, inputs, checkboxes, menus, and other focusable controls. It follows the primary color. * `--ring` * `--ring-foreground` ### sidebar [#sidebar] The base sidebar surface and default sidebar text on the Sidebar container and its default content. * `--sidebar` * `--sidebar-foreground` ### sidebar-primary [#sidebar-primary] High-emphasis actions inside the sidebar for active items, icon tiles, badges, and sidebar CTAs. * `--sidebar-primary` * `--sidebar-primary-foreground` ### sidebar-accent [#sidebar-accent] Hover and selected states inside the sidebar for menu hover states, open items, and interactive rows. * `--sidebar-accent` * `--sidebar-accent-foreground` ### sidebar-border [#sidebar-border] Sidebar-specific borders and separators on sidebar headers, groups, and internal dividers. * `--sidebar-border` ### sidebar-ring [#sidebar-ring] Sidebar-specific focus rings on focused controls inside the sidebar. It follows the primary color. * `--sidebar-ring` ### radius [#radius] The base corner radius scale for cards, inputs, buttons, popovers, and the derived `radius-*` tokens. Preset theme classes are documented in [Styling](/docs/styling). # Forms (/docs/forms) ## Picking a form library [#picking-a-form-library] For detailed guides with examples, validation, and field-type-specific patterns, see the linked pages above. ## Field Context [#field-context] Form components automatically integrate with `Field` through context. When nested inside a `Field`, they inherit `disabled`, `invalid`, `required`, and `readOnly` states automatically. Also `htmlFor` and `id` are automatically handled by the `Field` component. Never use them directly. ```tsx import { Field } from "@/registry/react/components/field" import { NumberInput } from "@/registry/react/components/number-input" const Demo = () => ( ) ``` ## Input states [#input-states] ### Invalid [#invalid] Pass the `invalid` prop to the `Field` component. The `FieldError` is only visible when the `invalid` prop is `true`. ```tsx import { Field, FieldLabel, FieldError, } from "@/registry/react/components/field" import { Input } from "@/registry/react/components/input" const Demo = () => (
Username Username is required.
) ``` ### Required [#required] Pass the `required` prop to the `Field` component. Optionally, you can use the `FieldRequiredIndicator` to indicate that the field is required. ```tsx import { Field, FieldLabel, FieldRequiredIndicator, FieldError, } from "@/registry/react/components/field" import { Input } from "@/registry/react/components/input" export const Demo = () => (
Username Username is required.
) ``` # Introduction (/docs) Built on top of [Ark UI](https://ark-ui.com) and [shadcn](https://ui.shadcn.com), it includes sensible defaults for styling, variants, and structure, so you can drop components into a project without starting from scratch. It’s not a black-box framework; you own the code, tweak what you need, and build on top of something that’s already thought through. The name blends the two projects it’s built on: **sh** from shadcn and **ark** from Ark UI. **Shark**. ## Motivation [#motivation] [Ark UI](https://ark-ui.com) offers a broad set of headless components and serves as a direct alternative to [Radix Primitives](https://radix-ui.com/primitives) and [Base UI](https://base-ui.com). It gives you accessible primitives and state management, but it leaves styling and layout entirely to you. **shadcn**, on the other hand, ships copy-paste components that look great. The gap is that Ark’s docs don’t show how to pair its primitives with Tailwind, or how to turn them into a reusable design system you can install, theme, and extend. ## How it works [#how-it-works] Instead of only installing a package from npm and importing opaque pieces, you keep source in your repository and change it with your app. That sidesteps the usual spiral of wrappers, style overrides, and mismatched APIs when defaults are not enough. This approach, where you keep and own the source code, means: * **Full transparency:** You see exactly how each component is built, with no hidden layers between you and the implementation. * **Easy customization:** Adjust any part of a component to match your design and functionality; you edit the source instead of working around a package API. * **AI-friendly workflows:** Because the code lives in your repo, LLMs and teammates can read, reason about, and help improve components without reverse-engineering a library. ## AI Ready [#ai-ready] The library is designed so **people and AI tools** can rely on it equally. Components are written to stay clear, readable, and predictable so assistants can understand structure, reason about changes, and modify files with less guesswork. Because the source sits in your repository with **inspectable implementations** and **consistent patterns** from component to component, models get the context they need to read your UI layer end to end. An assistant can learn how your pieces work, propose refactors or small fixes, or generate new components that match your existing tokens, layout, and conventions. # Installation (/docs/installation) ## Prerequisites [#prerequisites] Components require [Tailwind CSS v4](https://tailwindcss.com). Before you begin, make sure you have a project set up with Tailwind CSS installed. ## Adding components [#adding-components] ### CLI [#cli] ```bash npx shadcn@latest add @shark/ ``` ### Manual [#manual] Copy component source from the component docs via the Manual tab. ### All at once [#all-at-once] ```bash npx shadcn@latest add @shark/ui ``` ## New Project Setup [#new-project-setup] For new projects, you have the `CLI` and `Manual` setup. ### CLI [#cli-1] ```bash npx shadcn@latest init @shark/style ``` ### Manual [#manual-1] ## Styling [#styling] For theming and layout setup, see [Styling](/docs/styling). ## Color system [#color-system] See [Colors](/docs/colors) for the full palette and variable reference. # LLMs.txt (/docs/llms-txt) Shark UI provides [LLMs.txt](https://llmstxt.org/) endpoints so AI coding assistants can fetch documentation directly by URL. ## Available Files [#available-files] **Core documentation:** * [/llms.txt](/llms.txt) — Quick reference index for documentation * [/llms-full.txt](/llms-full.txt) — Complete Shark UI documentation **For limited context windows:** * [/llms-components.txt](/llms-components.txt) — Component documentation only * [/llms-patterns.txt](/llms-patterns.txt) — Common patterns and recipes **All platforms:** * [/llms.txt](/llms.txt) — Quick reference index * [/llms-full.txt](/llms-full.txt) — Complete documentation * [/llms-components.txt](/llms-components.txt) — All component documentation * [/llms-patterns.txt](/llms-patterns.txt) — All patterns and recipes ## Integration [#integration] **Claude Code:** Reference the docs in your prompt or add to your project’s `.claude` file: ```bash Use Shark UI documentation from https://shark.vini.one/llms.txt ``` **Cursor:** Use the `@Docs` feature: ```bash @Docs https://shark.vini.one/llms-full.txt ``` [Learn more](https://docs.cursor.com/context/@-symbols/@-docs) **Windsurf:** Add to your `.windsurfrules` file: ```bash #docs https://shark.vini.one/llms-full.txt ``` [Learn more](https://docs.codeium.com/windsurf/memories#memories-and-rules) **Other AI tools:** Most assistants accept documentation URLs: ```bash https://shark.vini.one/llms.txt ``` For component-specific documentation: ```bash https://shark.vini.one/llms-components.txt ``` For patterns and best practices: ```bash https://shark.vini.one/llms-patterns.txt ``` ## Contributing [#contributing] Spotted an issue with AI-generated code? Contributions to improve the LLMs.txt output are welcome on [GitHub](https://github.com/sharkui-inc/shark-ui). # RTL (/docs/rtl) ## Setup [#setup] Wrap your app with `LocaleProvider` and pass an RTL locale. Use this when you know the user’s language ahead of time or when the app switches locale dynamically. ```tsx showLineNumbers {4,6} import { LocaleProvider } from "@/components/ui/locale"; export const App = () => ( {/* Your app */} ); ``` Common RTL locales include `ar-BH`, `ar-SA`, `he-IL`, and `fa-IR`. > **Note:** If no `LocaleProvider` is set up, the default locale is `en-US` and the direction stays `ltr`. ## Applying Direction [#applying-direction] Read the current `dir` from `useLocale` and pass it to your root element—usually ``—so the layout renders correctly and child components inherit the right text direction. ```tsx import { LocaleProvider, useLocale } from "@/components/ui/locale"; const AppContent = () => { const { locale, dir } = useLocale(); return ( {/* Your app content */} ); }; ``` ## How it works [#how-it-works] Shark UI components rely on logical CSS properties wherever possible. That means spacing and layout use `ms-*`, `me-*`, `ps-*`, `pe-*`, and `start-*` / `end-*` instead of physical ones like `ml-*`, `mr-*`, `left-*`, or `right-*`. When you flip `dir` to `rtl`, the layout adapts automatically because those utilities follow the text direction. Setting `dir={dir}` on the root ensures that direction propagates down. Ark UI’s overlays, tooltips, and menus respect the document direction, so they position themselves correctly whether the user reads left-to-right or right-to-left. ## Animations [#animations] Animations should follow the reading direction. Physical utilities like `slide-in-from-right` will slide the wrong way in RTL. Use logical alternatives so motion stays consistent: * `slide-in-from-end` / `slide-out-to-end` instead of `slide-in-from-right` / `slide-out-to-right` * `slide-in-from-start` / `slide-out-to-start` instead of `slide-in-from-left` / `slide-out-to-left` *** For the full API reference, see the [Ark UI documentation](https://ark-ui.com/docs/utilities/locale). # Skills (/docs/skills) This skill covers Shark UI components, patterns, and styling. Your assistant uses it to implement those pieces correctly in your project. You can ask for something concrete: * *“Add a settings dialog with a form and save/cancel buttons.”* * *“Add a combobox with search filtering.”* * *“Migrate this shadcn dropdown to Shark’s Menu.”* * *“Add a Select with grouped options and a placeholder.”* ## Installation [#installation] ```bash npx skills add sharkui-inc/shark-ui ``` The public directory and leaderboard live at [skills.sh](https://skills.sh). ## What you get [#what-you-get] The layout matches other mature UI skills: a compact entry file and deeper material you load only when the task needs it. ### Component knowledge [#component-knowledge] Your assistant gets a map of the registry: what to import, how parts nest, and where the sharp edges are. Overlays (**Dialog** vs **Sheet**), menus (**Menu** vs **Context Menu**), list controls (**Select** vs **Combobox** with collections and filters), **Field**-driven forms, and **Sidebar** shells each have a short guide in the skill pack. That material stays aligned with the published component list in this project and the MDX on this site, so “what the skill says” and “what the docs say” stay in sync. ### Styling conventions [#styling-conventions] Tailwind CSS v4, semantic tokens, and the small habits that keep Shark visually consistent, plus the editorial rules we keep for examples and previews (thumbs, field widths, chart tooltips, sidebar preview framing, and similar detail). ### Migration patterns [#migration-patterns] When someone pastes radix, base-ui, or shadcn-shaped code, the skill nudges the rewrite toward **Shark UI**: collection objects for list primitives, and the chart or sidebar patterns we actually ship, not a generic “swap the import path” pass. ### CLI and registry [#cli-and-registry] The same workflow this site documents for adding components (shadcn-style CLI and the public registry JSON hosted here). The skill reminds agents to follow each component’s installation section, dependency list, and registry entry. ### Registry examples [#registry-examples] Every serious answer should look at the shipped examples that sit beside each component in source. Those snippets are the library’s own compositions; matching them keeps generated UI aligned with how Shark is maintained, not a one-line stub from a model’s training cut-off. ## How it works [#how-it-works] 1. **Activation:** After install, your agent discovers the skill the same way it discovers other Agent Skills. 2. **Progressive depth:** The **SKILL.md** file links into the registry index, shared rule files, and per-component notes only when the prompt touches that surface. 3. **Pattern enforcement:** The assistant follows Shark composition, combobox collection and filtering, chart tooltip wiring where applicable, sidebar preview layout, and the import conventions. 4. **Examples before invention:** The workflow tells the model to read the MDX for the component and the matching example snippets. ## Supported agents [#supported-agents] Any editor or CLI that implements the [Agent Skills](https://agentskills.io) layout can consume this bundle: Claude Code, Cursor, Codex, Cline, Windsurf, GitHub Copilot, and the rest of the list on [skills.sh](https://skills.sh). ## In the repository [#in-the-repository] The skill is versioned in the same open-source project as Shark UI. If you want to read or change it, open the project on [GitHub](https://github.com/sharkui-inc/shark-ui/tree/main/skills/shark-ui). # Styling (/docs/styling) ## Overview [#overview] Shark UI’s styling system is built for clarity and consistent theming. It follows [shadcn/ui theme tokens](https://ui.shadcn.com/docs/theming#theme-tokens) and adds three extra tokens: `success`, `warning`, and `info` to cover status states. ## CSS Configuration [#css-configuration] See [Installation](/docs/installation#new-project-setup) for installing with CLI. To add the theme yourself, paste the following into `globals.css`: ```css title="globals.css" @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); --color-card-foreground: var(--card-foreground); --color-popover: var(--popover); --color-popover-foreground: var(--popover-foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-destructive: var(--destructive); --color-destructive-foreground: var(--destructive-foreground); --color-info: var(--info); --color-info-foreground: var(--info-foreground); --color-success: var(--success); --color-success-foreground: var(--success-foreground); --color-warning: var(--warning); --color-warning-foreground: var(--warning-foreground); --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); --color-sidebar: var(--sidebar); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar-primary: var(--sidebar-primary); --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); --color-sidebar-accent: var(--sidebar-accent); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); --color-chart-1: var(--chart-1); --color-chart-2: var(--chart-2); --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); --radius-xs: calc(var(--radius) * 0.25); --radius-sm: calc(var(--radius) * 0.5); --radius-md: calc(var(--radius) * 0.75); --radius-lg: calc(var(--radius) * 1); --radius-xl: calc(var(--radius) * 1.5); --radius-2xl: calc(var(--radius) * 2); --radius-3xl: calc(var(--radius) * 3); --radius-4xl: calc(var(--radius) * 4); } :root { --radius: 0.5rem; --background: var(--color-neutral-50); --foreground: var(--color-neutral-800); --card: var(--color-neutral-50); --card-foreground: var(--color-neutral-800); --popover: var(--color-neutral-50); --popover-foreground: var(--color-neutral-800); --primary: var(--color-neutral-800); --primary-foreground: var(--color-neutral-50); --secondary: color-mix( in srgb, var(--color-neutral-950) 6%, var(--background) ); --secondary-foreground: var(--color-neutral-800); --muted: color-mix(in srgb, var(--color-neutral-950) 6%, var(--background)); --muted-foreground: color-mix( in srgb, var(--color-neutral-500) 80%, var(--color-neutral-950) ); --accent: color-mix(in srgb, var(--color-neutral-950) 6%, var(--background)); --accent-foreground: var(--color-neutral-800); --destructive: var(--color-red-500); --destructive-foreground: var(--color-red-700); --info: var(--color-blue-500); --info-foreground: var(--color-blue-700); --success: var(--color-emerald-500); --success-foreground: var(--color-emerald-700); --warning: var(--color-amber-500); --warning-foreground: var(--color-amber-700); --border: color-mix(in srgb, var(--color-neutral-950) 12%, var(--background)); --input: color-mix(in srgb, var(--color-neutral-950) 13%, var(--background)); --ring: var(--color-neutral-400); --sidebar: var(--color-neutral-50); --sidebar-foreground: color-mix( in srgb, var(--color-neutral-800) 64%, var(--sidebar) ); --sidebar-primary: var(--color-neutral-800); --sidebar-primary-foreground: var(--color-neutral-50); --sidebar-accent: color-mix( in srgb, var(--color-neutral-950) 6%, var(--sidebar) ); --sidebar-accent-foreground: var(--color-neutral-800); --sidebar-border: color-mix( in srgb, var(--color-neutral-950) 11%, var(--sidebar) ); --sidebar-ring: var(--color-neutral-400); --chart-1: var(--color-orange-600); --chart-2: var(--color-teal-600); --chart-3: var(--color-cyan-900); --chart-4: var(--color-amber-400); --chart-5: var(--color-amber-500); } .dark { --background: var(--color-neutral-950); --foreground: var(--color-neutral-100); --card: color-mix(in srgb, var(--background) 98%, var(--color-neutral-50)); --card-foreground: var(--color-neutral-100); --popover: color-mix( in srgb, var(--background) 96%, var(--color-neutral-50) ); --popover-foreground: var(--color-neutral-100); --primary: var(--color-neutral-100); --primary-foreground: var(--color-neutral-800); --secondary: color-mix(in srgb, var(--color-white) 8%, var(--background)); --secondary-foreground: var(--color-neutral-100); --muted: color-mix(in srgb, var(--color-neutral-50) 8%, var(--background)); --muted-foreground: color-mix( in srgb, var(--color-neutral-500) 70%, var(--color-neutral-50) ); --accent: color-mix(in srgb, var(--color-neutral-50) 8%, var(--background)); --accent-foreground: var(--color-neutral-100); --destructive: color-mix( in srgb, var(--color-red-600) 90%, var(--color-neutral-50) ); --destructive-foreground: var(--color-red-400); --info: var(--color-blue-500); --info-foreground: var(--color-blue-400); --success: var(--color-emerald-500); --success-foreground: var(--color-emerald-400); --warning: var(--color-amber-500); --warning-foreground: var(--color-amber-400); --border: color-mix(in srgb, var(--color-neutral-50) 12%, var(--background)); --input: color-mix(in srgb, var(--color-neutral-50) 13%, var(--background)); --ring: var(--color-neutral-500); --sidebar: color-mix( in srgb, var(--color-neutral-950) 97%, var(--color-neutral-50) ); --sidebar-foreground: color-mix( in srgb, var(--color-neutral-100) 64%, var(--sidebar) ); --sidebar-primary: var(--color-neutral-100); --sidebar-primary-foreground: var(--color-neutral-800); --sidebar-accent: color-mix( in srgb, var(--color-neutral-50) 8%, var(--sidebar) ); --sidebar-accent-foreground: var(--color-neutral-100); --sidebar-border: color-mix( in srgb, var(--color-neutral-50) 11%, var(--sidebar) ); --sidebar-ring: var(--color-neutral-400); --chart-1: var(--color-blue-700); --chart-2: var(--color-emerald-500); --chart-3: var(--color-amber-500); --chart-4: var(--color-purple-500); --chart-5: var(--color-rose-500); } ``` {/* TODO: work on font-heading ## Font Variables The theme preset defines `--font-sans` with system fallbacks. To use custom typefaces, set this variable in your layout via `next/font` or `@fontsource-variable`: ```tsx title="app/layout.tsx" import { Inter } from "next/font/google"; const fontSans = Inter({ variable: "--font-sans", subsets: ["latin"] }); export default function RootLayout({ children }) { return ( {children} ); } ``` */} ## Token convention [#token-convention] Each color has two tokens: the base name is the **fill**. The same name with **`-foreground`** is the **text** and **icon** color meant to sit on that fill. Use both together on every new surface so content stays readable. ```tsx
``` ## Adding new tokens [#adding-new-tokens] New variables must be wired through **`@theme inline`** as `--color-*` entries. See [Tailwind CSS](https://tailwindcss.com/docs/theme) ```css title="globals.css" @theme inline { --color-brand: var(--brand); --color-brand-foreground: var(--brand-foreground); } :root { --brand: oklch(0.55 0.18 250); --brand-foreground: oklch(0.99 0 0); } ``` ## Customizing colors [#customizing-colors] Override variables on `:root` and `.dark`. Always update foreground when you change a fill. ```css title="globals.css" :root { --primary: oklch(76.8% 0.233 130.85); --primary-foreground: oklch(98.6% 0.031 120.757); } .dark { --primary: oklch(53.2% 0.157 131.589); --primary-foreground: oklch(96.7% 0.067 122.328); } ``` ## Radius Scale [#radius-scale] `--radius` is the base radius token for your theme. We derive a small radius scale from it so components can use consistent corner sizes while still sharing a single source of truth. ```css title="app/globals.css" showLineNumbers @theme inline { --radius-xs: calc(var(--radius) * 0.25); --radius-sm: calc(var(--radius) * 0.5); --radius-md: calc(var(--radius) * 0.75); --radius-lg: calc(var(--radius) * 1); --radius-xl: calc(var(--radius) * 1.5); --radius-2xl: calc(var(--radius) * 2); --radius-3xl: calc(var(--radius) * 3); --radius-4xl: calc(var(--radius) * 4); } :root { --radius: 0.5rem; } ``` This means: * `radius-lg` is the base value. * Smaller radius scale down from `--radius`. * Larger radius scale up from `--radius`. * Changing `--radius` updates the entire radius scale. ## Color system [#color-system] See [Colors](/docs/colors) for the full token reference, and naming rules. # January 2026 - Beta 1 (/docs/changelog/26-01-first-beta) Beta 1 marks the first public release of Shark UI. The goal was to build a set of components on [Ark UI](https://ark-ui.com) styled with [Tailwind CSS](https://tailwindcss.com), so you can add accessible primitives to a project without wiring up styles from scratch. ## Components [#components] Roughly 80+ components are available, grouped into several categories: * **UI primitives**: Accordion, Alert, Avatar, Badge, Button, Card, Separator, Skeleton, Tabs * **Overlays and dialogs**: Dialog, Menu, Popover, Sheet, Tooltip, Hover Card, Context Menu * **Forms and inputs**: Input, Textarea, Checkbox, Radio Group, Select, Native Select, Field, Combobox, Input OTP, File Upload, Editable * **Layout and navigation**: Sidebar, Scroll Area, Resizable, Pagination, Breadcrumb, Bottom Navigation * **Feedback and display**: Progress, Slider, Rating Group, Toggle, Toggle Group, Steps, Carousel Components are copy-paste: they land in your project, and you own the code. Tailwind and Ark UI are the only runtime dependencies. ## Theme editor [#theme-editor] The theme editor lets you tweak colors and copy the resulting CSS variables into your project. Themes follow the shadcn color convention, with extra variables for success, warning, info, and destructive states. ## Limitations [#limitations] This is a beta. Some components may change before a stable release. If you run into issues, open an issue on [GitHub](https://github.com/sharkui-inc/shark-ui). # March 2026 - Release Candidate (/docs/changelog/26-03-rc) This release candidate builds on Beta 1 with new components, utilities, theme editor enhancements, and improved documentation. The component registry has been restructured with thumbs and consistent example naming. ## New Components [#new-components] * **Announcement** — Banner-style component for promotions and notices * **Calendar** — Full calendar with month/year navigation and range selection * **Color Picker** — Color selection with swatches and input fields * **Date Picker** — Date input with calendar popover and presets * **Drawer** — Slide-out panel for mobile-first layouts * **Image Cropper** — Crop images with zoom, aspect ratio, and constraints * **Prose** — Typography styles for markdown and long-form content * **Signature Pad** — Canvas-based signature capture * **Skip Nav** — Accessibility link to skip to main content * **Timer** — Countdown, interval, and Pomodoro timers ## New Utilities [#new-utilities] * **Client Only** — Render components only on the client * **Format** — Date, number, and relative time formatting * **Show** — Conditional rendering with animation support * **Download Trigger** — Programmatic file downloads * **Swap** — Toggle between two states with animation * **Presence** — Mount/unmount with enter/exit animations * **JSON Tree View** — Expandable JSON display * **Highlight** — Syntax highlighting for code blocks ## Component Updates [#component-updates] Registry examples and thumbs were standardized across components: * **Button** — Variants, sizes, and icon support * **Card** — Composition and theming * **Combobox** — Multi-select and controlled state * **Dialog** — Sizes and compositions * **Field** — Required fields and validation * **Floating Panel** — Positions and resize behavior * **Input Group** — Button integration and addons * **Menu** — Nested menus and keyboard navigation * **Number Input** — Stepper and format options * **Pagination** — Sizes and variants * **Select** — Multi-select and custom items * **Textarea** — Autoresize and validation * **Toast** — Placement, types, and promises * **Toggle** — Sizes, outline, and icon variants * **Tooltip** — Positioning and keyboard support * **Tour** — Step types, progress, and async steps ## Theme Editor [#theme-editor] * Updated color variable system and theme presets * Support for success, warning, info, and destructive states * Prose typography styles for content blocks ## Home Page [#home-page] * Redesigned hero with Announcement component * Component examples (Input OTP, forms, calendar, charts, and more) * Framework support badges (React, Solid, Vue, Svelte) * Theme cards for activity, chat, and sharing examples ## Documentation [#documentation] * **Forms** — New forms section with React Hook Form and TanStack Form guides * **RTL** — Right-to-left layout support * Component docs updated with API references and examples * New installation guides for various frameworks ## Infrastructure [#infrastructure] * Open Graph image generation for docs and changelog * RSS feed and sitemap generation * LLMs.txt route for AI crawlers ## Dependencies [#dependencies] * Package updates for Next.js, React, Ark UI, and dev tooling # May 2026 - Post-RC updates (/docs/changelog/26-05-post-rc) This update follows the March release candidate with ecosystem listing, a new Hitbox utility, expanded hooks and agent documentation, site improvements, and many fixes across theming and components. ## Registry & ecosystem [#registry--ecosystem] * **shadcn registry** — Shark UI is wired into the broader shadcn registry configuration via `components.json` * **Registry build** — Manifest and `public/r/*.json` metadata refreshed; registry build script updated for maintainers ## New utility [#new-utility] * **Hitbox** — Enlarge tap and click targets without changing layout; includes docs, registry examples, and dedicated styles ## Hooks & CLI-facing docs [#hooks--cli-facing-docs] * **use-is-mobile** — Documented hook for responsive behavior * **style**, **ui**, **utils** — Registry items exposed for CLI installs alongside other meta updates ## Site & product [#site--product] * **Blocks** — Early `/blocks` route scaffold for the blocks experience * **Analytics** — Site analytics integration * **Funding** — Ko-fi support link in project metadata * **Agent skill** — Shark UI skill for Cursor and expanded primitive references for contributors and coding agents ## Documentation & layout [#documentation--layout] * **Installation & components** — Dedicated overview pages for installation and the component index (`ComponentsList`), with framework guides remaining under Installation * **Docs shell** — Fixes for table of contents when headings are sparse, component doc routing, CLI copy snippets, and content replacement behavior * **Layout** — Global scrollbar and overflow refinements on the docs body ## Components & theming [#components--theming] * **Theme** — Switcher reliability and reduced first-paint flicker; border and input CSS variables; background token alignment * **Dialog** — RTL layout fix * **Table** — Spacing and header text treatment * **CodeBlock** / **Highlight** — Standardized prop for line numbers * **Badge** — Improved touch behavior for coarse pointers * **Combobox** — Follow-up fixes and examples after the combobox workstream * **Announcement** — Updates from community PRs * **Drawer**, **Toast**, **Sidebar**, **Timer**, **Prose** — Props, examples, and styling tweaks * **data-slot** — Consistency fix for slot-based styling hooks ## Dependencies & infrastructure [#dependencies--infrastructure] * Dependency updates and small component refactors * CI workflow adjustments for contributor runs # Changelog (/docs/changelog) Releases are listed by date, newest first. Each entry describes what changed—components added or updated, breaking changes, and fixes. For release tags and diffs, check the [Shark UI repository](https://github.com/sharkui-inc/shark-ui) on GitHub. # Formisch (/docs/forms/formisch) This guide will cover building forms using the [Field](/docs/components/field) component, adding schema validation with [Valibot](https://valibot.dev), handling errors, ensuring accessibility, and more. ## Demo [#demo] We’ll build a form with a text input and textarea. When you submit, the form data is validated and any errors will be shown. Browser validation disabled For the purposes of this demo, browser validation is disabled to illustrate schema validation. In production, keep native validation enabled when appropriate. ## Approach [#approach] This form uses Formisch for state and Valibot for validation. We'll build forms using the `Field` component, which gives you complete flexibility over the markup and styling. * Uses Formisch's `useForm` hook for form state management. * Uses the `Form` component for submit handling. * Import Formisch’s `Field` under an alias (`FormischField`) for controlled inputs. * Uses Shark `Field` components for building accessible forms. * Uses client-side validation by passing your Valibot schema into `schema`. ## Anatomy [#anatomy] Typical structure: wrap each field with `FormischField`, and the `Field` component. ```tsx showLineNumbers {5-12}
{(field) => ( Bug Title Provide a concise title for your bug report. {field.errors?.[0]} )}
``` ## Form [#form] ### Create a schema [#create-a-schema] Define your form shape with a Valibot schema. **Note:** Formisch only supports [Valibot](https://formisch.dev/react/guides/installation/#install-valibot) for validation. ### Setup [#setup] * Create the form with `useForm` from Formisch and pass your schema to the `schema` option, * Wrap fields in `Form` and pass the form to the `onSubmit` option. ```tsx showLineNumbers title="form.tsx" {9-15,18-20} import { Form, Field as FormischField, useForm } from "@formisch/react"; import * as v from "valibot"; const formSchema = v.object({ // ... }); export const BugReportForm = () => { const form = useForm({ schema: formSchema, initialInput: { title: "", description: "", }, }); return (
console.log(output)}> {/* Build the form here */}
); }; ``` ### Build [#build] Build the form using the `FormischField` from Formisch and the Shark `Field`. ### Done [#done] That's it. You now have a fully accessible form with client-side validation. When you submit the form, the `onSubmit` handler on `Form` receives validated output. If the form data is invalid, Formisch will display the errors on `field.errors` for `FieldError`. ## Validation [#validation] ### Client-side [#client-side] Formisch validates your form data using the Valibot schema. Define a schema and pass it to the `schema` option of the `useForm` hook. ```tsx showLineNumbers title="example-form.tsx" {4-7,11} import { useForm } from "@formisch/react" import * as v from "valibot" const formSchema = v.object({ title: v.string(), description: v.optional(v.string()), }) export const ExampleForm = () => { const form = useForm({ schema: formSchema, initialInput: { title: "", description: "", }, }) } ``` ### Modes [#modes] Configure when validation runs via the `validate` and `revalidate` options: ```tsx showLineNumbers title="form.tsx" {3-4} const form = useForm({ schema: formSchema, validate: "submit", revalidate: "input", }) ``` | Option | Role | | ----------- | -------------------------------------- | | `"initial"` | Validation triggers on initial render. | | `"touch"` | Validation triggers on field touch. | | `"input"` | Validation triggers on field input. | | `"change"` | Validation triggers on field change. | | `"blur"` | Validation triggers on field blur. | | `"submit"` | Validation triggers on form submit. | ## Displaying Errors [#displaying-errors] Display errors next to the field using `FieldError`. For styling and accessibility: * Add the `invalid` prop to the `Field` component. * Don't need to add the `invalid` prop to the form control such as `Input`, `Checkbox`, etc. ```tsx showLineNumbers title="form.tsx" {3,6} {(field) => ( Email {field.errors?.[0]} )} ``` ## Different types of fields [#different-types-of-fields] ### Input [#input] * Spread `field.props` on `Input` and set `value={field.input}`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Textarea [#textarea] * Spread `field.props` on `Textarea` and set `value={field.input}`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### NativeSelect [#nativeselect] * Spread `field.props` on `NativeSelect` and set `value={field.input}`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Select [#select] * Wire `field.input` and `field.onChange` to `Select`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Checkbox [#checkbox] * Wire `field.input` and `field.onChange` to `Checkbox`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. * Remember to add `data-slot="checkbox-group"` to the `FieldGroup` component for proper styling and spacing. ### Radio group [#radio-group] * Wire `field.input` and `field.onChange` to `RadioGroup`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Switch [#switch] * Wire `field.input` and `field.onChange` to `Switch`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### NumberInput [#numberinput] * Wire `field.input` and `field.onChange` to `NumberInput`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Slider [#slider] * Wire `field.input` and `field.onChange` to `Slider`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Combobox [#combobox] * Wire `field.input` and `field.onChange` to `Combobox`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Autocomplete [#autocomplete] * Wire `field.input` and `field.onChange` to `Autocomplete`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Date Picker [#date-picker] * Wire `field.input` and `field.onChange` to `DatePicker`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Input OTP [#input-otp] * Wire `field.input` and `field.onChange` to `InputOTP`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Rating [#rating] * Use `field.onChange` with `Rating`’s `onValueChange` and bind `value` from `field.input`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### File Upload [#file-upload] * Use `FileUpload` `onFileAccept` to push files into the field value (`field.onChange`). * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Complex Forms [#complex-forms] Here is an example of a more complex form with multiple fields and validation. ## Resetting the Form [#resetting-the-form] Import `reset` and pass the form to reset the form to its default values. ```tsx showLineNumbers import { reset } from "@formisch/react"; ``` ## Array Fields [#array-fields] Formisch provides a `FieldArray` component for managing dynamic array fields. Also provides helpers like `insert` and `remove` for dynamic lists. This is useful when you need to add or remove fields dynamically. ### Array Field Structure [#array-field-structure] Use `FieldArray` component and pass the form to the `of` prop. ```tsx showLineNumbers title="form.tsx" {9-15} import { FieldArray, Field as FormischField, useForm } from "@formisch/react"; export const ExampleForm = () => { const form = useForm({ // ... form config }); return ( {(arrayField) => ( arrayField.items.map((itemId, index) => ( // Nested field for each array item )) )} ); } ``` ### Nested Fields [#nested-fields] Use `arrayField.items` to render each nested field, passing the correct path for each item. ```tsx showLineNumbers title="form.tsx" { arrayField.items.map((itemId, index) => ( {(field) => ( field.onChange(e.target.value)} placeholder="name@example.com" type="email" value={field.input} /> {arrayField.items.length > 1 && ( remove(form, { path: ["emails"], at: index }) } size="icon-xs" type="button" variant="ghost" > )} {field.errors?.[0]} )} )) } ``` ### Adding items [#adding-items] * Use `insert` to add a new array item. * Provide `initialInput` matching the nested structure of the array element. ```tsx showLineNumbers title="form.tsx" import { insert } from "@formisch/react"; ``` ### Removing items [#removing-items] Use `remove` with the array path and index. ```tsx showLineNumbers title="form.tsx" import { remove } from "@formisch/react"; { arrayField.items.length > 1 && ( remove(form, { path: ["emails"], at: index })} aria-label={`Remove email ${index + 1}`} > ); } ``` ### Array validation [#array-validation] Use Valibot's `array` method to validate array fields. ```tsx showLineNumbers title="form.tsx" import * as v from "valibot"; const formSchema = v.object({ emails: v.pipe( v.array( v.object({ contact: v.object({ address: v.pipe( v.string(), v.nonEmpty("Enter an email address."), v.email("Enter a valid email address.") ), }), }) ), v.minLength(1, "Add at least one email address."), v.maxLength(5, "You can add up to 5 email addresses.") ), }); ``` # React Hook Form (/docs/forms/react-hook-form) This guide will cover building forms using the [Field](/docs/components/field) component, adding schema validation with [Zod](https://zod.dev), handling errors, ensuring accessibility, and more. ## Demo [#demo] We’ll build a form with a text input and textarea. When you submit, the form data is validated and any errors will be shown. Browser validation disabled For the purposes of this demo, browser validation is disabled to illustrate schema validation. In production, keep native validation enabled when appropriate. ## Approach [#approach] This form uses React Hook Form for state and Zod for validation. We'll build forms using the `Field` component, which gives you complete flexibility over the markup and styling. * Uses React Hook Form's useForm hook for form state management. * Uses the `Controller` component for controlled inputs. * Uses the `Field` components for building accessible forms. * Uses client-side validation by passing your Zod schema into `resolver`. ## Anatomy [#anatomy] Typical structure: wrap each field with `Controller`, and the `Field` component. ```tsx showLineNumbers {7-18}
( Bug Title Provide a concise title for your bug report. {fieldState.error?.message} )} />
``` ## Form [#form] ### Create a schema [#create-a-schema] Define your form shape with a Zod schema. **Note:** React Hook Form supports other [Standard Schema](https://react-hook-form.com/get-started#SchemaValidation) libraries; Zod is used here for clarity. ```tsx showLineNumbers title="form.tsx" import * as z from "zod" const formSchema = z.object({ title: z .string() .min(5, "Bug title must be at least 5 characters.") .max(32, "Bug title must be at most 32 characters."), description: z .string() .min(20, "Description must be at least 20 characters.") .max(100, "Description must be at most 100 characters."), }) ``` ### Setup [#setup] Create the form with `useForm` from React Hook Form and pass your schema to the `resolver` option. ```tsx showLineNumbers title="form.tsx" {10-16} import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import * as z from "zod"; const formSchema = z.object({ // ... }); export const BugReportForm = () => { const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { title: "", description: "", }, }); const onSubmit = (data: z.infer) => { console.log(data); } return (
{/* Build the form here */}
); }; ``` ### Build [#build] Build the form using the `Controller` from React Hook Form and the Shark `Field`. ### Done [#done] That's it. You now have a fully accessible form with client-side validation. When you submit the form, the `onSubmit` function will be called with the validated form data. If the form is invalid, React Hook Form will display the errors on `field.state.error` for `FieldError`. ## Validation [#validation] ### Client-side [#client-side] React Hook Form validates your form data using the Zod schema. Define a schema and pass it to the `resolver` option of the `useForm` hook. ```tsx showLineNumbers title="example-form.tsx" {5-8,12} import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import * as z from "zod" const formSchema = z.object({ title: z.string(), description: z.string().optional(), }) export const ExampleForm = () => { const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { title: "", description: "", }, }) } ``` ### Modes [#modes] Configure when validation runs via the `mode` option: ```tsx showLineNumbers title="form.tsx" {3} const form = useForm({ resolver: zodResolver(formSchema), mode: "onChange", }) ``` | Mode | Description | | ------------- | -------------------------------------------------------- | | `"onChange"` | Validation triggers on every change. | | `"onBlur"` | Validation triggers on blur. | | `"onSubmit"` | Validation triggers on submit (default). | | `"onTouched"` | Validation triggers on first blur, then on every change. | | `"all"` | Validation triggers on blur and change. | ## Displaying Errors [#displaying-errors] Display errors next to the field using `FieldError`. For styling and accessibility: * Add the `invalid` prop to the `Field` component. * Don't need to add the `invalid` prop to the form control such as `Input`, `Checkbox`, etc. ```tsx showLineNumbers title="form.tsx" {5,8} ( Email {fieldState.error?.message} )} /> ``` ## Different types of fields [#different-types-of-fields] ### Input [#input] * Spread the field object onto the `Input` component. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Textarea [#textarea] * Spread the field object onto the `Textarea` component. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### NativeSelect [#nativeselect] * Spread the field object onto the `NativeSelect` component. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Select [#select] * Wire `field.value` and `field.onChange` to `Select`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Checkbox [#checkbox] * Wire `field.value` and `field.onChange` to `Checkbox`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. * Remember to add `data-slot="checkbox-group"` to the `FieldGroup` component for proper styling and spacing. ### Radio group [#radio-group] * Wire `field.value` and `field.onChange` to `RadioGroup`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Switch [#switch] * Wire `field.value` and `field.onChange` to `Switch`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### NumberInput [#numberinput] * Wire `field.value` and `field.onChange` to `NumberInput`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Slider [#slider] * Wire `field.value` and `field.onChange` to `Slider`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Combobox [#combobox] * Wire `field.value` and `field.onChange` to `Combobox`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Autocomplete [#autocomplete] * Wire `field.value` and `field.onChange` to `Autocomplete`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Date Picker [#date-picker] * Wire `field.value` and `field.onChange` to `DatePicker`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Input OTP [#input-otp] * Wire `field.value` and `field.onChange` to `InputOTP`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Rating [#rating] * Wire `field.value` and `field.onChange` to `Rating`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### File Upload [#file-upload] * Wire `field.value` and `field.onChange` to `FileUpload`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Complex Forms [#complex-forms] Here is an example of a more complex form with multiple fields and validation. ## Resetting the Form [#resetting-the-form] Use `form.reset()` to reset the form to its default values. ```tsx showLineNumbers ``` ## Array Fields [#array-fields] React Hook Form provides a `useFieldArray` hook for managing dynamic array fields. This is useful when you need to add or remove fields dynamically. ### Using useFieldArray [#using-usefieldarray] Use the `useFieldArray` hook to manage array fields. It provides `fields`, `append`, and `remove` methods. ```tsx showLineNumbers title="form.tsx" {8-11} import { useFieldArray, useForm } from "react-hook-form"; export const ExampleForm = () => { const form = useForm({ // ... form config }); const { fields, append, remove } = useFieldArray({ control: form.control, name: "emails", }); } ``` ### Array Field Structure [#array-field-structure] Wrap your array fields in a `FieldSet` with a `FieldLegend` and `FieldDescription`. ```tsx showLineNumbers title="form.tsx"
Email Addresses Add up to 5 email addresses where we can contact you. {/* Array items go here */}
``` ### Controller Pattern for Array Items [#controller-pattern-for-array-items] Map over the `fields` array and use `Controller` for each item. **Make sure to use `field.id` as the key**. ```tsx showLineNumbers title="form.tsx" { fields.map((field, index) => ( ( {/* Remove button */} {fieldState.error?.message} )} /> ))} ``` ### Adding Items [#adding-items] Use the `append` method to add new items to the array. ```tsx showLineNumbers title="form.tsx" ``` ### Removing Items [#removing-items] Use the `remove` method to remove items from the array. Add the remove button conditionally. ```tsx showLineNumbers title="form.tsx" { fields.length > 1 && ( remove(index)} aria-label={`Remove email ${index + 1}`} > )} } ``` ### Array Validation [#array-validation] Use Zod's `array` method to validate array fields. ```tsx showLineNumbers title="form.tsx" const formSchema = z.object({ emails: z .array( z.object({ address: z.string().email("Enter a valid email address."), }) ) .min(1, "Add at least one email address.") .max(5, "You can add up to 5 email addresses."), }); ``` # TanStack Form (/docs/forms/tanstack-form) This guide will cover building forms using the [Field](/docs/components/field) component, adding schema validation with [Zod](https://zod.dev), handling errors, ensuring accessibility, and more. ## Demo [#demo] We’ll build a form with a text input and textarea. When you submit, the form data is validated and any errors will be shown. Browser validation disabled For the purposes of this demo, browser validation is disabled to illustrate schema validation. In production, keep native validation enabled when appropriate. ## Approach [#approach] This form uses TanStack Form for state and Zod for validation. We'll build forms using the `Field` component, which gives you complete flexibility over the markup and styling. * Uses TanStack Form's `useForm` hook for form state management. * Uses `form.Field` with a render function for controlled inputs. * Uses the `Field` components for building accessible forms. * Uses client-side validation by passing your Zod schema into `validators`. ## Anatomy [#anatomy] Here's a basic example of a form using TanStack Form with the `Field` component. ```tsx showLineNumbers {11-29}
{ e.preventDefault() form.handleSubmit() }} > ( Bug Title field.handleChange(e.target.value)} placeholder="Login button not working on mobile" autoComplete="off" /> Provide a concise title for your bug report. {field.state.meta.errors .map((e) => e?.message || e) .join(", ")} )} />
``` ## Form [#form] ### Create a schema [#create-a-schema] Define your form shape with a Zod schema. **Note:** TanStack Form works with Zod and other [Standard Schema](https://tanstack.com/form/latest/docs/framework/react/guides/validation#schema-validation) libraries via its validators API. ```tsx showLineNumbers title="form.tsx" import * as z from "zod" const formSchema = z.object({ title: z .string() .min(5, "Bug title must be at least 5 characters.") .max(32, "Bug title must be at most 32 characters."), description: z .string() .min(20, "Description must be at least 20 characters.") .max(100, "Description must be at most 100 characters."), }) ``` ### Setup [#setup] * Create the form with `useForm` from TanStack Form and pass your schema to the `onSubmit` option. * Use e.preventDefault() and e.stopPropagation() before calling form.handleSubmit() ```tsx showLineNumbers title="form.tsx" {9-18} import { useForm } from "@tanstack/react-form"; import * as z from "zod"; const formSchema = z.object({ // ... }); export const ExampleForm = () => { const form = useForm({ defaultValues: { title: "", description: "", }, validators: { onSubmit: formSchema }, onSubmit: async ({ value }) => { console.log(value); }, }); return (
{ e.preventDefault(); e.stopPropagation() form.handleSubmit(); }} > {/* Build the form here */}
); }; ``` ### Build [#build] build the form using the `form.Field` from TanStack Form and the Shark `Field`. ### Done [#done] That's it. You now have a fully accessible form with client-side validation. When you submit the form, the `onSubmit` handler receives validated values. If the form is invalid, TanStack Form exposes errors on `field.state.meta.errors` for `FieldError`. ## Validation [#validation] ### Client-side [#client-side] TanStack Form validates your form data using the Zod schema. Define a schema and pass it to the `validators` option of the `useForm` hook. ```tsx showLineNumbers title="example-form.tsx" {4-7,15} import { useForm } from "@tanstack/react-form" import * as z from "zod" const formSchema = z.object({ title: z.string(), description: z.string().optional(), }) export const ExampleForm = () => { const form = useForm({ defaultValues: { title: "", description: "", }, validators: { onSubmit: formSchema }, onSubmit: async () => {}, }) } ``` ### Modes [#modes] Configure when validation runs via the `validators` option: ```tsx showLineNumbers title="form.tsx" {2} const form = useForm({ validators: { onSubmit: formSchema }, }) ``` | Mode | Description | | ------------ | ------------------------------------ | | `"onChange"` | Validation triggers on every change. | | `"onBlur"` | Validation triggers on blur. | | `"onSubmit"` | Validation triggers on submit. | ## Displaying Errors [#displaying-errors] Display errors next to the field using `FieldError`. For styling and accessibility: * Add the `invalid` prop to the `Field` component. * Don't need to add the `invalid` prop to the form control such as `Input`, `Checkbox`, etc. ```tsx showLineNumbers title="form.tsx" {4,13-15} ( Email field.handleChange(e.target.value)} type="email" value={field.state.value} /> {field.state.meta.errors.map((e) => e?.message).join(", ")} )} /> ``` ## Different types of fields [#different-types-of-fields] ### Input [#input] * Bind `field.state.value` and `field.handleChange` to `Input`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Textarea [#textarea] * Bind `field.state.value` and `field.handleChange` to `Textarea`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### NativeSelect [#nativeselect] * Bind `field.state.value` and `field.handleChange` to `NativeSelect`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Select [#select] * Wire `value` and `onValueChange` on `Select`. For overlays, call `field.handleBlur()` from `onInteractOutside` when your example needs blur sync. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. ### Checkbox [#checkbox] * Wire `field.state.value` and `field.handleChange` to `Checkbox`. * Add the `invalid` prop to the `Field` component and pass the error message to the `FieldError` component. * For checkbox arrays, use `mode="array"` on the `form.Field` component and TanStack Form's array helpers. * Remember to add `data-slot="checkbox-group"` to the `FieldGroup` component for proper styling and spacing. ### Radio group [#radio-group] * Wire `field.state.value` and `field.handleChange` to `RadioGroup`. * Add the `invalid` prop to the `Field` component and pass the `FieldError` component. ### Switch [#switch] * Use `field.state.value` and `field.handleChange` with `Switch`. * Add the `invalid` prop to the `Field` component and pass the `FieldError` component. ### NumberInput [#numberinput] * Wire `field.state.value` and `field.handleChange` to `NumberInput`. * Add the `invalid` prop to the `Field` component and pass the `FieldError` component. ### Slider [#slider] * Wire `field.state.value` and `field.handleChange` to `Slider`. * Add the `invalid` prop to the `Field` component and pass the `FieldError` component. ### Combobox [#combobox] * Wire `field.state.value` and `field.handleChange` to `Combobox`. * Add the `invalid` prop to the `Field` component and pass the `FieldError` component. ### Autocomplete [#autocomplete] * Wire `field.state.value` and `field.handleChange` to `Autocomplete`. * Add the `invalid` prop to the `Field` component and pass the `FieldError` component. ### Date Picker [#date-picker] * Wire `field.state.value` and `field.handleChange` to `DatePicker`. * Add the `invalid` prop to the `Field` component and pass the `FieldError` component. ### Input OTP [#input-otp] * Use `field.state.value` (as `string[]`) and `field.handleChange` with `InputOTP`. * Add the `invalid` prop to the `Field` component and pass the `FieldError` component. ### Rating [#rating] * Wire `field.state.value` and `field.handleChange` to `Rating`. * Add the `invalid` prop to the `Field` component and pass the `FieldError` component. ### File Upload [#file-upload] * Wire `onFileAccept` to sync files into form state. * Add the `invalid` prop to the `Field` component and pass the `FieldError` component. ### Complex Forms [#complex-forms] Here is an example of a more complex form with multiple fields and validation. ## Resetting the Form [#resetting-the-form] Use `form.reset()` to reset the form to its default values. ```tsx showLineNumbers ``` ## Array Fields [#array-fields] TanStack Form provides powerful array field management with `mode="array"`. This allows you to dynamically add, remove, and update array items with full validation support. ### Array Field Structure [#array-field-structure] Use `mode="array"` on the parent field to enable array field management. ```tsx showLineNumbers title="form.tsx" {3,11-13} (
Email Addresses Add up to 5 email addresses where we can contact you. {field.state.value.map((_, index) => ( // Nested field for each array item ))}
)} /> ``` ### Nested Fields [#nested-fields] Access individual array items using bracket notation: `fieldName[index].propertyName`. ```tsx showLineNumbers title="form.tsx" ( subField.handleChange(e.target.value)} placeholder="name@example.com" type="email" /> {field.state.value.length > 1 && ( field.removeValue(index)} aria-label={`Remove email ${index + 1}`} > )} {subField.state.meta.errors.map((e) => e?.message).join(", ")} )} /> ``` ### Adding Items [#adding-items] Use `field.pushValue(item)` to add items to an array field. You can disable the button when the array reaches its maximum length. ```tsx showLineNumbers title="form.tsx" ``` ### Removing Items [#removing-items] Use `field.removeValue(index)` to remove items from an array field. You can conditionally show the remove button only when there's more than one item. ```tsx showLineNumbers title="form.tsx" { field.state.value.length > 1 && ( field.removeValue(index)} aria-label={`Remove email ${index + 1}`} > ) } ``` ### Removing items [#removing-items-1] Use `removeValue(index)` on the array field. ```tsx showLineNumbers title="form.tsx" { emailsField.state.value.length > 1 && ( emailsField.removeValue(index)} aria-label={`Remove email ${index + 1}`} > ); } ``` ### Array validation [#array-validation] Validate arrays with Zod’s `z.array()` and `.min()` / `.max()`. ```tsx showLineNumbers title="form.tsx" const formSchema = z.object({ emails: z .array( z.object({ address: z.string().email("Enter a valid email address."), }) ) .min(1, "Add at least one email address.") .max(5, "You can add up to 5 email addresses."), }); ``` # useIsMobile (/docs/hooks/use-is-mobile) `useIsMobile` tells you if the viewport is less than **768px**. It uses `matchMedia`, so it reacts instantly to browser zoom and device rotation, not just window resizing. ## Installation [#installation] CLI Manual ```bash npx shadcn@latest add @shark/use-is-mobile ``` This hook has no package dependencies beyond React. Copy and paste the following code into your project. Update the import paths to match your project setup. ## Usage [#usage] ```tsx import { useIsMobile } from "@/registry/react/hooks/use-is-mobile"; ``` ## Example [#example] ```tsx showLineNumbers "use client"; import { useIsMobile } from "@/registry/react/hooks/use-is-mobile"; export function Example() { const isMobile = useIsMobile(); return (

{isMobile ? "Mobile layout" : "Desktop layout"}

); } ``` # Astro (/docs/installation/astro) ## Use the Shark Preset [#use-the-shark-preset] ### Create Project [#create-project] Run the `init` command with the Shark preset and the Astro template: ```bash npx shadcn@latest init @shark/style -t astro ``` ### Add Components [#add-components] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components in an Astro page with a React client directive: ```astro title="src/pages/index.astro" showLineNumbers --- import Layout from "@/layouts/main.astro"; import { Button } from "@/components/ui/button"; ---
```
## Use the CLI [#use-the-cli] ### Create Project [#create-project-1] Run the `init` command to scaffold a new Astro project and configure Shark UI: ```bash npx shadcn@latest init @shark/style -t astro ``` For a monorepo project, use the `--monorepo` flag: ```bash npx shadcn@latest init @shark/style -t astro --monorepo ``` ### Add Components [#add-components-1] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root: ```bash npx shadcn@latest add @shark/button -c apps/web ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components in an Astro page with a React client directive: ```astro title="src/pages/index.astro" showLineNumbers --- import Layout from "@/layouts/main.astro"; import { Button } from "@/components/ui/button"; ---
``` If you created a monorepo, update `apps/web/src/pages/index.astro` and import from your workspace UI package instead. The monorepo layout at `apps/web/src/layouts/main.astro` already imports your shared global CSS for you.
## Existing Project [#existing-project] ### Create Project [#create-project-2] If you need a new Astro project, create one first. Otherwise, skip this step. ```bash npm create astro@latest astro-app -- --template with-tailwindcss --install --add react --git ``` This command sets up Tailwind CSS and the React integration for you. If you're adding Shark UI to an older or custom Astro app, make sure both are configured before continuing. The Tailwind starter loads your global stylesheet through `src/layouts/main.astro`. Keep that layout in place, or make sure your page imports `@/styles/global.css`. ### Edit tsconfig.json [#edit-tsconfigjson] Add path aliases so imports resolve correctly: ```ts title="tsconfig.json" showLineNumbers { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } } ``` ### Run the CLI [#run-the-cli] Run the `shadcn` init command with the Shark preset to set up your project. ```bash npx shadcn@latest init @shark/style ``` ### Add Components [#add-components-2] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components in an Astro page with a React client directive: ```astro title="src/pages/index.astro" showLineNumbers --- import Layout from "@/layouts/main.astro"; import { Button } from "@/components/ui/button"; ---
```
# Laravel (/docs/installation/laravel) The shadcn CLI does not scaffold a new Laravel app. Start by creating a Laravel app with the React starter kit, then choose how you want to configure Shark UI. ### Create Project [#create-project] Create a new Laravel app using the Laravel installer: ```bash laravel new my-app ``` If you already have a Laravel app with React and Inertia configured, skip this step. Choose the **React** starter kit when prompted. For more information, see the official [Laravel frontend documentation](https://laravel.com/docs/starter-kits#react). Then move into your project directory: ```bash cd my-app ``` ## Use the Shark Preset [#use-the-shark-preset] ### Run the Command [#run-the-command] Run the `init` command with the Shark preset and the Laravel template from the root of your Laravel app: ```bash npx shadcn@latest init @shark/style -t laravel ``` When asked to overwrite `components.json` and components, choose `Yes`. ### Add Components [#add-components] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Switch` component to your project: ```bash npx shadcn@latest add @shark/switch ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="resources/js/pages/index.tsx" showLineNumbers import { Switch } from "@/components/ui/switch"; const MyPage = () => { return (
); }; export default MyPage; ```
## Use the CLI [#use-the-cli] ### Run the CLI [#run-the-cli] Run the `shadcn` init command with the Shark preset from the root of your Laravel app: ```bash npx shadcn@latest init @shark/style ``` When asked to overwrite `components.json` and components, choose `Yes`. ### Add Components [#add-components-1] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Switch` component to your project: ```bash npx shadcn@latest add @shark/switch ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="resources/js/pages/index.tsx" showLineNumbers import { Switch } from "@/components/ui/switch"; const MyPage = () => { return (
); }; export default MyPage; ```
# Manual Installation (/docs/installation/manual) Manual setup gives you full control over every file. Use this when the CLI does not fit your setup or you prefer to wire the project yourself. ### Add Tailwind CSS [#add-tailwind-css] Components are styled using Tailwind CSS. Install Tailwind CSS in your project first: [Follow the Tailwind CSS installation instructions.](https://tailwindcss.com/docs/installation) ### Add dependencies [#add-dependencies] Add the dependencies used by Shark UI components: ```bash pnpm add @ark-ui/react tailwind-variants clsx tailwind-merge lucide-react tw-animate-css ``` ### Configure import aliases [#configure-import-aliases] Choose one of the following alias setups. #### Option A: tsconfig.json paths [#option-a-tsconfigjson-paths] ```json title="tsconfig.json" showLineNumbers {2-6} { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./*"] } } } ``` #### Option B: package.json#imports [#option-b-packagejsonimports] ```json title="package.json" showLineNumbers { "imports": { "#components/*": "./src/components/*.tsx", "#lib/*": "./src/lib/*.ts", "#hooks/*": "./src/hooks/*.ts" } } ``` ```json title="tsconfig.json" showLineNumbers { "compilerOptions": { "moduleResolution": "bundler", "resolvePackageJsonImports": true } } ``` The `@` alias is a preference. You can use other aliases if needed. If you use `package.json#imports`, keep the matching alias roots in `components.json`. ### Configure styles [#configure-styles] Create a file `styles/globals.css` and follow [Styling](/docs/styling#css-configuration) to configure the theme. ### Add a cn helper [#add-a-cn-helper] ```ts title="lib/utils.ts" showLineNumbers import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs)) ``` ### Create a components.json file [#create-a-componentsjson-file] Create a `components.json` file in the project root so the shadcn CLI knows where to write components if you use it later. ```json title="components.json" showLineNumbers { "$schema": "https://ui.shadcn.com/schema.json", "style": "new-york", "rsc": true, "tsx": true, "tailwind": { "config": "", "css": "styles/globals.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" }, "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" }, "iconLibrary": "lucide", "registries": { "@shark": "https://shark.vini.one/r/{name}.json" } } ``` If you're using `package.json#imports`, use the corresponding `#...` aliases instead: ```json title="components.json" showLineNumbers { "aliases": { "components": "#components", "utils": "#lib/utils", "ui": "#components/ui", "lib": "#lib", "hooks": "#hooks" } } ``` ## Adding components [#adding-components] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` # Next.js (/docs/installation/next) ## Use the Shark Preset [#use-the-shark-preset] ### Create Project [#create-project] Run the `init` command with the Shark preset and the Next.js template: ```bash npx shadcn@latest init @shark/style -t next ``` ### Add Components [#add-components] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="app/page.tsx" showLineNumbers import { Button } from "@/components/ui/button"; export default function Home() { return (
); } ```
## Use the CLI [#use-the-cli] ### Create Project [#create-project-1] Run the `init` command to scaffold a new Next.js project and configure Shark UI: ```bash npx shadcn@latest init @shark/style -t next ``` ### Add Components [#add-components-1] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="app/page.tsx" showLineNumbers import { Button } from "@/components/ui/button"; export default function Home() { return (
); } ```
## Existing Project [#existing-project] ### Create Project [#create-project-2] If you need a new Next.js project, create one with `create-next-app`. Otherwise, skip this step. ```bash npx create-next-app@latest ``` Choose the recommended defaults so Tailwind CSS, the App Router, and the default `@/*` import alias are configured for you. If you prefer a `src/` directory, use `--src-dir` or choose `Yes` when prompted: ```bash npx create-next-app@latest --src-dir ``` With `--src-dir`, Next.js places your app in `src/app` and configures the `@/*` alias to point to `./src/*`. ### Configure Tailwind CSS and Import Aliases [#configure-tailwind-css-and-import-aliases] If you created your project with the recommended `create-next-app` defaults, you can skip this step. If you're adding Shark UI to an older or custom Next.js app, make sure Tailwind CSS is installed first. You can follow the official [Next.js installation guide](https://nextjs.org/docs/app/getting-started). Then make sure your `tsconfig.json` includes the `@/*` import alias: ```json title="tsconfig.json" showLineNumbers { "compilerOptions": { "paths": { "@/*": ["./*"] } } } ``` If you used `--src-dir`, point the alias to `./src/*` instead. ### Run the CLI [#run-the-cli] Run the `shadcn` init command with the Shark preset to set up your project. ```bash npx shadcn@latest init @shark/style ``` ### Add Components [#add-components-2] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="app/page.tsx" showLineNumbers import { Button } from "@/components/ui/button"; export default function Home() { return (
); } ``` If you used `--src-dir`, add the component to `src/app/page.tsx` instead.
# React Router (/docs/installation/react-router) ## Use the Shark Preset [#use-the-shark-preset] ### Create Project [#create-project] ```bash npx shadcn@latest init @shark/style -t react-router ``` ### Add Components [#add-components] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="app/routes/home.tsx" showLineNumbers import { Button } from "~/components/ui/button"; import type { Route } from "./+types/home"; export const meta = ({}: Route.MetaArgs) => { return [ { title: "New React Router App" }, { name: "description", content: "Welcome to React Router!" }, ]; }; export default function Home() { return (
); } ```
## Use the CLI [#use-the-cli] ### Create Project [#create-project-1] Run the `init` command to scaffold a new React Router project and configure Shark UI: ```bash npx shadcn@latest init @shark/style -t react-router ``` For a monorepo project, use the `--monorepo` flag: ```bash npx shadcn@latest init @shark/style -t react-router --monorepo ``` ### Add Components [#add-components-1] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root: ```bash npx shadcn@latest add @shark/button -c apps/web ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="app/routes/home.tsx" showLineNumbers import { Button } from "~/components/ui/button"; import type { Route } from "./+types/home"; export const meta = ({}: Route.MetaArgs) => { return [ { title: "New React Router App" }, { name: "description", content: "Welcome to React Router!" }, ]; }; export default function Home() { return (
); } ``` If you created a monorepo, update `apps/web/app/routes/home.tsx` and import from your workspace UI package instead.
## Existing Project [#existing-project] ### Create Project [#create-project-2] If you need a new React Router project, create one first. Otherwise, skip this step. ```bash npx create-react-router@latest my-app ``` ### Run the CLI [#run-the-cli] Run the `shadcn` init command with the Shark preset to set up your project. ```bash npx shadcn@latest init @shark/style ``` ### Add Components [#add-components-2] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="app/routes/home.tsx" showLineNumbers import { Button } from "~/components/ui/button"; import type { Route } from "./+types/home"; export const meta = ({}: Route.MetaArgs) => { return [ { title: "New React Router App" }, { name: "description", content: "Welcome to React Router!" }, ]; }; export default function Home() { return (
); } ```
# TanStack Start (/docs/installation/tanstack-start) ## Use the Shark Preset [#use-the-shark-preset] ### Create Project [#create-project] Run the `init` command with the Shark preset and the TanStack Start template: ```bash npx shadcn@latest init @shark/style -t start ``` ### Add Components [#add-components] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="src/routes/index.tsx" showLineNumbers import { createFileRoute } from "@tanstack/react-router"; import { Button } from "@/components/ui/button"; export const Route = createFileRoute("/")({ component: App, }); function App() { return (
); } ```
## Use the CLI [#use-the-cli] ### Create Project [#create-project-1] Run the `init` command to scaffold a new TanStack Start project and configure Shark UI: ```bash npx shadcn@latest init @shark/style -t start ``` For a monorepo project, use the `--monorepo` flag: ```bash npx shadcn@latest init @shark/style -t start --monorepo ``` ### Add Components [#add-components-1] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root: ```bash npx shadcn@latest add @shark/button -c apps/web ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="src/routes/index.tsx" showLineNumbers import { createFileRoute } from "@tanstack/react-router"; import { Button } from "@/components/ui/button"; export const Route = createFileRoute("/")({ component: App, }); function App() { return (
); } ``` If you created a monorepo, update `apps/web/src/routes/index.tsx` and import from your workspace UI package instead.
## Existing Project [#existing-project] ### Create Project [#create-project-2] If you need a new TanStack Start project, create one first. Otherwise, skip this step. ```bash npx @tanstack/cli@latest create ``` Choose TanStack Start, the React framework, and the recommended defaults so Tailwind CSS and the `@/*` import alias are configured for you. Do not add the `shadcn` add-on when prompted. The `shadcn` CLI will configure Shark UI later in this guide. The TanStack CLI already configures Tailwind CSS and the default `@/*` import alias for you. If you're adding Shark UI to an older or custom TanStack Start app, make sure both are configured before continuing. ### Run the CLI [#run-the-cli] Run the `shadcn` init command with the Shark preset to set up your project. ```bash npx shadcn@latest init @shark/style ``` ### Add Components [#add-components-2] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="src/routes/index.tsx" showLineNumbers import { createFileRoute } from "@tanstack/react-router"; import { Button } from "@/components/ui/button"; export const Route = createFileRoute("/")({ component: App, }); function App() { return (
); } ```
# Vite (/docs/installation/vite) ## Use the Shark Preset [#use-the-shark-preset] ### Create Project [#create-project] Run the `init` command with the Shark preset and the Vite template: ```bash npx shadcn@latest init @shark/style -t vite ``` ### Add Components [#add-components] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="src/App.tsx" showLineNumbers import { Button } from "@/components/ui/button"; function App() { return (
); } export default App; ```
## Use the CLI [#use-the-cli] ### Create Project [#create-project-1] Run the `init` command to scaffold a new Vite project and configure Shark UI: ```bash npx shadcn@latest init @shark/style -t vite ``` For a monorepo project, use the `--monorepo` flag: ```bash npx shadcn@latest init @shark/style -t vite --monorepo ``` ### Add Components [#add-components-1] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root: ```bash npx shadcn@latest add @shark/button -c apps/web ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="src/App.tsx" showLineNumbers import { Button } from "@/components/ui/button"; function App() { return (
); } export default App; ``` If you created a monorepo, update `apps/web/src/App.tsx` and import from your workspace UI package instead.
## Existing Project [#existing-project] ### Create Project [#create-project-2] If you need a new Vite project, create one first and select the **React + TypeScript** template. Otherwise, skip this step. ```bash npm create vite@latest ``` ### Add Tailwind CSS [#add-tailwind-css] If your project already has Tailwind CSS configured, skip this step. ```bash npm install tailwindcss @tailwindcss/vite ``` Replace everything in `src/index.css` with the following: ```css title="src/index.css" @import "tailwindcss"; ``` ### Edit tsconfig.json [#edit-tsconfigjson] Vite splits TypeScript config across multiple files. Add `baseUrl` and `paths` to the `compilerOptions` in both `tsconfig.json` and `tsconfig.app.json`: ```ts title="tsconfig.json" showLineNumbers { "files": [], "references": [ { "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" } ], "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } } ``` ### Edit tsconfig.app.json [#edit-tsconfigappjson] Add the same path resolution so your IDE resolves imports correctly: ```ts title="tsconfig.app.json" showLineNumbers { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } } ``` ### Update vite.config.ts [#update-viteconfigts] Add the path alias so Vite resolves `@/` at build time: ```bash npm install -D @types/node ``` ```typescript title="vite.config.ts" showLineNumbers import path from "path" import tailwindcss from "@tailwindcss/vite" import react from "@vitejs/plugin-react" import { defineConfig } from "vite" export default defineConfig({ plugins: [react(), tailwindcss()], resolve: { alias: { "@": path.resolve(__dirname, "./src"), }, }, }) ``` ### Run the CLI [#run-the-cli] Run the `shadcn` init command with the Shark preset to set up your project. ```bash npx shadcn@latest init @shark/style ``` ### Add Components [#add-components-2] You can add components with the CLI or copy them manually from the component docs: * **CLI**: Run `npx shadcn@latest add @shark/` (e.g. `button`, `dialog`). * **Manual**: Copy component source from Manual tab in the component docs. For example, add the `Button` component to your project: ```bash npx shadcn@latest add @shark/button ``` You can also install every component at once: ```bash npx shadcn@latest add @shark/ui ``` Then import and use components like this: ```tsx title="src/App.tsx" showLineNumbers import { Button } from "@/components/ui/button"; function App() { return (
); } export default App; ```
# Client Only (/docs/utilities/client-only) ## Installation [#installation] CLI Manual ```bash npx shadcn@latest add @shark/client-only ``` Install the following dependencies: ```bash npm install @ark-ui/react ``` Copy and paste the following code into your project. Update the import paths to match your project setup. ## Usage [#usage] ```tsx import { ClientOnly } from "@/registry/react/components/client-only"; ``` ```tsx
This content only renders on the client.
``` ## Examples [#examples] ### With fallback [#with-fallback] Pass `fallback` to show content while the client-only content is loading: ## API Reference [#api-reference] ### ClientOnly [#clientonly] Shows children only on the client. Useful for hydration-safe client components. | Prop | Type | Default | | ---------- | ----------- | ------- | | `fallback` | `ReactNode` | - | *** For a complete list of props, see the [Ark UI documentation](https://ark-ui.com/docs/utilities/client-only#api-reference). # Download Trigger (/docs/utilities/download-trigger) ## Installation [#installation] CLI Manual ```bash npx shadcn@latest add @shark/download-trigger ``` Install the following dependencies: ```bash npm install @ark-ui/react ``` Copy and paste the following code into your project. Update the import paths to match your project setup. ## Usage [#usage] ```tsx import { DownloadTrigger } from "@/registry/react/components/download-trigger"; ``` ```tsx Download ``` ## Examples [#examples] ### Download SVG [#download-svg] Download an SVG file by passing the SVG markup to `data` and setting `mimeType` to `image/svg+xml`. ### Promise [#promise] Trigger downloads from a promise that returns a `Blob`, `File`, or `string`. Pass a function to `data`. ## API Reference [#api-reference] ### DownloadTrigger [#downloadtrigger] | Prop | Type | Default | | ---------- | ------------------------------------------------------------ | ------- | | `data` | `DownloadableData \| (() => MaybePromise)` | - | | `fileName` | `string` | - | | `mimeType` | `FileMimeType` | - | | `asChild` | `boolean` | - | *** For a complete list of props, see the [Ark UI documentation](https://ark-ui.com/docs/utilities/download-trigger#api-reference). # Format (/docs/utilities/format) ## Installation [#installation] CLI Manual ```bash npx shadcn@latest add @shark/format ``` Install the following dependencies: ```bash npm install @ark-ui/react ``` Copy and paste the following code into your project. Update the import paths to match your project setup. ## Usage [#usage] ```tsx import { FormatByte, FormatNumber, FormatRelativeTime } from "@/registry/react/components/format"; ``` ```tsx ``` ## Examples [#examples] ### Format Byte [#format-byte] Format byte values as file sizes. #### Unit display [#unit-display] Use the `unitDisplay` prop to control how the unit is displayed. #### Unit system [#unit-system] Use `unitSystem` to choose between decimal (1000 bytes) or binary (1024 bytes). ### Format Relative Time [#format-relative-time] Format dates as relative time. #### Style [#style] Use the `style` prop for long, short, or narrow format. ### Format Number [#format-number] Format numbers with locale-aware options. #### Currency [#currency] Use `style="currency"` with the `currency` prop for currency formatting. #### Percentage [#percentage] Use `style="percent"` to format numbers as percentages. #### Compact notation [#compact-notation] Use `notation="compact"` for compact display. ## API Reference [#api-reference] ### FormatByte [#formatbyte] | Prop | Type | Default | | ------------- | ----------------------------------- | -------- | | `value` | `number` | - | | `unit` | `"byte"` \| `"bit"` | `"byte"` | | `unitDisplay` | `"long"` \| `"short"` \| `"narrow"` | - | | `unitSystem` | `"decimal"` \| `"binary"` | - | | `locale` | `string` | - | ### FormatRelativeTime [#formatrelativetime] | Prop | Type | Default | | --------- | ----------------------------------- | ------- | | `value` | `Date` \| `number` | - | | `numeric` | `"always"` \| `"auto"` | - | | `style` | `"long"` \| `"short"` \| `"narrow"` | - | | `locale` | `string` | - | ### FormatNumber [#formatnumber] | Prop | Type | Default | | ----------------------- | ---------------------------------------------------------------- | ------------ | | `value` | `number` | - | | `locale` | `string` | - | | `style` | `"decimal"` \| `"percent"` \| `"currency"` \| `"unit"` | `"decimal"` | | `currency` | `string` | - | | `unit` | `string` | - | | `notation` | `"standard"` \| `"compact"` \| `"scientific"` \| `"engineering"` | `"standard"` | | `minimumFractionDigits` | `number` | - | | `maximumFractionDigits` | `number` | - | *** For a complete list of props, see the [Ark UI documentation](https://ark-ui.com/docs/components/format#api-reference). # Highlight (/docs/utilities/highlight) ## Installation [#installation] CLI Manual ```bash npx shadcn@latest add @shark/highlight ``` Install the following dependencies: ```bash npm install @ark-ui/react ``` Copy and paste the following code into your project. Update the import paths to match your project setup. ## Usage [#usage] ```tsx import { Highlight } from "@/registry/react/components/highlight"; ``` ```tsx ``` ## Examples [#examples] ### Multiple [#multiple] Pass an array of strings to the `query` prop to highlight multiple substrings. ### Search Query [#search-query] Use the Highlight component to highlight search query results. ### With Squiggle [#with-squiggle] Use a custom decoration like a wavy underline for a fancier highlight effect. ### Custom Style [#custom-style] Use the `className` prop to customize the style of the highlighted text. ## API Reference [#api-reference] ### Highlight [#highlight] | Prop | Type | Default | | ------------ | -------------------- | ------------ | | `query` | `string \| string[]` | **required** | | `text` | `string` | **required** | | `ignoreCase` | `boolean` | `false` | | `exactMatch` | `boolean` | `false` | | `className` | `string` | `""` | *** For a complete list of props, see the [Ark UI documentation](https://ark-ui.com/docs/utilities/highlight#api-reference). # Hitbox (/docs/utilities/hitbox) Kudos to [Kian Bazza](https://bazza.dev/craft/2026/hit-area) for the original implementation. ## Installation [#installation] CLI Manual ```bash npx shadcn@latest add @shark/hitbox ``` Import the following semantic color variables into your CSS file when using `hitbox-debug` ```css @theme inline { --color-info: var(--info); --color-success: var(--success); } :root { --info: var(--color-blue-500); --success: var(--color-emerald-500); } .dark { --info: var(--color-blue-500); --success: var(--color-emerald-500); } ``` Import the following CSS rules into your `globals.css` ```css title="globals.css" showLineNumbers @utility hitbox-debug { position: relative; &::before { content: ""; position: absolute; top: var(--hitbox-t, 0px); right: var(--hitbox-r, 0px); bottom: var(--hitbox-b, 0px); left: var(--hitbox-l, 0px); pointer-events: inherit; @apply border border-dashed border-info bg-info/10; } &:hover::before { @apply border border-dashed border-success bg-success/10; } } @utility hitbox { position: relative; &::before { content: ""; position: absolute; top: var(--hitbox-t, 0px); right: var(--hitbox-r, 0px); bottom: var(--hitbox-b, 0px); left: var(--hitbox-l, 0px); pointer-events: inherit; } } @utility hitbox-* { position: relative; --hitbox-t: calc(-1 * --spacing(--value(number, [*]))); --hitbox-b: calc(-1 * --spacing(--value(number, [*]))); --hitbox-l: calc(-1 * --spacing(--value(number, [*]))); --hitbox-r: calc(-1 * --spacing(--value(number, [*]))); &::before { content: ""; position: absolute; top: var(--hitbox-t, 0px); right: var(--hitbox-r, 0px); bottom: var(--hitbox-b, 0px); left: var(--hitbox-l, 0px); pointer-events: inherit; } } @utility hitbox-l-* { position: relative; --hitbox-l: calc(-1 * --spacing(--value(number, [*]))); &::before { content: ""; position: absolute; top: var(--hitbox-t, 0px); right: var(--hitbox-r, 0px); bottom: var(--hitbox-b, 0px); left: var(--hitbox-l, 0px); pointer-events: inherit; } } @utility hitbox-r-* { position: relative; --hitbox-r: calc(-1 * --spacing(--value(number, [*]))); &::before { content: ""; position: absolute; top: var(--hitbox-t, 0px); right: var(--hitbox-r, 0px); bottom: var(--hitbox-b, 0px); left: var(--hitbox-l, 0px); pointer-events: inherit; } } @utility hitbox-t-* { position: relative; --hitbox-t: calc(-1 * --spacing(--value(number, [*]))); &::before { content: ""; position: absolute; top: var(--hitbox-t, 0px); right: var(--hitbox-r, 0px); bottom: var(--hitbox-b, 0px); left: var(--hitbox-l, 0px); pointer-events: inherit; } } @utility hitbox-b-* { position: relative; --hitbox-b: calc(-1 * --spacing(--value(number, [*]))); &::before { content: ""; position: absolute; top: var(--hitbox-t, 0px); right: var(--hitbox-r, 0px); bottom: var(--hitbox-b, 0px); left: var(--hitbox-l, 0px); pointer-events: inherit; } } @utility hitbox-x-* { position: relative; --hitbox-l: calc(-1 * --spacing(--value(number, [*]))); --hitbox-r: calc(-1 * --spacing(--value(number, [*]))); &::before { content: ""; position: absolute; top: var(--hitbox-t, 0px); right: var(--hitbox-r, 0px); bottom: var(--hitbox-b, 0px); left: var(--hitbox-l, 0px); pointer-events: inherit; } } @utility hitbox-y-* { position: relative; --hitbox-t: calc(-1 * --spacing(--value(number, [*]))); --hitbox-b: calc(-1 * --spacing(--value(number, [*]))); &::before { content: ""; position: absolute; top: var(--hitbox-t, 0px); right: var(--hitbox-r, 0px); bottom: var(--hitbox-b, 0px); left: var(--hitbox-l, 0px); pointer-events: inherit; } } ``` Update the import paths to match your project setup. ## Usage [#usage] ```tsx Link ``` ## Examples [#examples] ### Basic [#basic] Use `hitbox-*` to extend the hit area uniformly on all sides. ### Individual sides [#individual-sides] Target specific sides with `hitbox-l-*`, `hitbox-r-*`, `hitbox-t-*`, and `hitbox-b-*`. ### Horizontal and vertical [#horizontal-and-vertical] Use `hitbox-x-*` and `hitbox-y-*` for axis shorthands. ### Custom values [#custom-values] Use arbitrary values with bracket syntax. ### Debugging [#debugging] Add `hitbox-debug` to visualize the expanded hit area. ### Sidebar navigation [#sidebar-navigation] Use `hitbox-y-*` so adjacent items feel continuous. ## API Reference [#api-reference] | Class | Expansion | | -------------- | -------------------------------- | | `hitbox` | Base (no expansion) | | `hitbox-*` | All sides (spacing or `[value]`) | | `hitbox-l-*` | Left | | `hitbox-r-*` | Right | | `hitbox-t-*` | Top | | `hitbox-b-*` | Bottom | | `hitbox-x-*` | Left and right | | `hitbox-y-*` | Top and bottom | | `hitbox-debug` | Debug overlay | # JSON Tree View (/docs/utilities/json-tree-view) ## Installation [#installation] CLI Manual ```bash npx shadcn@latest add @shark/json-tree-view ``` Install the following dependencies: ```bash npm install @ark-ui/react lucide-react ``` Import the following variables into your CSS file ```css @theme inline { --color-destructive-foreground: var(--destructive-foreground); --color-info: var(--info); --color-info-foreground: var(--info-foreground); --color-success: var(--success); --color-success-foreground: var(--success-foreground); --color-warning: var(--warning); --color-warning-foreground: var(--warning-foreground); } :root { --destructive-foreground: var(--color-red-700); --info: var(--color-blue-500); --info-foreground: var(--color-blue-700); --success: var(--color-emerald-500); --success-foreground: var(--color-emerald-700); --warning: var(--color-amber-500); --warning-foreground: var(--color-amber-700); } .dark { --destructive-foreground: var(--color-red-400); --info: var(--color-blue-500); --info-foreground: var(--color-blue-400); --success: var(--color-emerald-500); --success-foreground: var(--color-emerald-400); --warning: var(--color-amber-500); --warning-foreground: var(--color-amber-400); } ``` Copy and paste the following code into your project. Update the import paths to match your project setup. ## Usage [#usage] ```tsx import { JsonTreeView } from "@/registry/react/components/json-tree-view"; const data = { name: "John", age: 30, address: { city: "NYC" } }; ``` ## Examples [#examples] ### Different data types [#different-data-types] Display various JavaScript data types including objects, arrays, primitives, dates, and special values. ### Controlling expand level [#controlling-expand-level] Use the `defaultExpandedDepth` prop to control how many levels are expanded by default. ### Map and Set [#map-and-set] Native JavaScript Map and Set objects are supported. ## API Reference [#api-reference] ### JsonTreeView [#jsontreeview] | Prop | Type | Default | | ---------------------- | --------------------- | ------- | | `data` | `object` | - | | `defaultExpandedDepth` | `number` | - | | `renderValue` | `(node) => ReactNode` | - | *** For a complete list of props, see the [Ark UI documentation](https://ark-ui.com/docs/utilities/json-tree-view#api-reference). # Presence (/docs/utilities/presence) ## Installation [#installation] CLI Manual ```bash npx shadcn@latest add @shark/presence ``` Install the following dependencies: ```bash npm install @ark-ui/react ``` Copy and paste the following code into your project. Update the import paths to match your project setup. ## Usage [#usage] ```tsx import React from "react"; import { Presence } from "@/registry/react/components/presence"; const [visible, setVisible] = React.useState(false); Content that animates in and out ``` ## Lazy [#lazy] Setting `lazyMount` and `unmountOnExit` to `true` lazy mounts and unmounts the content. It will remove the element from the DOM when it is not present. ```tsx showLineNumbers {/** content */} ``` ## States [#states] Presence automatically manages the attribute `data-state` to `open` and `closed`. This enables styling and animations based on visibility state. ```tsx showLineNumbers //
//
``` ## API Reference [#api-reference] ### Presence [#presence] | Prop | Type | Default | | --------------- | --------- | ------- | | `present` | `boolean` | `false` | | `unmountOnExit` | `boolean` | `true` | | `lazyMount` | `boolean` | `true` | | `asChild` | `boolean` | `false` | *** For a complete list of props, see the [Ark UI documentation](https://ark-ui.com/docs/utilities/presence#api-reference). # Show (/docs/utilities/show) ## Installation [#installation] CLI Manual ```bash npx shadcn@latest add @shark/show ``` Copy and paste the following code into your project. Update the import paths to match your project setup. ## Usage [#usage] ```tsx import { Show } from "@/registry/react/components/show"; ``` ```tsx }> {/** content */} ``` ## API Reference [#api-reference] ### Show [#show] | Prop | Type | Default | | ---------- | ----------------- | -------- | | `when` | `boolean` | required | | `fallback` | `React.ReactNode` | - | | `children` | `React.ReactNode` | required | # Swap (/docs/utilities/swap) ## Installation [#installation] CLI Manual ```bash npx shadcn@latest add @shark/swap ``` Install the following dependencies: ```bash npm install @ark-ui/react tailwind-variants ``` Add the following keyframes to your `globals.css` for the flip variant: ```css title="globals.css" @theme inline { --animate-flip-in: flip-in 0.2s ease-out; --animate-flip-out: flip-out 0.2s ease-out; @keyframes flip-in { from { transform: rotateY(180deg); } to { transform: rotateY(0deg); } } @keyframes flip-out { from { transform: rotateY(0deg); } to { transform: rotateY(180deg); } } } ``` Copy and paste the following code into your project. Update the import paths to match your project setup. ## Usage [#usage] ```tsx import { Swap, SwapIndicator } from "@/registry/react/components/swap"; ``` ```tsx ``` ## Examples [#examples] ### Fade [#fade] ### Flip [#flip] ### Rotate [#rotate] ### Scale [#scale] ### Blur [#blur] ## API Reference [#api-reference] ### Swap [#swap] | Prop | Type | Default | | --------------- | --------------------------------------------------- | -------- | | `variant` | `"fade" \| "scale" \| "flip" \| "rotate" \| "blur"` | `"fade"` | | `swap` | `boolean` | `-` | | `lazyMount` | `boolean` | `true` | | `unmountOnExit` | `boolean` | `true` | | `className` | `string` | `-` | | `asChild` | `boolean` | `-` | ### SwapIndicator [#swapindicator] | Prop | Type | Default | | ----------- | --------------- | ------------ | | `type` | `'on' \| 'off'` | **required** | | `className` | `string` | `-` | | `asChild` | `boolean` | `-` | *** For a complete list of props, see the [Ark UI documentation](https://ark-ui.com/docs/utilities/swap#api-reference). # Accordion - Examples and Patterns Examples for Accordion component. ## Example: card ```tsx import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; const AccordionCardDemo = () => ( Product Information Common questions about our products, shipping, and returns. Product Information

Our flagship product combines cutting-edge technology with sleek design. Built with premium materials, it offers unparalleled performance and reliability.

Shipping Details

We offer worldwide shipping through trusted courier partners. Standard delivery takes 3-5 business days, while express shipping ensures delivery within 1-2 business days.

Return Policy

We stand behind our products with a comprehensive 30-day return policy. If you're not completely satisfied, simply return the item in its original condition.

); export default AccordionCardDemo; ``` ## Example: controlled ```tsx "use client"; import React from "react"; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; const Example = () => { const [value, setValue] = React.useState(["item-1"]); return (
setValue(value)} value={value}> Product Information

Our flagship product combines cutting-edge technology with sleek design. Built with premium materials, it offers unparalleled performance and reliability.

Shipping Details

We offer worldwide shipping through trusted courier partners. Standard delivery takes 3-5 business days.

Return Policy

We stand behind our products with a comprehensive 30-day return policy. If you're not completely satisfied, simply return the item in its original condition.

{value}
); }; export default Example; ``` ## Example: default ```tsx import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; const AccordionDemo = () => ( Product Information

Our flagship product combines cutting-edge technology with sleek design. Built with premium materials, it offers unparalleled performance and reliability.

Key features include advanced processing capabilities, and an intuitive user interface designed for both beginners and experts.

Shipping Details

We offer worldwide shipping through trusted courier partners. Standard delivery takes 3-5 business days, while express shipping ensures delivery within 1-2 business days.

All orders are carefully packaged and fully insured. Track your shipment in real-time through our dedicated tracking portal.

Return Policy

We stand behind our products with a comprehensive 30-day return policy. If you're not completely satisfied, simply return the item in its original condition.

Our hassle-free return process includes free return shipping and full refunds processed within 48 hours of receiving the returned item.

); export default AccordionDemo; ``` ## Example: disabled ```tsx import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; const Example = () => ( Product Information

Our flagship product combines cutting-edge technology with sleek design. Built with premium materials, it offers unparalleled performance and reliability.

Shipping Details

We offer worldwide shipping through trusted courier partners. Standard delivery takes 3-5 business days.

Return Policy

We stand behind our products with a comprehensive 30-day return policy. If you're not completely satisfied, simply return the item in its original condition.

); export default Example; ``` ## Example: multiple ```tsx import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; const Example = () => ( Product Information

Our flagship product combines cutting-edge technology with sleek design. Built with premium materials, it offers unparalleled performance and reliability.

Shipping Details

We offer worldwide shipping through trusted courier partners. Standard delivery takes 3-5 business days.

Return Policy

We stand behind our products with a comprehensive 30-day return policy. If you're not completely satisfied, simply return the item in its original condition.

); export default Example; ``` ## Example: non-collapsible ```tsx import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; const Example = () => ( Product Information

Our flagship product combines cutting-edge technology with sleek design. Built with premium materials, it offers unparalleled performance and reliability.

Shipping Details

We offer worldwide shipping through trusted courier partners. Standard delivery takes 3-5 business days.

Return Policy

We stand behind our products with a comprehensive 30-day return policy. If you're not completely satisfied, simply return the item in its original condition.

); export default Example; ``` # Action Bar - Examples and Patterns Examples for Action Bar component. ## Example: close-trigger ```tsx "use client"; import { ArchiveIcon, DownloadIcon, PencilIcon, Trash2Icon, XIcon, } from "lucide-react"; import React from "react"; import { ActionBar, ActionBarBody, ActionBarClose, ActionBarContent, ActionBarSeparator, ActionBarTrigger, ActionBarValue, } from "@/components/ui/action-bar"; import { Button } from "@/components/ui/button"; const Example = () => { const [isOpen, setIsOpen] = React.useState(false); return ( ); }; export default Example; ``` ## Example: controlled ```tsx "use client"; import { ArchiveIcon, DownloadIcon, PencilIcon, Trash2Icon, XIcon, } from "lucide-react"; import React from "react"; import { ActionBar, ActionBarBody, ActionBarClose, ActionBarContent, ActionBarSeparator, ActionBarValue, } from "@/components/ui/action-bar"; import { Button } from "@/components/ui/button"; const Example = () => { const [isOpen, setIsOpen] = React.useState(false); return ( ); }; export default Example; ``` ## Example: custom-spacing ```tsx "use client"; import { PencilIcon, Trash2Icon, XIcon } from "lucide-react"; import React from "react"; import { ActionBar, ActionBarBody, ActionBarClose, ActionBarContent, ActionBarSeparator, ActionBarTrigger, ActionBarValue, } from "@/components/ui/action-bar"; import { Button } from "@/components/ui/button"; const Example = () => { const [isOpen, setIsOpen] = React.useState(false); return ( ); }; export default Example; ``` ## Example: default ```tsx import { ArchiveIcon, DownloadIcon, PencilIcon, Trash2Icon, XIcon, } from "lucide-react"; import { ActionBar, ActionBarBody, ActionBarClose, ActionBarContent, ActionBarSeparator, ActionBarTrigger, ActionBarValue, } from "@/components/ui/action-bar"; import { Button } from "@/components/ui/button"; const ActionBarDemo = () => ( ); export default ActionBarDemo; ``` ## Example: dialog ```tsx import { Trash2Icon, XIcon } from "lucide-react"; import { ActionBar, ActionBarBody, ActionBarClose, ActionBarContent, ActionBarSeparator, ActionBarTrigger, ActionBarValue, } from "@/components/ui/action-bar"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogClose, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; import { Button } from "@/components/ui/button"; const Example = () => ( Cancel Delete ); export default Example; ``` ## Example: gutter ```tsx "use client"; import { ArchiveIcon, DownloadIcon, PencilIcon, Trash2Icon, XIcon, } from "lucide-react"; import React from "react"; import { ActionBar, ActionBarBody, ActionBarClose, ActionBarContent, ActionBarSeparator, ActionBarValue, } from "@/components/ui/action-bar"; import { Button } from "@/components/ui/button"; const gutters = ["24px", "32px"] as const; const Example = () => { const [isOpen, setIsOpen] = React.useState(false); const [gutter, setGutter] = React.useState<(typeof gutters)[number]>("24px"); return ( <>
{gutters.map((value) => ( ))}
); }; export default Example; ``` ## Example: menu ```tsx import { ArchiveIcon, CopyIcon, EllipsisIcon, Trash2Icon, XIcon, } from "lucide-react"; import { ActionBar, ActionBarBody, ActionBarClose, ActionBarContent, ActionBarSeparator, ActionBarTrigger, ActionBarValue, } from "@/components/ui/action-bar"; import { Button } from "@/components/ui/button"; import { Menu, MenuContent, MenuItem, MenuTrigger, } from "@/components/ui/menu"; const Example = () => ( Archive Duplicate Delete ); export default Example; ``` ## Example: positioning ```tsx "use client"; import { ArchiveIcon, DownloadIcon, PencilIcon, Trash2Icon, XIcon, } from "lucide-react"; import React from "react"; import { ActionBar, ActionBarBody, ActionBarClose, ActionBarContent, ActionBarSeparator, ActionBarValue, } from "@/components/ui/action-bar"; import { Button } from "@/components/ui/button"; type Placement = "bottom" | "bottom-start" | "bottom-end"; const Example = () => { const [isOpen, setIsOpen] = React.useState(false); const [placement, setPlacement] = React.useState("bottom"); const handleOpenChange = (nextPlacement: Placement) => { setIsOpen(true); setPlacement(nextPlacement); }; return ( <>
); }; export default Example; ``` ## Example: table ```tsx "use client"; import { ArchiveIcon, CopyIcon, EllipsisIcon, PencilIcon, SendIcon, Trash2Icon, XIcon, } from "lucide-react"; import React from "react"; import { ActionBar, ActionBarBody, ActionBarClose, ActionBarContent, ActionBarSeparator, ActionBarValue, } from "@/components/ui/action-bar"; import { AlertDialog, AlertDialogAction, AlertDialogBody, AlertDialogCancel, AlertDialogClose, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; import { Badge, type BadgeVariant } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Menu, MenuContent, MenuItem, MenuTrigger, } from "@/components/ui/menu"; import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; const Example = () => { const [selectedIds, setSelectedIds] = React.useState([]); const isOpen = selectedIds.length > 0; const allSelected = selectedIds.length > 0 && selectedIds.length === orders.length; const handleSelectAll = (checked: boolean | "indeterminate") => { if (checked) { setSelectedIds(orders.map((order) => order.id)); } else { setSelectedIds([]); } }; const handleSelectRow = (id: string, checked: boolean | "indeterminate") => { if (checked) { setSelectedIds((prev) => [...prev, id]); } else { setSelectedIds((prev) => prev.filter((item) => item !== id)); } }; const handleClose = () => { setSelectedIds([]); }; return (
!open && handleClose()} open={isOpen}> Orders with checkbox selection and action bar. handleSelectAll(checked)} /> ID Name Status Amount {orders.map((order) => { const isSelected = selectedIds.includes(order.id); return ( handleSelectRow(order.id, checked) } /> {order.id} {order.name} {order.status} {order.amount} ); })}
Archive Duplicate
    {selectedIds.map((id) => { const order = orders.find((order) => order.id === id); if (!order) { return null; } return (
  • {order.id} - {order.name}
  • ); })}
Cancel Delete
); }; export default Example; const orders = [ { id: "SO-01", name: "Macbook Pro 16", status: "progress", amount: "245,12 $", }, { id: "SO-02", name: "Apple Watch Series 9", status: "transit", amount: "122,18 $", }, { id: "SO-03", name: "AirPods Max", status: "pending", amount: "89,50 $", }, { id: "SO-04", name: "iPad Pro 13", status: "pending", amount: "310,00 $", }, { id: "SO-05", name: "iPhone 15 Pro Max", status: "transit", amount: "156,75 $", }, ]; const statusVariants: Record = { transit: "success", pending: "warning", progress: "info", }; ``` # Alert - Examples and Patterns Examples for Alert component. ## Example: custom-color ```tsx import { WandSparklesIcon } from "lucide-react"; import { Alert, AlertDescription, AlertTitle, } from "@/components/ui/alert"; const Example = () => ( Fancy alert, huh? This is a fancy alert with a custom color. ); export default Example; ``` ## Example: default ```tsx import { Alert, AlertDescription, AlertTitle, } from "@/components/ui/alert"; const AlertDemo = () => ( Heads up! You can add icons to alerts to provide visual context and improve user experience. ); export default AlertDemo; ``` ## Example: variant-default ```tsx import { CheckCheckIcon } from "lucide-react"; import { Alert, AlertDescription, AlertTitle, } from "@/components/ui/alert"; const Example = () => ( Deployment successful You can now start building your next great project. ); export default Example; ``` ## Example: variant-destructive ```tsx import { TriangleAlertIcon } from "lucide-react"; import { Alert, AlertDescription, AlertTitle, } from "@/components/ui/alert"; const Example = () => ( Session expired Your session has expired. Please log in again. ); export default Example; ``` ## Example: variant-info ```tsx import { HistoryIcon } from "lucide-react"; import { Alert, AlertDescription, AlertTitle, } from "@/components/ui/alert"; const Example = () => ( New update available A new update is available. Check it out now. ); export default Example; ``` ## Example: variant-success ```tsx import { CheckCircleIcon } from "lucide-react"; import { Alert, AlertDescription, AlertTitle, } from "@/components/ui/alert"; const Example = () => ( Payment successful Your payment has been processed successfully. You will receive a receipt in your email. ); export default Example; ``` ## Example: variant-warning ```tsx import { AlertTriangleIcon } from "lucide-react"; import { Alert, AlertDescription, AlertTitle, } from "@/components/ui/alert"; const Example = () => ( Storage almost full Your storage is almost full. Consider upgrading your plan to avoid losing data. ); export default Example; ``` ## Example: with-action ```tsx import { HistoryIcon } from "lucide-react"; import { Alert, AlertAction, AlertDescription, AlertTitle, } from "@/components/ui/alert"; import { Button } from "@/components/ui/button"; const Example = () => ( New update available Check it out now. ); export default Example; ``` ## Example: with-icon ```tsx import { SparklesIcon } from "lucide-react"; import { Alert, AlertDescription, AlertTitle, } from "@/components/ui/alert"; const Example = () => ( New Feature Available Icons can be added to alerts to provide visual context and improve user experience. ); export default Example; ``` # Alert Dialog - Examples and Patterns Examples for Alert Dialog component. ## Example: default ```tsx import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogClose, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; import { Button } from "@/components/ui/button"; const AlertDialogDemo = () => ( Don't allow Allow ); export default AlertDialogDemo; ``` ## Example: variant-destructive ```tsx import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogClose, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; import { Button } from "@/components/ui/button"; const Example = () => ( Cancel Delete project ); export default Example; ``` # Announcement - Examples and Patterns Examples for Announcement component. ## Example: default ```tsx import { Badge } from "@registry/react/components/badge"; import { Announcement, AnnouncementTitle, } from "@/components/ui/announcement"; const Example = () => ( Release v2.1.0 — Dark mode, faster builds, and 12 new components ); export default Example; ``` ## Example: variant-default ```tsx import { Badge } from "@registry/react/components/badge"; import { Announcement, AnnouncementTitle, } from "@/components/ui/announcement"; const Example = () => ( Release v2.1.0 — Dark mode, faster builds, and 12 new components ); export default Example; ``` ## Example: variant-destructive ```tsx import { Badge } from "@registry/react/components/badge"; import { TriangleAlertIcon } from "lucide-react"; import { Announcement, AnnouncementTitle, } from "@/components/ui/announcement"; const Example = () => ( Payment failed Your last invoice couldn't be processed. Update your billing info. ); export default Example; ``` ## Example: variant-info ```tsx import { Badge } from "@registry/react/components/badge"; import { Announcement, AnnouncementTitle, } from "@/components/ui/announcement"; const Example = () => ( Maintenance Scheduled downtime tonight 2–4 AM UTC. No action needed. ); export default Example; ``` ## Example: variant-success ```tsx import { Badge } from "@registry/react/components/badge"; import { ArrowUpRightIcon, CheckCircleIcon } from "lucide-react"; import Link from "next/link"; import { Announcement, AnnouncementTitle, } from "@/components/ui/announcement"; const Example = () => ( Deployed Production build completed in 2m 34s ); export default Example; ``` ## Example: variant-warning ```tsx import { Badge } from "@registry/react/components/badge"; import { TriangleAlertIcon } from "lucide-react"; import { Announcement, AnnouncementTitle, } from "@/components/ui/announcement"; const Example = () => ( Trial ending Your free trial expires in 3 days. Upgrade to keep access. ); export default Example; ``` ## Example: with-icon ```tsx import { Badge } from "@registry/react/components/badge"; import { SparklesIcon } from "lucide-react"; import { Announcement, AnnouncementTitle, } from "@/components/ui/announcement"; const Example = () => ( New features Dark mode and 12 new components available ); export default Example; ``` ## Example: with-link ```tsx import { Badge } from "@registry/react/components/badge"; import { ArrowUpRight } from "lucide-react"; import Link from "next/link"; import { Announcement, AnnouncementTitle, } from "@/components/ui/announcement"; const Example = () => ( Latest update New feature added ); export default Example; ``` ## Example: without-badge ```tsx import { ArrowUpRightIcon } from "lucide-react"; import { Announcement, AnnouncementTitle, } from "@/components/ui/announcement"; const Example = () => ( New features added, check the logs for more details. ); export default Example; ``` # Aspect Ratio - Examples and Patterns Examples for Aspect Ratio component. ## Example: default ```tsx import { AspectRatio } from "@/components/ui/aspect-ratio"; const AspectRatioDemo = () => (
1:1
); export default AspectRatioDemo; ``` ## Example: portrait ```tsx import { AspectRatio } from "@/components/ui/aspect-ratio"; const Example = () => (
9:16
); export default Example; ``` ## Example: responsive ```tsx import { AspectRatio } from "@/components/ui/aspect-ratio"; const Example = () => (
16:9 → 1:1
); export default Example; ``` ## Example: square ```tsx import { AspectRatio } from "@/components/ui/aspect-ratio"; const Example = () => (
1:1
); export default Example; ``` ## Example: video ```tsx import { AspectRatio } from "@/components/ui/aspect-ratio"; const Example = () => (
16:9
); export default Example; ``` # Autocomplete - Examples and Patterns Examples for Autocomplete component. ## Example: controlled ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import React from "react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; const Example = () => { const [value, setValue] = React.useState("banana"); const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return (
filter(inputValue)} onValueChange={(e) => setValue(e.value?.at(0))} value={value ? [value] : []} > {collection.items.map((item) => ( {item.label} ))}

Selected: {value ?? "(none)"}

); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, ]; export default Example; ``` ## Example: default ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Field, FieldLabel } from "@registry/react/components/field"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; const AutocompleteDemo = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( Search fruits filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, ]; export default AutocompleteDemo; ``` ## Example: disabled ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > No items found. {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, ]; export default Example; ``` ## Example: group ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteGroup, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, groupBy: (item) => item.continent, initialItems, }); return ( filter(inputValue)} > {collection.group().map(([continent, group]) => ( {group.map((item) => ( {item.label} ))} ))} ); }; const initialItems = [ { label: "Canada", value: "ca", continent: "North America" }, { label: "United States", value: "us", continent: "North America" }, { label: "Mexico", value: "mx", continent: "North America" }, { label: "United Kingdom", value: "uk", continent: "Europe" }, { label: "Germany", value: "de", continent: "Europe" }, { label: "France", value: "fr", continent: "Europe" }, { label: "Japan", value: "jp", continent: "Asia" }, { label: "South Korea", value: "kr", continent: "Asia" }, { label: "China", value: "cn", continent: "Asia" }, ]; export default Example; ``` ## Example: invalid ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, ]; export default Example; ``` ## Example: size-lg ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > No items found. {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, ]; export default Example; ``` ## Example: size-md ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, ]; export default Example; ``` ## Example: size-sm ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > No items found. {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, ]; export default Example; ``` ## Example: with-clear-button ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > No items found. {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, ]; export default Example; ``` ## Example: with-field ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; import { Field, FieldError, FieldHelper, FieldLabel, } from "@/components/ui/field"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( Country filter(inputValue)} required > {collection.items.map((item) => ( {item.label} ))} We'll use this for shipping estimates Please select a valid country ); }; const initialItems = [ { label: "Brazil", value: "br" }, { label: "Mexico", value: "mx" }, { label: "Ireland", value: "ie" }, ]; export default Example; ``` ## Example: with-start-icon ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { AppleIcon } from "lucide-react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; import { InputGroupAddon } from "@/components/ui/input-group"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, ]; export default Example; ``` ## Example: with-trigger ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Autocomplete, AutocompleteContent, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, } from "@/components/ui/autocomplete"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, ]; export default Example; ``` # Avatar - Examples and Patterns Examples for Avatar component. ## Example: badge-with-icon ```tsx import { PlusIcon } from "lucide-react"; import { Avatar, AvatarBadge, AvatarFallback, AvatarImage, } from "@/components/ui/avatar"; const Example = () => ( VV ); export default Example; ``` ## Example: custom-radius ```tsx import { Avatar, AvatarFallback, AvatarImage, } from "@/components/ui/avatar"; const Example = () => (
VV CN SA PV
); export default Example; ``` ## Example: default ```tsx import { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, } from "@/components/ui/avatar"; const AvatarDemo = () => (
VV CN VV SA PV +2
); export default AvatarDemo; ``` ## Example: fallback-icon ```tsx import { UserIcon } from "lucide-react"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; const Example = () => ( ); export default Example; ``` ## Example: group-count-icon ```tsx import { PlusIcon } from "lucide-react"; import { Avatar, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, } from "@/components/ui/avatar"; const Example = () => ( VV SA PV IA ); export default Example; ``` ## Example: group-count ```tsx import { Avatar, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, } from "@/components/ui/avatar"; const Example = () => ( VV SA PV IA +5 ); export default Example; ``` ## Example: group-popover ```tsx import { Avatar, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { Popover, PopoverBody, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; const Example = () => ( VV SA PV IA SC VC NJ RT TS ); export default Example; ``` ## Example: group ```tsx import { Avatar, AvatarFallback, AvatarGroup, AvatarImage, } from "@/components/ui/avatar"; const Example = () => ( VV SA PV IA ); export default Example; ``` ## Example: hover-card ```tsx import { Avatar, AvatarFallback, AvatarGroup, AvatarImage, } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { HoverCard, HoverCardContent, HoverCardTrigger, } from "@/components/ui/hover-card"; const Example = () => (
VV

Vinicius Vicentini

@vinihvc

VV

Shadcn

@shadcn

); export default Example; ``` ## Example: size-custom ```tsx import { Avatar, AvatarFallback, AvatarImage, } from "@/components/ui/avatar"; const Example = () => ( VV ); export default Example; ``` ## Example: size-lg ```tsx import { Avatar, AvatarFallback, AvatarImage, } from "@/components/ui/avatar"; const Example = () => ( VV ); export default Example; ``` ## Example: size-md ```tsx import { Avatar, AvatarFallback, AvatarImage, } from "@/components/ui/avatar"; const Example = () => ( VV ); export default Example; ``` ## Example: size-sm ```tsx import { Avatar, AvatarFallback, AvatarImage, } from "@/components/ui/avatar"; const Example = () => ( VV ); export default Example; ``` ## Example: with-status ```tsx import { Avatar, AvatarBadge, AvatarFallback, AvatarImage, } from "@/components/ui/avatar"; const Example = () => (
VV SA PV
); export default Example; ``` # Badge - Examples and Patterns Examples for Badge component. ## Example: custom-color ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => (
Indigo Pink Sky Purple
); export default Example; ``` ## Example: default ```tsx import { Star } from "lucide-react"; import { Badge } from "@/components/ui/badge"; const Example = () => ( Favorite ); export default Example; ``` ## Example: pill ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: size-lg ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: size-md ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: size-sm ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: variant-default ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: variant-destructive ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: variant-info ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: variant-outline ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: variant-secondary ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: variant-success ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: variant-warning ```tsx import { Badge } from "@/components/ui/badge"; const Example = () => Badge; export default Example; ``` ## Example: with-icon ```tsx import { StarIcon } from "lucide-react"; import { Badge } from "@/components/ui/badge"; const Example = () => ( Favorite ); export default Example; ``` ## Example: with-link ```tsx import { ArrowUpRightIcon, CirclePlusIcon } from "lucide-react"; import Link from "next/link"; import { Badge } from "@/components/ui/badge"; const Example = () => ( New components ); export default Example; ``` ## Example: with-spinner ```tsx import { Badge } from "@/components/ui/badge"; import { Spinner } from "@/components/ui/spinner"; const Example = () => (
Deleting Generating
); export default Example; ``` # Bottom Navigation - Examples and Patterns Examples for Bottom Navigation component. ## Example: default ```tsx import { BellIcon, HomeIcon, SearchIcon, UserIcon } from "lucide-react"; import { BottomNavigation, BottomNavigationItem, BottomNavigationItemIcon, BottomNavigationItemLabel, BottomNavigationList, } from "@/components/ui/bottom-navigation"; import { ScrollArea } from "@/components/ui/scroll-area"; const Example = () => (
Home Search News Profile
); export default Example; ``` ## Example: icon-only ```tsx import { BellIcon, HomeIcon, SearchIcon, UserIcon } from "lucide-react"; import { BottomNavigation, BottomNavigationItem, BottomNavigationItemIcon, BottomNavigationList, } from "@/components/ui/bottom-navigation"; import { ScrollArea } from "@/components/ui/scroll-area"; const Example = () => (
); export default Example; ``` ## Example: with-links ```tsx "use client"; import { BellIcon, HomeIcon, SearchIcon, UserIcon } from "lucide-react"; import Link from "next/link"; import { BottomNavigation, BottomNavigationItem, BottomNavigationItemIcon, BottomNavigationItemLabel, BottomNavigationList, } from "@/components/ui/bottom-navigation"; import { ScrollArea } from "@/components/ui/scroll-area"; const Example = () => (
Home Search News Profile
); export default Example; ``` # Breadcrumb - Examples and Patterns Examples for Breadcrumb component. ## Example: collapsed ```tsx import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumb"; const Example = () => ( Home Components Breadcrumb ); export default Example; ``` ## Example: custom-separator ```tsx import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumb"; const Example = () => ( Home / Documentation / Introduction ); export default Example; ``` ## Example: default ```tsx import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumb"; const Example = () => ( Home Components Breadcrumb ); export default Example; ``` ## Example: with-link ```tsx import Link from "next/link"; import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumb"; const Example = () => ( Docs Components Breadcrumb ); export default Example; ``` ## Example: with-menu ```tsx "use client"; import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumb"; import { Button } from "@/components/ui/button"; import { Menu, MenuContent, MenuItem, MenuTrigger, } from "@/components/ui/menu"; const Example = () => ( Home Documentation Components Hooks Products Breadcrumb ); export default Example; ``` # Button - Examples and Patterns Examples for Button component. ## Example: custom-color ```tsx import { Button } from "@/components/ui/button"; const Example = () => (
); export default Example; ``` ## Example: default ```tsx import { CirclePlusIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; const ButtonDemo = () => (
); export default ButtonDemo; ``` ## Example: disabled ```tsx import { SendIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; const Example = () => ( ); export default Example; ``` ## Example: hitbox ```tsx "use client"; import { Menu } from "lucide-react"; import React from "react"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { Field, FieldLabel } from "@/components/ui/field"; import { Switch } from "@/components/ui/switch"; const Example = () => { const [show, setShow] = React.useState(true); return (
setShow(checked)} /> Show hitbox
); }; export default Example; ``` ## Example: icon ```tsx import { StarIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; const Example = () => ( ); export default Example; ``` ## Example: loading ```tsx import { Button } from "@/components/ui/button"; const Example = () => ; export default Example; ``` ## Example: no-click-effect ```tsx import { Button } from "@/components/ui/button"; const Example = () => ; export default Example; ``` ## Example: pill ```tsx import { PlusIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; const Example = () => ( ); export default Example; ``` ## Example: size-lg ```tsx import { PlusIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; const Example = () => (
); export default Example; ``` ## Example: size-md ```tsx import { PlusIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; const Example = () => (
); export default Example; ``` ## Example: size-sm ```tsx import { PlusIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; const Example = () => (
); export default Example; ``` ## Example: size-xl ```tsx import { PlusIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; const Example = () => (
); export default Example; ``` ## Example: size-xs ```tsx import { PlusIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; const Example = () => (
); export default Example; ``` ## Example: state-as-child ```tsx import Link from "next/link"; import { Button } from "@/components/ui/button"; const Example = () => ( ); export default Example; ``` ## Example: variant-default ```tsx import { Button } from "@/components/ui/button"; const Example = () => ; export default Example; ``` ## Example: variant-destructive ```tsx import { Button } from "@/components/ui/button"; const Example = () => ; export default Example; ``` ## Example: variant-ghost ```tsx import { Button } from "@/components/ui/button"; const Example = () => ; export default Example; ``` ## Example: variant-link ```tsx import { Button } from "@/components/ui/button"; const Example = () => ; export default Example; ``` ## Example: variant-outline ```tsx import { Button } from "@/components/ui/button"; const Example = () => ; export default Example; ``` ## Example: variant-secondary ```tsx import { Button } from "@/components/ui/button"; const Example = () => ; export default Example; ``` ## Example: with-icon ```tsx import { DownloadIcon, ExternalLinkIcon, HeartIcon, PlusIcon, SettingsIcon, } from "lucide-react"; import { Button } from "@/components/ui/button"; const Example = () => (
); export default Example; ``` # Button Group - Examples and Patterns Examples for Button Group component. ## Example: default ```tsx import { ArrowLeftIcon, MoreHorizontalIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { ButtonGroup } from "@/components/ui/button-group"; const ButtonGroupDemo = () => ( ); export default ButtonGroupDemo; ``` ## Example: nested ```tsx import { BoldIcon, BracesIcon, ImagePlusIcon, ItalicIcon, UnderlineIcon, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { ButtonGroup } from "@/components/ui/button-group"; const Example = () => ( ); export default Example; ``` ## Example: orientation-horizontal ```tsx import { PlayIcon, SkipBackIcon, SkipForwardIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { ButtonGroup } from "@/components/ui/button-group"; const Example = () => ( ); export default Example; ``` ## Example: orientation-vertical ```tsx import { MinusIcon, PlusIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { ButtonGroup } from "@/components/ui/button-group"; const Example = () => ( ); export default Example; ``` ## Example: separator ```tsx import { MinusIcon, PlusIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { ButtonGroup, ButtonGroupSeparator, } from "@/components/ui/button-group"; const Example = () => ( ); export default Example; ``` ## Example: with-input ```tsx import { SearchIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { ButtonGroup } from "@/components/ui/button-group"; import { Input } from "@/components/ui/input"; const Example = () => ( ); export default Example; ``` ## Example: with-menu ```tsx import { BanIcon, BookmarkIcon, CloudDownloadIcon, MoreHorizontalIcon, Share2Icon, StarIcon, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { ButtonGroup } from "@/components/ui/button-group"; import { Menu, MenuContent, MenuGroup, MenuItem, MenuSeparator, MenuTrigger, } from "@/components/ui/menu"; const Example = () => ( Share Watch later Download Report ); export default Example; ``` ## Example: with-popover ```tsx import { ChevronDownIcon, GitForkIcon, PlusIcon } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { ButtonGroup } from "@/components/ui/button-group"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Separator } from "@/components/ui/separator"; const Example = () => (

Existing forks

You don't have any forks of this repository.

); export default Example; ``` # Calendar - Examples and Patterns Examples for Calendar component. ## Example: booked-dates ```tsx "use client"; import { getDay } from "date-fns"; import { Calendar, CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, } from "@/components/ui/calendar"; import { Card, CardContent } from "@/components/ui/card"; const Example = () => ( ); const isWeekend = (date: { year: number; month: number; day: number }) => { const dayOfWeek = getDay(new Date(date.year, date.month - 1, date.day)); return dayOfWeek === 0 || dayOfWeek === 6; }; export default Example; ``` ## Example: controlled ```tsx "use client"; import React from "react"; import { Calendar, CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, parseDate, } from "@/components/ui/calendar"; import { Card, CardContent } from "@/components/ui/card"; const Example = () => { const [value, setValue] = React.useState([parseDate(new Date(Date.now()))]); return (
setValue(value)} value={value} >

{value.map((date) => date.toString())}

); }; export default Example; ``` ## Example: custom-cell-size ```tsx import { Calendar, CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, } from "@/components/ui/calendar"; import { Card, CardContent } from "@/components/ui/card"; const Example = () => ( ); export default Example; ``` ## Example: default ```tsx import { Calendar, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarViewDate, CalendarWeekDays, } from "@/components/ui/calendar"; import { Card, CardContent } from "@/components/ui/card"; const CalendarDemo = () => ( ); export default CalendarDemo; ``` ## Example: fixed-weeks ```tsx import { Calendar, CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, } from "@/components/ui/calendar"; import { Card, CardContent } from "@/components/ui/card"; const Example = () => ( ); export default Example; ``` ## Example: min-max ```tsx "use client"; import { Calendar, CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, parseDate, } from "@/components/ui/calendar"; import { Card, CardContent } from "@/components/ui/card"; const Example = () => ( ); export default Example; ``` ## Example: month-year-selector ```tsx import { Calendar, CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, } from "@/components/ui/calendar"; import { Card, CardContent } from "@/components/ui/card"; const Example = () => ( ); export default Example; ``` ## Example: multiple-months ```tsx "use client"; import React from "react"; import { Calendar, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarTableNextMonth, CalendarViewControl, CalendarViewDate, CalendarWeekDays, parseDate, } from "@/components/ui/calendar"; import { Card, CardContent } from "@/components/ui/card"; const Example = () => { const [value, setValue] = React.useState([parseDate(new Date(Date.now()))]); return ( setValue(value)} selectionMode="range" value={value} >
); }; export default Example; ``` ## Example: presets ```tsx import { Button } from "@/components/ui/button"; import { Calendar, CalendarMonthSelect, CalendarNextTrigger, CalendarPresetTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, } from "@/components/ui/calendar"; import { Card, CardContent, CardFooter, } from "@/components/ui/card"; const Example = () => ( {presets.map((preset) => ( ))} ); const presets = [ { label: "Last 7 days", value: "last7Days" as const }, { label: "Last 14 days", value: "last14Days" as const }, { label: "Last 30 days", value: "last30Days" as const }, { label: "This month", value: "thisMonth" as const }, ]; export default Example; ``` ## Example: range ```tsx import { Calendar, CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, } from "@/components/ui/calendar"; import { Card, CardContent } from "@/components/ui/card"; const Example = () => ( ); export default Example; ``` ## Example: select-today ```tsx import { Calendar, CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarTodayTrigger, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, } from "@/components/ui/calendar"; import { Card, CardContent, CardFooter, } from "@/components/ui/card"; const Example = () => ( ); export default Example; ``` # Card - Examples and Patterns Examples for Card component. ## Example: custom-spacing ```tsx import { GoogleIcon } from "@/components/icons/google"; import { Button } from "@/components/ui/button"; import { Card, CardAction, CardContent, CardFooter, CardHeader, } from "@/components/ui/card"; import { Field, FieldLabel, FieldSet } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => (
Email
); export default Example; ``` ## Example: default ```tsx import { GoogleIcon } from "@/components/icons/google"; import { Button } from "@/components/ui/button"; import { Card, CardAction, CardContent, CardFooter, CardHeader, } from "@/components/ui/card"; import { Field, FieldLabel, FieldSet } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const CardDemo = () => (
Email
); export default CardDemo; ``` ## Example: icon ```tsx import { DollarSignIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardFooter, CardHeader, CardMedia, } from "@/components/ui/card"; const Example = () => (
          15OFF
        
); export default Example; ``` ## Example: product ```tsx import { Button } from "@/components/ui/button"; import { Card, CardFooter, CardHeader, CardMedia, } from "@/components/ui/card"; const Example = () => (
{/* Image hoes here */}
); export default Example; ``` # Carousel - Examples and Patterns Examples for Carousel component. ## Example: autoplay ```tsx import { Card, CardContent } from "@/components/ui/card"; import { Carousel, CarouselContent, CarouselControl, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const Example = () => { const slides = Array.from({ length: 8 }); return ( Previous Next {slides.map((_, index) => ( {index + 1} ))} ); }; export default Example; ``` ## Example: controlled ```tsx "use client"; import React from "react"; import { Card, CardContent } from "@/components/ui/card"; import { Carousel, CarouselContent, CarouselControl, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const Example = () => { const [page, setPage] = React.useState(0); const slides = Array.from({ length: 8 }); return (
setPage(page)} page={page} slideCount={slides.length} > Previous Next {slides.map((_, index) => ( {index + 1} ))}

Current page: {page + 1} of 5

); }; export default Example; ``` ## Example: default ```tsx import { Card, CardContent } from "@/components/ui/card"; import { Carousel, CarouselContent, CarouselControl, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const CarouselDemo = () => { const slides = Array.from({ length: 8 }); return ( Previous Next {slides.map((_, index) => ( {index + 1} ))} ); }; export default CarouselDemo; ``` ## Example: loop ```tsx import { Card, CardContent } from "@/components/ui/card"; import { Carousel, CarouselContent, CarouselControl, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const Example = () => { const slides = Array.from({ length: 4 }); return ( Previous Next {slides.map((_, index) => ( {index + 1} ))} ); }; export default Example; ``` ## Example: mouse-drag ```tsx import { Card, CardContent } from "@/components/ui/card"; import { Carousel, CarouselContent, CarouselControl, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const Example = () => { const slides = Array.from({ length: 8 }); return ( Previous Next {slides.map((_, index) => ( {index + 1} ))} ); }; export default Example; ``` ## Example: orientation-horizontal ```tsx import { Carousel, CarouselContent, CarouselControl, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const Example = () => { const slides = [ { src: "https://picsum.photos/seed/1/500/300", alt: "Nature landscape" }, { src: "https://picsum.photos/seed/2/500/300", alt: "City skyline" }, { src: "https://picsum.photos/seed/3/500/300", alt: "Mountain view" }, { src: "https://picsum.photos/seed/4/500/300", alt: "Ocean sunset" }, { src: "https://picsum.photos/seed/5/500/300", alt: "Forest path" }, ]; return ( Previous Next {slides.map((slide, index) => ( {slide.alt} ))} ); }; export default Example; ``` ## Example: orientation-vertical ```tsx import { Carousel, CarouselContent, CarouselControl, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const Example = () => { const slides = [ { src: "https://picsum.photos/seed/1/500/300", alt: "Nature landscape" }, { src: "https://picsum.photos/seed/2/500/300", alt: "City skyline" }, { src: "https://picsum.photos/seed/3/500/300", alt: "Mountain view" }, { src: "https://picsum.photos/seed/4/500/300", alt: "Ocean sunset" }, { src: "https://picsum.photos/seed/5/500/300", alt: "Forest path" }, ]; return ( Previous Next {slides.map((slide, index) => ( {slide.alt} ))} ); }; export default Example; ``` ## Example: slides-per-page ```tsx import { Card, CardContent } from "@/components/ui/card"; import { Carousel, CarouselContent, CarouselControl, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const Example = () => { const slides = Array.from({ length: 16 }); return ( Previous Next {slides.map((_, index) => ( {index + 1} ))} ); }; export default Example; ``` ## Example: spacing ```tsx import { Card, CardContent } from "@/components/ui/card"; import { Carousel, CarouselContent, CarouselControl, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const Example = () => { const slides = Array.from({ length: 8 }); return ( Previous Next {slides.map((_, index) => ( {index + 1} ))} ); }; export default Example; ``` ## Example: thumbnail-indicator-vertical ```tsx import { Carousel, CarouselContent, CarouselControl, CarouselIndicator, CarouselIndicatorGroup, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const Example = () => { const slides = [ { src: "https://picsum.photos/seed/1/500/300", alt: "Nature landscape" }, { src: "https://picsum.photos/seed/2/500/300", alt: "City skyline" }, { src: "https://picsum.photos/seed/3/500/300", alt: "Mountain view" }, { src: "https://picsum.photos/seed/4/500/300", alt: "Ocean sunset" }, { src: "https://picsum.photos/seed/5/500/300", alt: "Forest path" }, ]; return ( Previous Next {slides.map((slide, index) => ( {slide.alt} ))} {slides.map((slide) => ( {slide.alt} ))} ); }; export default Example; ``` ## Example: thumbnail-indicator ```tsx import { Carousel, CarouselContent, CarouselControl, CarouselIndicator, CarouselIndicatorGroup, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; const Example = () => { const slides = [ { src: "https://picsum.photos/seed/1/500/300", alt: "Nature landscape" }, { src: "https://picsum.photos/seed/2/500/300", alt: "City skyline" }, { src: "https://picsum.photos/seed/3/500/300", alt: "Mountain view" }, { src: "https://picsum.photos/seed/4/500/300", alt: "Ocean sunset" }, { src: "https://picsum.photos/seed/5/500/300", alt: "Forest path" }, ]; return ( Previous Next {slides.map((slide, index) => ( {slide.alt} ))} {slides.map((slide) => ( {slide.alt} ))} ); }; export default Example; ``` # Chart - Examples and Patterns Examples for Chart component. ## Example: default ```tsx "use client"; import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"; import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart"; const chartData = [ { month: "January", desktop: 186, mobile: 80 }, { month: "February", desktop: 305, mobile: 200 }, { month: "March", desktop: 237, mobile: 120 }, { month: "April", desktop: 73, mobile: 190 }, { month: "May", desktop: 209, mobile: 130 }, { month: "June", desktop: 214, mobile: 140 }, ]; const chartConfig = { desktop: { label: "Desktop", color: "#2563eb", }, mobile: { label: "Mobile", color: "#60a5fa", }, } satisfies ChartConfig; const ChartDemo = () => ( value.slice(0, 3)} tickLine={false} tickMargin={10} /> } /> ); export default ChartDemo; ``` # Checkbox - Examples and Patterns Control for multiple selections in a set. ## Example: card ```tsx import { Checkbox } from "@/components/ui/checkbox"; import { Field, FieldContent, FieldDescription, FieldLabel, FieldTitle, } from "@/components/ui/field"; const Example = () => ( Enable notifications You can enable or disable notifications at any time. ); export default Example; ``` ## Example: checkbox-group ```tsx import { Checkbox, CheckboxGroup } from "@/components/ui/checkbox"; import { Field, FieldDescription, FieldGroup, FieldLabel, FieldLegend, FieldSet, } from "@/components/ui/field"; const Example = () => (
Show these items on the desktop: Select the items you want to show on the desktop. Hard disks External disks CDs, DVDs, and iPods Connected servers
); export default Example; ``` ## Example: controlled ```tsx "use client"; import type { CheckboxCheckedState } from "@ark-ui/react"; import React from "react"; import { Checkbox } from "@/components/ui/checkbox"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; const Example = () => { const [checked, setChecked] = React.useState(false); return ( setChecked(checked)} /> Accept terms and conditions

{checked ? "✅" : "❌"}

); }; export default Example; ``` ## Example: default ```tsx import { Checkbox } from "@/components/ui/checkbox"; import { Field, FieldContent, FieldDescription, FieldGroup, FieldLabel, } from "@/components/ui/field"; const CheckboxDemo = () => ( Accept terms and conditions Receive notifications You'll receive a notification when someone posts a comment Receive marketing emails ); export default CheckboxDemo; ``` ## Example: disabled ```tsx import { Checkbox } from "@/components/ui/checkbox"; import { Field, FieldLabel } from "@/components/ui/field"; const Example = () => ( Receive newsletter ); export default Example; ``` ## Example: indeterminate ```tsx import { Checkbox } from "@/components/ui/checkbox"; import { Field, FieldContent, FieldGroup, FieldLabel, } from "@/components/ui/field"; const Example = () => ( Select all items ); export default Example; ``` ## Example: invalid ```tsx import { Checkbox } from "@/components/ui/checkbox"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; const Example = () => ( Accept terms and conditions ); export default Example; ``` ## Example: with-description ```tsx import { Checkbox } from "@/components/ui/checkbox"; import { Field, FieldContent, FieldDescription, FieldGroup, FieldLabel, } from "@/components/ui/field"; const Example = () => ( Receive notifications You'll receive a notification when someone posts a comment on your post ); export default Example; ``` # Circular Progress - Examples and Patterns Examples for Circular Progress component. ## Example: controlled ```tsx "use client"; import { MinusIcon, PlusIcon } from "lucide-react"; import React from "react"; import { Button } from "@/components/ui/button"; import { ButtonGroup } from "@/components/ui/button-group"; import { CircularProgress } from "@/components/ui/circular-progress"; const Example = () => { const [value, setValue] = React.useState(55); return (
); }; export default Example; ``` ## Example: default ```tsx "use client"; import React from "react"; import { CircularProgress } from "@/components/ui/circular-progress"; const Example = () => { const [progress, setProgress] = React.useState(24); React.useEffect(() => { const timer = setTimeout(() => setProgress(72), 500); return () => clearTimeout(timer); }, []); return ; }; export default Example; ``` ## Example: indeterminate ```tsx import { CircularProgress } from "@/components/ui/circular-progress"; import { Field, FieldLabel } from "@/components/ui/field"; const Example = () => ( Establishing connection... ); export default Example; ``` ## Example: size ```tsx import { CircularProgress } from "@/components/ui/circular-progress"; const Example = () => (
); export default Example; ``` ## Example: thickness ```tsx import { CircularProgress } from "@/components/ui/circular-progress"; const Example = () => (
); export default Example; ``` ## Example: with-value ```tsx import { CircularProgress, CircularProgressValue, } from "@/components/ui/circular-progress"; const Example = () => ( ); export default Example; ``` # Circular Slider - Examples and Patterns Examples for Circular Slider component. ## Example: controlled ```tsx "use client"; import React from "react"; import { CircularSlider } from "@/components/ui/circular-slider"; const Example = () => { const [value, setValue] = React.useState(45); return (
More than: 180
setValue(e.value)} value={value} />
{value > 180 ? "✅" : "❌"}
); }; export default Example; ``` ## Example: custom-markers ```tsx "use client"; import { CircularSlider } from "@/components/ui/circular-slider"; function Example() { return ( ); } export default Example; ``` ## Example: default ```tsx import { CircularSlider, CircularSliderValue, } from "@/components/ui/circular-slider"; const CircularSliderDemo = () => ( ); export default CircularSliderDemo; ``` ## Example: disabled ```tsx import { CircularSlider } from "@/components/ui/circular-slider"; const Example = () => ( ); export default Example; ``` ## Example: size ```tsx import { CircularSlider } from "@/components/ui/circular-slider"; const Example = () => ( ); export default Example; ``` ## Example: step ```tsx import { CircularSlider } from "@/components/ui/circular-slider"; const Example = () => ( ); export default Example; ``` ## Example: thickness ```tsx import { CircularSlider } from "@/components/ui/circular-slider"; const Example = () => ( ); export default Example; ``` ## Example: with-markers ```tsx import { CircularSlider } from "@/components/ui/circular-slider"; const Example = () => ( ); export default Example; ``` ## Example: with-value ```tsx "use client"; import { Thermometer } from "lucide-react"; import { CircularSlider, CircularSliderValue, } from "@/components/ui/circular-slider"; function Example() { return ( } suffix="°" /> ); } export default Example; ``` # Client Only - Examples and Patterns Examples for Client Only component. ## Example: default ```tsx import { ClientOnly } from "@/components/ui/client-only"; const ClientOnlyDemo = () => (
This content is only rendered on the client side.
); export default ClientOnlyDemo; ``` ## Example: fallback ```tsx "use client"; import { ClientOnly } from "@/components/ui/client-only"; const Example = () => ( Loading…
} > ); const CurrentTime = () => { const now = new Date(); return (
Current time: {now.toLocaleTimeString()}
); }; export default Example; ``` # Clipboard - Examples and Patterns Examples for Clipboard component. ## Example: controlled ```tsx "use client"; import React from "react"; import { Button } from "@/components/ui/button"; import { Clipboard, ClipboardIndicator, ClipboardInput, ClipboardTrigger, } from "@/components/ui/clipboard"; const Example = () => { const [value, setValue] = React.useState("https://x.com/vinihvc"); return (
); }; export default Example; ``` ## Example: custom-timeout ```tsx import { Button } from "@/components/ui/button"; import { Clipboard, ClipboardIndicator, ClipboardInput, ClipboardTrigger, } from "@/components/ui/clipboard"; const Example = () => (
); export default Example; ``` ## Example: default ```tsx import { Button } from "@/components/ui/button"; import { Clipboard, ClipboardIndicator, ClipboardInput, ClipboardTrigger, } from "@/components/ui/clipboard"; const ClipboardDemo = () => (
); export default ClipboardDemo; ``` ## Example: different-icon ```tsx import { SparkleIcon, SparklesIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Clipboard, ClipboardIndicator, ClipboardTrigger, } from "@/components/ui/clipboard"; const Example = () => ( ); export default Example; ``` ## Example: icon-only ```tsx import { Button } from "@/components/ui/button"; import { Clipboard, ClipboardIndicator, ClipboardTrigger, } from "@/components/ui/clipboard"; const Example = () => ( ); export default Example; ``` ## Example: value-text ```tsx import { Button } from "@/components/ui/button"; import { Clipboard, ClipboardIndicator, ClipboardTrigger, ClipboardValue, } from "@/components/ui/clipboard"; const Example = () => ( ); export default Example; ``` # Collapsible - Examples and Patterns Examples for Collapsible component. ## Example: controlled ```tsx "use client"; import React from "react"; import { Button } from "@/components/ui/button"; import { Collapsible, CollapsibleContent, CollapsibleIndicator, CollapsibleTrigger, } from "@/components/ui/collapsible"; const Example = () => { const [open, setOpen] = React.useState(false); return (
setOpen(open)} open={open}>

This collapsible is controlled. The state is managed externally.

{open ? "✅" : "❌"}

); }; export default Example; ``` ## Example: default ```tsx import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardAction, CardDescription, CardHeader, } from "@/components/ui/card"; import { Collapsible, CollapsibleContent, CollapsibleIndicator, CollapsibleTrigger, } from "@/components/ui/collapsible"; const CollapsibleDemo = () => (
22.3% 10.1% 6.8% 1.4%
Google
22.3%
Facebook
-10.1%
TikTok
6.8%
Instagram
1.4%
); export default CollapsibleDemo; ``` ## Example: disabled ```tsx import { Button } from "@/components/ui/button"; import { Collapsible, CollapsibleContent, CollapsibleIndicator, CollapsibleTrigger, } from "@/components/ui/collapsible"; const Example = () => (

This content cannot be accessed because the collapsible is disabled.

); export default Example; ``` ## Example: nested ```tsx import { CopyButton } from "@/components/copy-button"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, } from "@/components/ui/card"; import { Collapsible, CollapsibleContent, CollapsibleIndicator, CollapsibleTrigger, } from "@/components/ui/collapsible"; const Example = () => (

Here you can find the documentation for all the components and how to use them.

Copy the following code:

                npm install @shark-ui

                
              
); export default Example; ``` ## Example: partial-collapse ```tsx import { Button } from "@/components/ui/button"; import { Collapsible, CollapsibleContent, CollapsibleIndicator, CollapsibleTrigger, } from "@/components/ui/collapsible"; const Example = () => (

This is the first paragraph of content. When collapsed, only a portion of this content will be visible.

This is the second paragraph. It will be hidden when the collapsible is in its collapsed state.

This is the third paragraph. Expand the collapsible to see all the content.

This is the fourth paragraph. The collapsedHeight prop controls how much content is visible when collapsed.

); export default Example; ``` # Color Picker - Examples and Patterns Examples for Color Picker component. ## Example: area-channels ```tsx import { ColorPicker, ColorPickerArea, ColorPickerAreaThumb, } from "@/components/ui/color-picker"; const Example = () => ( ); export default Example; ``` ## Example: area-dots ```tsx import { ColorPicker, ColorPickerArea, ColorPickerAreaThumb, } from "@/components/ui/color-picker"; const Example = () => ( ); export default Example; ``` ## Example: custom-spacing ```tsx import { ColorPicker, ColorPickerArea, ColorPickerAreaThumb, ColorPickerContent, ColorPickerControl, ColorPickerEyeDropperTrigger, ColorPickerInput, ColorPickerSlider, ColorPickerSwatchPreview, ColorPickerTransparencyGrid, ColorPickerTrigger, ColorPickerView, } from "@/components/ui/color-picker"; import { InputGroup, InputGroupAddon, InputGroupInput, } from "@/components/ui/input-group"; const Example = () => (
); export default Example; ``` ## Example: default ```tsx import { ColorPicker, ColorPickerArea, ColorPickerAreaThumb, ColorPickerContent, ColorPickerControl, ColorPickerEyeDropperTrigger, ColorPickerInput, ColorPickerSlider, ColorPickerSwatchPreview, ColorPickerTransparencyGrid, ColorPickerTrigger, ColorPickerView, } from "@/components/ui/color-picker"; import { InputGroup, InputGroupAddon, InputGroupInput, } from "@/components/ui/input-group"; const ColorPickerDemo = () => (
); export default ColorPickerDemo; ``` ## Example: input-channel ```tsx "use client"; import { ColorPicker, ColorPickerControl, ColorPickerInput, ColorPickerSwatchPreview, ColorPickerView, parseColor, } from "@/components/ui/color-picker"; import { Field, FieldLabel } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => (
RGB HSB HSL Hex
); export default Example; ``` ## Example: input-compact ```tsx "use client"; import { PercentIcon } from "lucide-react"; import { ColorPicker, ColorPickerArea, ColorPickerAreaThumb, ColorPickerContent, ColorPickerControl, ColorPickerInput, ColorPickerSlider, ColorPickerSwatchPreview, ColorPickerTransparencyGrid, ColorPickerTrigger, ColorPickerView, parseColor, } from "@/components/ui/color-picker"; import { InputGroup, InputGroupAddon, InputGroupInput, } from "@/components/ui/input-group"; import { Separator } from "@/components/ui/separator"; const Example = () => ( ); export default Example; ``` ## Example: input-controlled ```tsx "use client"; import React from "react"; import { ColorPicker, ColorPickerControl, ColorPickerInput, parseColor, } from "@/components/ui/color-picker"; import { Input } from "@/components/ui/input"; const Example = () => { const [value, setValue] = React.useState("#eb5e41"); return (
setValue(valueAsString)} value={value} >

{parseColor(value).toString("hex")}

); }; export default Example; ``` ## Example: input-disabled ```tsx import { ColorPicker, ColorPickerControl, ColorPickerInput, } from "@/components/ui/color-picker"; import { Input } from "@/components/ui/input"; const Example = () => ( ); export default Example; ``` ## Example: input-invalid ```tsx import { ColorPicker, ColorPickerControl, ColorPickerInput, } from "@/components/ui/color-picker"; import { Field, FieldError, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => ( Color Please enter a valid hex color ); export default Example; ``` ## Example: input-with-popover ```tsx import { ColorPicker, ColorPickerArea, ColorPickerAreaThumb, ColorPickerContent, ColorPickerControl, ColorPickerInput, ColorPickerSlider, ColorPickerSwatchPreview, ColorPickerTrigger, ColorPickerView, } from "@/components/ui/color-picker"; import { InputGroup, InputGroupAddon, InputGroupInput, } from "@/components/ui/input-group"; const Example = () => ( ); export default Example; ``` ## Example: input-with-swatch-preview ```tsx import { ColorPicker, ColorPickerControl, ColorPickerInput, ColorPickerSwatchPreview, } from "@/components/ui/color-picker"; import { InputGroup, InputGroupAddon, InputGroupInput, } from "@/components/ui/input-group"; const Example = () => ( ); export default Example; ``` ## Example: popover-disabled ```tsx import { Button } from "@/components/ui/button"; import { ColorPicker, ColorPickerArea, ColorPickerContent, ColorPickerControl, ColorPickerSwatchPreview, ColorPickerTrigger, } from "@/components/ui/color-picker"; const Example = () => ( ); export default Example; ``` ## Example: popover-sliders-only ```tsx "use client"; import { Button } from "@/components/ui/button"; import { ColorPicker, ColorPickerContent, ColorPickerControl, ColorPickerSlider, ColorPickerSwatchPreview, ColorPickerTransparencyGrid, ColorPickerTrigger, ColorPickerView, } from "@/components/ui/color-picker"; import { Field, FieldLabel } from "@/components/ui/field"; const Example = () => (
Hue Saturation Lightness Alpha
); export default Example; ``` ## Example: popover-with-channel-editing ```tsx import { Button } from "@/components/ui/button"; import { ColorPicker, ColorPickerArea, ColorPickerAreaThumb, ColorPickerContent, ColorPickerControl, ColorPickerInput, ColorPickerSlider, ColorPickerSwatchPreview, ColorPickerTrigger, } from "@/components/ui/color-picker"; import { Input } from "@/components/ui/input"; const Example = () => (
); export default Example; ``` ## Example: popover-with-swatch-picker ```tsx "use client"; import { Button } from "@/components/ui/button"; import { ColorPicker, ColorPickerArea, ColorPickerAreaThumb, ColorPickerContent, ColorPickerControl, ColorPickerSlider, ColorPickerSwatch, ColorPickerSwatchGroup, ColorPickerSwatchPreview, ColorPickerSwatchTrigger, ColorPickerTrigger, ColorPickerView, } from "@/components/ui/color-picker"; const Example = () => ( {swatches.map((color) => ( ))} ); const swatches = [ "#ef4444", "#f97316", "#eab308", "#22c55e", "#06b6d4", "#3b82f6", "#8b5cf6", "#ec4899", "#f43f5e", ]; export default Example; ``` ## Example: slider-alpha-channel ```tsx import { ColorPicker, ColorPickerSlider, ColorPickerTransparencyGrid, ColorPickerView, } from "@/components/ui/color-picker"; const Example = () => ( ); export default Example; ``` ## Example: slider-controlled ```tsx "use client"; import React from "react"; import { ColorPicker, ColorPickerSlider, ColorPickerView, } from "@/components/ui/color-picker"; const Example = () => { const [color, setColor] = React.useState("rgba(82, 65, 235, 1)"); return (
setColor(e.valueAsString)} value={color} >

{color}

); }; export default Example; ``` ## Example: slider-disabled ```tsx import { ColorPicker, ColorPickerSlider, ColorPickerView, } from "@/components/ui/color-picker"; const Example = () => ( ); export default Example; ``` ## Example: slider-hsba-channels ```tsx import { ColorPicker, ColorPickerSlider, ColorPickerView, } from "@/components/ui/color-picker"; const Example = () => (
); export default Example; ``` ## Example: slider-hsl-channels ```tsx import { ColorPicker, ColorPickerSlider, ColorPickerView, } from "@/components/ui/color-picker"; const Example = () => (
); export default Example; ``` ## Example: slider-rgb-channels ```tsx import { ColorPicker, ColorPickerSlider, ColorPickerView, } from "@/components/ui/color-picker"; const Example = () => (
); export default Example; ``` ## Example: slider-vertical ```tsx import { ColorPicker, ColorPickerSlider, ColorPickerView, } from "@/components/ui/color-picker"; const Example = () => (
); export default Example; ``` ## Example: swatch-picker-controlled ```tsx "use client"; import React from "react"; import { ColorPicker, ColorPickerSwatch, ColorPickerSwatchGroup, ColorPickerSwatchIndicator, ColorPickerSwatchTrigger, parseColor, } from "@/components/ui/color-picker"; const swatches = ["#0485F7", "#EF4444", "#F59E0B", "#10B981"]; const Example = () => { const [value, setValue] = React.useState("#0485F7"); return (
setValue(valueAsString)} value={value} > {swatches.map((color) => ( ))}

{parseColor(value).toString("hex")}

); }; export default Example; ``` ## Example: swatch-picker-custom-indicator ```tsx "use client"; import { SparkleIcon } from "lucide-react"; import { ColorPicker, ColorPickerSwatch, ColorPickerSwatchGroup, ColorPickerSwatchIndicator, ColorPickerSwatchTrigger, } from "@/components/ui/color-picker"; const swatches = ["#0485F7", "#EF4444", "#F59E0B", "#10B981"]; const Example = () => ( {swatches.map((color) => ( ))} ); export default Example; ``` ## Example: swatch-picker-custom-radius ```tsx import { ColorPicker, ColorPickerSwatch, ColorPickerSwatchGroup, ColorPickerSwatchIndicator, ColorPickerSwatchTrigger, } from "@/components/ui/color-picker"; const Example = () => ( ); export default Example; ``` ## Example: swatch-picker-custom-size ```tsx import { ColorPicker, ColorPickerSwatch, ColorPickerSwatchGroup, ColorPickerSwatchIndicator, ColorPickerSwatchTrigger, } from "@/components/ui/color-picker"; const Example = () => ( ); export default Example; ``` ## Example: swatch-picker-disabled ```tsx import { ColorPicker, ColorPickerSwatch, ColorPickerSwatchGroup, ColorPickerSwatchIndicator, ColorPickerSwatchTrigger, } from "@/components/ui/color-picker"; const swatches = ["#0485F7", "#EF4444", "#F59E0B", "#10B981"]; const Example = () => ( {swatches.map((color) => ( ))} ); export default Example; ``` ## Example: swatch-picker ```tsx import { ColorPicker, ColorPickerSwatch, ColorPickerSwatchGroup, ColorPickerSwatchIndicator, ColorPickerSwatchTrigger, } from "@/components/ui/color-picker"; const swatches = ["#0485F7", "#EF4444", "#F59E0B", "#10B981"]; const Example = () => ( {swatches.map((color) => ( ))} ); export default Example; ``` ## Example: with-field ```tsx import { ColorPicker, ColorPickerControl, ColorPickerInput, } from "@/components/ui/color-picker"; import { Field, FieldHelper, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => ( Color Enter your brand's primary color ); export default Example; ``` # Combobox - Examples and Patterns Examples for Combobox component. ## Example: autohighlight ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, { label: "Elderberry", value: "elderberry" }, ]; export default Example; ``` ## Example: controlled ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import React from "react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const [value, setValue] = React.useState("banana"); const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return (
filter(inputValue)} onValueChange={({ value }) => setValue(value[0])} > {collection.items.map((item) => ( {item.label} ))}

Selected: {value ?? "(none)"}

); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, ]; export default Example; ``` ## Example: default ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const ComboboxDemo = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, ]; export default ComboboxDemo; ``` ## Example: disabled ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, ]; export default Example; ``` ## Example: group ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, groupBy: (item) => item.continent, initialItems, }); return ( filter(inputValue)} > {collection.group().map(([continent, group]) => ( {group.map((item) => ( {item.label} ))} ))} ); }; const initialItems = [ { label: "Canada", value: "ca", continent: "North America" }, { label: "United States", value: "us", continent: "North America" }, { label: "Mexico", value: "mx", continent: "North America" }, { label: "United Kingdom", value: "uk", continent: "Europe" }, { label: "Germany", value: "de", continent: "Europe" }, { label: "France", value: "fr", continent: "Europe" }, { label: "Japan", value: "jp", continent: "Asia" }, { label: "South Korea", value: "kr", continent: "Asia" }, { label: "China", value: "cn", continent: "Asia" }, ]; export default Example; ``` ## Example: invalid ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, ]; export default Example; ``` ## Example: multiple ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "React", value: "react" }, { label: "Vue", value: "vue" }, { label: "Svelte", value: "svelte" }, { label: "Solid", value: "solid" }, ]; export default Example; ``` ## Example: size-lg ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, ]; export default Example; ``` ## Example: size-md ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, ]; export default Example; ``` ## Example: size-sm ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, { label: "Date", value: "date" }, ]; export default Example; ``` ## Example: with-clear-button ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, ]; export default Example; ``` ## Example: with-field ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; import { Field, FieldError, FieldHelper, FieldLabel, } from "@/components/ui/field"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, }); return ( Country filter(inputValue)} required > {collection.items.map((item) => ( {item.label} ))} We'll use this for shipping estimates Please select a valid country ); }; const initialItems = [ { label: "Brazil", value: "br" }, { label: "Mexico", value: "mx" }, { label: "Ireland", value: "ie" }, ]; export default Example; ``` ## Example: with-scroll ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = Array.from({ length: 30 }, (_, i) => ({ label: `Option ${i + 1}`, value: `option-${i + 1}`, })); export default Example; ``` ## Example: with-start-icon ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { AppleIcon } from "lucide-react"; import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList, } from "@/components/ui/combobox"; import { InputGroupAddon } from "@/components/ui/input-group"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} ))} ); }; const initialItems = [ { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, { label: "Cherry", value: "cherry" }, ]; export default Example; ``` # Command - Examples and Patterns Examples for Command component. ## Example: default ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Command, CommandContent, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, } from "@/components/ui/command"; const CommandExample = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ initialItems, filter: contains, groupBy: (item) => item.group, }); return ( filter(inputValue)} > {collection.group().map(([group, items], index) => ( {items.map((item) => ( {item.label} {item.shortcut} ))} {index < collection.group().length - 1 && } ))} ); }; const initialItems = [ { label: "Linear", shortcut: "⌘L", value: "linear", group: "Suggestions" }, { label: "Figma", shortcut: "⌘F", value: "figma", group: "Suggestions" }, { label: "Slack", shortcut: "⌘S", value: "slack", group: "Suggestions" }, { label: "YouTube", shortcut: "⌘Y", value: "youtube", group: "Suggestions" }, { label: "Raycast", shortcut: "⌘R", value: "raycast", group: "Suggestions" }, { label: "Settings", shortcut: "⌘,", value: "settings", group: "Settings" }, { label: "Help", shortcut: "⌘?", value: "help", group: "Settings" }, { label: "About", shortcut: "⌘I", value: "about", group: "Settings" }, { label: "Feedback", shortcut: "⌘F", value: "feedback", group: "Settings" }, { label: "Support", shortcut: "⌘S", value: "support", group: "Settings" }, { label: "Updates", shortcut: "⌘U", value: "updates", group: "Settings" }, { label: "Logout", shortcut: "⌘L", value: "logout", group: "Settings" }, { label: "Sign out", shortcut: "⌘O", value: "sign out", group: "Settings" }, { label: "Sign in", shortcut: "⌘I", value: "sign in", group: "Settings" }, ]; export default CommandExample; ``` ## Example: dialog ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { CornerDownLeftIcon } from "lucide-react"; import React from "react"; import { Button } from "@/components/ui/button"; import { Command, CommandContent, CommandDialog, CommandDialogContent, CommandDialogTrigger, CommandEmpty, CommandFooter, CommandGroup, CommandInput, CommandItem, CommandList, CommandShortcut, } from "@/components/ui/command"; import { Kbd } from "@/components/ui/kbd"; const Example = () => { const [open, setOpen] = React.useState(false); const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, groupBy: (item) => item.group, initialItems, }); return ( setOpen(o)} open={open}> filter(inputValue)} onValueChange={() => setOpen(false)} > No results found. {collection.group().map(([group, items]) => ( {items.map((item) => ( {item.label} {item.shortcut} ))} ))}
To select
); }; const initialItems = [ { label: "New File", shortcut: "⌘N", value: "new", group: "File" }, { label: "Save", shortcut: "⌘S", value: "save", group: "File" }, { label: "Open", shortcut: "⌘O", value: "open", group: "File" }, { label: "Undo", shortcut: "⌘Z", value: "undo", group: "Edit" }, { label: "Redo", shortcut: "⌘Z", value: "redo", group: "Edit" }, { label: "Cut", shortcut: "⌘X", value: "cut", group: "Edit" }, { label: "Copy", shortcut: "⌘C", value: "copy", group: "Edit" }, ]; export default Example; ``` ## Example: groups ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Command, CommandContent, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, } from "@/components/ui/command"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, groupBy: (item) => item.group, initialItems, }); return ( filter(inputValue)} > {collection.group().map(([group, items], index) => ( <> {index !== 0 && } {items.map((item) => ( {item.label} ))} ))} ); }; const initialItems = [ { label: "Apple", value: "apple", group: "Fruit" }, { label: "Banana", value: "banana", group: "Fruit" }, { label: "Cherry", value: "cherry", group: "Fruit" }, { label: "United States", value: "us", group: "Countries" }, { label: "United Kingdom", value: "uk", group: "Countries" }, { label: "Germany", value: "de", group: "Countries" }, ]; export default Example; ``` ## Example: scrollable ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Command, CommandContent, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, groupBy: (item) => item.group, initialItems, }); return ( filter(inputValue)} > {collection.group().map(([group, items]) => ( {items.map((item) => ( {item.label} ))} ))} ); }; const initialItems = [ { label: "Angular", value: "angular", group: "Frameworks" }, { label: "Astro", value: "astro", group: "Frameworks" }, { label: "Ember", value: "ember", group: "Frameworks" }, { label: "Gatsby", value: "gatsby", group: "Frameworks" }, { label: "Next.js", value: "nextjs", group: "Frameworks" }, { label: "Nuxt.js", value: "nuxtjs", group: "Frameworks" }, { label: "React", value: "react", group: "Frameworks" }, { label: "Remix", value: "remix", group: "Frameworks" }, { label: "Solid", value: "solid", group: "Frameworks" }, { label: "Svelte", value: "svelte", group: "Frameworks" }, { label: "Vue.js", value: "vuejs", group: "Frameworks" }, { label: "Alpine.js", value: "alpinejs", group: "Libraries" }, { label: "jQuery", value: "jquery", group: "Libraries" }, { label: "Lit", value: "lit", group: "Libraries" }, { label: "Preact", value: "preact", group: "Libraries" }, { label: "Qwik", value: "qwik", group: "Libraries" }, { label: "Stencil", value: "stencil", group: "Libraries" }, { label: "Blitz.js", value: "blitzjs", group: "Meta-frameworks" }, { label: "Redwood", value: "redwood", group: "Meta-frameworks" }, { label: "T3 Stack", value: "t3", group: "Meta-frameworks" }, { label: "TanStack Start", value: "tanstack-start", group: "Meta-frameworks", }, { label: "Wasp", value: "wasp", group: "Meta-frameworks" }, ]; export default Example; ``` ## Example: shortcuts ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { Command, CommandContent, CommandEmpty, CommandInput, CommandItem, CommandList, CommandShortcut, } from "@/components/ui/command"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, initialItems, }); return ( filter(inputValue)} > {collection.items.map((item) => ( {item.label} {item.shortcut} ))} ); }; const initialItems = [ { label: "New File", shortcut: "⌘N", value: "new" }, { label: "Save", shortcut: "⌘S", value: "save" }, { label: "Copy", shortcut: "⌘C", value: "copy" }, { label: "Paste", shortcut: "⌘V", value: "paste" }, { label: "Undo", shortcut: "⌘Z", value: "undo" }, { label: "Find", shortcut: "⌘F", value: "find" }, ]; export default Example; ``` ## Example: with-footer ```tsx "use client"; import { useFilter, useListCollection } from "@ark-ui/react"; import { ArrowDownIcon, ArrowUpIcon, CornerDownLeftIcon } from "lucide-react"; import { Command, CommandContent, CommandEmpty, CommandFooter, CommandGroup, CommandInput, CommandItem, CommandList, CommandShortcut, } from "@/components/ui/command"; import { Kbd } from "@/components/ui/kbd"; const Example = () => { const { contains } = useFilter({ sensitivity: "base" }); const { collection, filter } = useListCollection({ filter: contains, groupBy: (item) => item.group, initialItems, }); return ( filter(inputValue)} > {collection.group().map(([group, items]) => ( {items.map((item) => ( {item.label} {item.shortcut} ))} ))}
Select
Navigate
); }; const initialItems = [ { label: "Settings", shortcut: "⌘,", value: "settings", group: "App" }, { label: "Keyboard Shortcuts", shortcut: "⌘K", value: "shortcuts", group: "App", }, { label: "Help", shortcut: "⌘?", value: "help", group: "App" }, ]; export default Example; ``` # Context Menu - Examples and Patterns Examples for Context Menu component. ## Example: default ```tsx import { Archive, ArchiveX, Bell, CirclePlus, FolderInput, MailX, Reply, ReplyAll, Send, SquarePen, Trash, Trash2, } from "lucide-react"; import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, } from "@/components/ui/context-menu"; const ContextMenuDemo = () => ( Right click here Long press here Forward ⌘F Reply ⌘R Reply all ⌘A Archive ⌘Z Move to Junk Trash Reminders More Drafts Spam Delete ⌘ ⌫ ); export default ContextMenuDemo; ``` # Data List - Examples and Patterns Examples for Data List component. ## Example: default ```tsx import { DataList, DataListItem, DataListItemLabel, DataListItemValue, } from "@/components/ui/data-list"; const data = [ { label: "New Users", value: "234" }, { label: "Sales", value: "£12,340" }, { label: "Revenue", value: "3,450" }, ]; const DataListDemo = () => ( {data.map((item) => ( {item.label} {item.value} ))} ); export default DataListDemo; ``` ## Example: info-tip ```tsx import { InfoIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { DataList, DataListItem, DataListItemLabel, DataListItemValue, } from "@/components/ui/data-list"; import { ToggleTooltip, ToggleTooltipContent, ToggleTooltipTrigger, } from "@/components/ui/toggle-tooltip"; const data = [ { label: "New Users", value: "234", info: "Total new user signups this month", }, { label: "Sales", value: "£12,340", info: "Revenue from product sales" }, { label: "Revenue", value: "3,450", info: "Total revenue in the last quarter", }, ]; const Example = () => ( {data.map((item) => ( {item.label} {item.info} {item.value} ))} ); export default Example; ``` ## Example: orientation-horizontal ```tsx import { DataList, DataListItem, DataListItemLabel, DataListItemValue, } from "@/components/ui/data-list"; const Example = () => ( First Name Jassie Last Name Bhatia Email jassie@example.com ); export default Example; ``` ## Example: orientation-vertical ```tsx import { DataList, DataListItem, DataListItemLabel, DataListItemValue, } from "@/components/ui/data-list"; const Example = () => ( First Name Jassie Last Name Bhatia Email jassie@example.com ); export default Example; ``` ## Example: separator ```tsx import { DataList, DataListItem, DataListItemLabel, DataListItemValue, } from "@/components/ui/data-list"; const data = [ { label: "First Name", value: "Jassie" }, { label: "Last Name", value: "Bhatia" }, { label: "Email", value: "jassie@example.com" }, { label: "Phone", value: "1234567890" }, { label: "Address", value: "1234 Main St, Anytown, USA" }, ]; const Example = () => ( {data.map((item) => ( {item.label} {item.value} ))} ); export default Example; ``` # Date Picker - Examples and Patterns Examples for Date Picker component. ## Example: custom-format ```tsx "use client"; import { format } from "date-fns"; import { CalendarIcon } from "lucide-react"; import React from "react"; import { Button } from "@/components/ui/button"; import { CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, parseDate, } from "@/components/ui/calendar"; import { DatePicker, DatePickerContent, DatePickerTrigger, } from "@/components/ui/date-picker"; const Example = () => { const [value, setValue] = React.useState([parseDate("2025-01-15")]); const formattedDate = format(value[0].toString(), "PPP"); return ( setValue(value)} value={value}> ); }; export default Example; ``` ## Example: default ```tsx "use client"; import { CalendarIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, } from "@/components/ui/calendar"; import { DatePicker, DatePickerContent, DatePickerTrigger, DatePickerValue, } from "@/components/ui/date-picker"; const Example = () => ( ); export default Example; ``` ## Example: input ```tsx import { CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, } from "@/components/ui/calendar"; import { DatePicker, DatePickerContent, DatePickerInput, } from "@/components/ui/date-picker"; const Example = () => ( ); export default Example; ``` ## Example: range ```tsx "use client"; import { CalendarIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, parseDate, } from "@/components/ui/calendar"; import { DatePicker, DatePickerContent, DatePickerTrigger, DatePickerValue, } from "@/components/ui/date-picker"; const Example = () => ( ); export default Example; ``` ## Example: time ```tsx import { DatePickerTimer } from "@/components/ui/date-picker"; import { Field, FieldLabel } from "@/components/ui/field"; const Example = () => ( Time ); export default Example; ``` ## Example: with-presets ```tsx "use client"; import { CalendarIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { CalendarMonthSelect, CalendarNextTrigger, CalendarPrevTrigger, CalendarTable, CalendarTableDays, CalendarViewControl, CalendarWeekDays, CalendarYearSelect, parseDate, } from "@/components/ui/calendar"; import { DatePicker, DatePickerContent, DatePickerPresetTrigger, DatePickerTrigger, DatePickerValue, } from "@/components/ui/date-picker"; const Example = () => (
{presets.map((preset) => ( ))}
); const presets = [ { label: "Today", days: 0 }, { label: "Tomorrow", days: 1 }, { label: "In 3 days", days: 3 }, { label: "In a week", days: 7 }, ] as const; export default Example; ``` # Dialog - Examples and Patterns Examples for Dialog component. ## Example: close-behavior ```tsx import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogHeader, DialogTrigger, } from "@/components/ui/dialog"; const Example = () => (
); export default Example; ``` ## Example: custom-spacing ```tsx import { Button } from "@/components/ui/button"; import { Dialog, DialogBody, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTrigger, } from "@/components/ui/dialog"; import { Field, FieldGroup, FieldLabel, FieldSet, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { NativeSelect, NativeSelectOption, } from "@/components/ui/native-select"; const Example = () => (
Name Main branch main develop
); export default Example; ``` ## Example: default ```tsx import { Button } from "@/components/ui/button"; import { Dialog, DialogBody, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTrigger, } from "@/components/ui/dialog"; import { Field, FieldGroup, FieldLabel, FieldSet, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { NativeSelect, NativeSelectOption, } from "@/components/ui/native-select"; const DialogDemo = () => (
Name Main branch main develop feature/123 release/1.0.0
); export default DialogDemo; ``` ## Example: initial-focus ```tsx "use client"; import React from "react"; import { Button } from "@/components/ui/button"; import { Dialog, DialogBody, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTrigger, } from "@/components/ui/dialog"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => { const inputRef = React.useRef(null); return ( inputRef.current}> Name Email ); }; export default Example; ``` ## Example: nested ```tsx import { Button } from "@/components/ui/button"; import { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => (

Name

Bora Baloglu

Email

bora@example.com

Edit details Make changes to the member's information. Name Email
); export default Example; ``` ## Example: no-close-button ```tsx import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogHeader, DialogTrigger, } from "@/components/ui/dialog"; const Example = () => ( ); export default Example; ``` ## Example: non-modal ```tsx import { Button } from "@/components/ui/button"; import { Dialog, DialogBody, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTrigger, } from "@/components/ui/dialog"; const Example = () => (

Non-modal dialogs allow interaction with elements outside the dialog. Focus trapping and scroll prevention are disabled.

); export default Example; ``` ## Example: open-from-menu ```tsx "use client"; import { InfoIcon, SettingsIcon, UserIcon } from "lucide-react"; import React from "react"; import { Button } from "@/components/ui/button"; import { Dialog, DialogBody, DialogClose, DialogContent, DialogFooter, DialogHeader, } from "@/components/ui/dialog"; import { Menu, MenuContent, MenuItem, MenuTrigger, } from "@/components/ui/menu"; const Example = () => { const [isOpen, setIsOpen] = React.useState(false); return ( <> setIsOpen(true)} value="settings"> Open settings View profile Help setIsOpen(open)} open={isOpen}>

You can open dialogs imperatively from menu items using the onSelect handler.

); }; export default Example; ``` ## Example: scroll-area ```tsx import { Button } from "@/components/ui/button"; import { Dialog, DialogBody, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTrigger, } from "@/components/ui/dialog"; const Example = () => (

What is Lorem Ipsum?

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi imperdiet placerat nisl, ac consequat sem hendrerit in.

Why do we use it?

Pellentesque quis sapien tortor. Nulla egestas tristique justo, in commodo quam posuere id. Cras varius, nunc non placerat vulputate, dolor turpis elementum elit, non lobortis lacus nunc nec nisl.

Where does it come from?

Pellentesque turpis est, mollis eu arcu eu, tempor tincidunt urna. Pellentesque pellentesque est euismod accumsan ullamcorper. Quisque urna lorem, porttitor ac malesuada at, vehicula eget nulla. Donec eget consequat erat, quis pharetra ex.

Where can I get some?

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec egestas semper eros a maximus. Sed consequat tempus lobortis. Phasellus sed vulputate turpis. Nulla facilisi. Curabitur consequat dui tellus.

Who can I contact if I have questions?

Donec tortor lorem, finibus vel suscipit vehicula, sagittis efficitur erat. Proin sagittis aliquam sagittis. Nullam sed porta leo. Nunc sed velit felis.

What happens if I don't agree to these terms?

Aenean maximus, libero vel laoreet congue, purus leo iaculis libero, egestas egestas quam mi at quam. Curabitur eu tempus mauris. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae;

Where can I get some?

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec egestas semper eros a maximus. Sed consequat tempus lobortis. Phasellus sed vulputate turpis. Nulla facilisi. Curabitur consequat dui tellus.

); export default Example; ``` # Download Trigger - Examples and Patterns Examples for Download Trigger component. ## Example: default ```tsx import { DownloadIcon, FileTextIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { DownloadTrigger } from "@/components/ui/download-trigger"; import { Item, ItemTitle } from "@/components/ui/item"; const DownloadTriggerDemo = () => (
{content}
); const content = "Hello, World! This is a sample text file."; export default DownloadTriggerDemo; ``` ## Example: download-svg ```tsx import { DownloadIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { DownloadTrigger } from "@/components/ui/download-trigger"; const Example = () => ( ); const svgContent = ``; export default Example; ``` ## Example: promise ```tsx "use client"; import { DownloadIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { DownloadTrigger } from "@/components/ui/download-trigger"; const Example = () => ( ); const fetchData = () => new Promise((resolve) => { setTimeout(() => { resolve( new Blob(['{"message": "Loaded asynchronously!"}'], { type: "application/json", }) ); }, 500); }); export default Example; ``` # Drawer - Examples and Patterns Examples for Drawer component. ## Example: custom-spacing ```tsx import { Button } from "@/components/ui/button"; import { Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerContentInner, DrawerFooter, DrawerHeader, DrawerTrigger, } from "@/components/ui/drawer"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => ( Name Username ); export default Example; ``` ## Example: default ```tsx import { Button } from "@/components/ui/button"; import { Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerContentInner, DrawerFooter, DrawerHeader, DrawerTrigger, } from "@/components/ui/drawer"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const DrawerDemo = () => ( Name Username ); export default DrawerDemo; ``` ## Example: drawer-content-inner ```tsx import { Button } from "@/components/ui/button"; import { Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerContentInner, DrawerFooter, DrawerHeader, DrawerTrigger, } from "@/components/ui/drawer"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => ( Name Email ); export default Example; ``` ## Example: inset ```tsx import { Button } from "@/components/ui/button"; import { Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerContentInner, DrawerFooter, DrawerHeader, DrawerTrigger, } from "@/components/ui/drawer"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => ( Name Email ); export default Example; ``` ## Example: snap-points ```tsx import { Button } from "@/components/ui/button"; import { Drawer, DrawerBody, DrawerContent, DrawerContentInner, DrawerHeader, DrawerTrigger, } from "@/components/ui/drawer"; const Example = () => (

This drawer has multiple snap points. Try dragging the handle to quarter, half, or full height.

); export default Example; ``` ## Example: swipe-directions ```tsx import { Button } from "@/components/ui/button"; import { Drawer, DrawerBody, DrawerContent, DrawerHeader, DrawerTrigger, } from "@/components/ui/drawer"; const Example = () => (

Swipe down to close this drawer.

Swipe up to close this drawer.

Swipe left to close this drawer.

Swipe right to close this drawer.

); export default Example; ``` # Editable - Examples and Patterns Examples for Editable component. ## Example: activation-click ```tsx import { CheckIcon, XIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, } from "@/components/ui/card"; import { Editable, EditableArea, EditableCancelTrigger, EditableControl, EditableInput, EditablePreview, EditableSubmitTrigger, } from "@/components/ui/editable"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => ( Name Username ); export default Example; ``` ## Example: activation-focus ```tsx import { CheckIcon, XIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, } from "@/components/ui/card"; import { Editable, EditableArea, EditableCancelTrigger, EditableControl, EditableInput, EditablePreview, EditableSubmitTrigger, } from "@/components/ui/editable"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => ( Name Username ); export default Example; ``` ## Example: activation-none ```tsx import { CheckIcon, EditIcon, XIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, } from "@/components/ui/card"; import { Editable, EditableArea, EditableCancelTrigger, EditableControl, EditableEditTrigger, EditableInput, EditablePreview, EditableSubmitTrigger, } from "@/components/ui/editable"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => ( Name Username ); export default Example; ``` ## Example: controlled ```tsx "use client"; import { CheckIcon, PencilIcon } from "lucide-react"; import React from "react"; import { Button } from "@/components/ui/button"; import { Card, CardAction, CardContent, CardHeader, } from "@/components/ui/card"; import { Editable, EditableArea, EditableInput, EditablePreview, } from "@/components/ui/editable"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => { const [isEditing, setIsEditing] = React.useState(false); return ( Name Username ); }; export default Example; ``` ## Example: dblclick ```tsx import { CheckIcon, XIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, } from "@/components/ui/card"; import { Editable, EditableArea, EditableCancelTrigger, EditableControl, EditableInput, EditablePreview, EditableSubmitTrigger, } from "@/components/ui/editable"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const Example = () => ( Name Username ); export default Example; ``` ## Example: default ```tsx import { CheckIcon, XIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, } from "@/components/ui/card"; import { Editable, EditableArea, EditableCancelTrigger, EditableControl, EditableInput, EditablePreview, EditableSubmitTrigger, } from "@/components/ui/editable"; import { Field, FieldGroup, FieldLabel, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; const EditableDemo = () => ( Name Username ); export default EditableDemo; ``` ## Example: orientation-horizontal ```tsx import { CheckIcon, XIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Editable, EditableArea, EditableCancelTrigger, EditableControl, EditableInput, EditablePreview, EditableSubmitTrigger, } from "@/components/ui/editable"; import { Input } from "@/components/ui/input"; const Example = () => ( ); export default Example; ``` ## Example: orientation-vertical ```tsx import { CheckIcon, XIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Editable, EditableArea, EditableCancelTrigger, EditableControl, EditableInput, EditablePreview, EditableSubmitTrigger, } from "@/components/ui/editable"; import { Textarea } from "@/components/ui/textarea"; const Example = () => (