---
name: ark-ui
description: Builds accessible UI components with Ark UI headless primitives for React, Vue, Solid, and Svelte. Use when creating custom-styled components with robust state management and accessibility built-in.
---
# Ark UI
Headless component library with 45+ accessible components powered by state machines.
## Quick Start
```bash
npm install @ark-ui/react
```
```tsx
import { Accordion } from '@ark-ui/react'
function App() {
return (
What is React?
React is a JavaScript library for building user interfaces.
)
}
```
## Core Concepts
### Anatomy Pattern
Ark UI uses compound components with dot notation:
```tsx
```
### Data Attributes for Styling
Components expose state via data attributes:
```css
/* Base styles */
[data-scope="accordion"][data-part="trigger"] {
display: flex;
justify-content: space-between;
}
/* State-based styles */
[data-state="open"] {
background-color: #f0f0f0;
}
[data-state="closed"] {
background-color: white;
}
[data-disabled] {
opacity: 0.5;
}
[data-focus] {
outline: 2px solid blue;
}
```
### With Tailwind CSS
```tsx
Trigger Text
```
## Components
### Accordion
```tsx
import { Accordion } from '@ark-ui/react'
import { ChevronDownIcon } from 'lucide-react'
function AccordionDemo() {
return (
{items.map((item) => (
{item.title}
{item.content}
))}
)
}
```
### Dialog
```tsx
import { Dialog, Portal } from '@ark-ui/react'
function DialogDemo() {
return (
Open Dialog
Dialog Title
Dialog description text here.
Cancel
)
}
```
### Menu
```tsx
import { Menu, Portal } from '@ark-ui/react'
function MenuDemo() {
return (
Open Menu
Edit
Duplicate
Delete
)
}
```
### Select
```tsx
import { Select, Portal } from '@ark-ui/react'
import { CheckIcon, ChevronDownIcon } from 'lucide-react'
const items = [
{ label: 'React', value: 'react' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte' },
]
function SelectDemo() {
return (
Framework
{items.map((item) => (
{item.label}
))}
)
}
```
### Combobox
```tsx
import { Combobox, Portal } from '@ark-ui/react'
import { useState } from 'react'
const allItems = [
{ label: 'React', value: 'react' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte' },
{ label: 'Solid', value: 'solid' },
]
function ComboboxDemo() {
const [items, setItems] = useState(allItems)
const handleInputChange = ({ inputValue }) => {
const filtered = allItems.filter((item) =>
item.label.toLowerCase().includes(inputValue.toLowerCase())
)
setItems(filtered)
}
return (
Framework
{items.map((item) => (
{item.label}
))}
)
}
```
### Tabs
```tsx
import { Tabs } from '@ark-ui/react'
function TabsDemo() {
return (
React
Vue
Svelte
React content
Vue content
Svelte content
)
}
```
### Switch
```tsx
import { Switch } from '@ark-ui/react'
function SwitchDemo() {
return (
Enable notifications
)
}
```
### Checkbox
```tsx
import { Checkbox } from '@ark-ui/react'
import { CheckIcon, MinusIcon } from 'lucide-react'
function CheckboxDemo() {
return (
Accept terms
)
}
```
### Slider
```tsx
import { Slider } from '@ark-ui/react'
function SliderDemo() {
return (
Volume
)
}
// Range slider
```
### Tooltip
```tsx
import { Tooltip, Portal } from '@ark-ui/react'
function TooltipDemo() {
return (
Hover me
Tooltip content
)
}
```
### Popover
```tsx
import { Popover, Portal } from '@ark-ui/react'
function PopoverDemo() {
return (
Open Popover
Popover Title
This is the popover content.
)
}
```
### DatePicker
```tsx
import { DatePicker, Portal } from '@ark-ui/react'
function DatePickerDemo() {
return (
Date
{(api) => (
<>
{api.weekDays.map((day, i) => (
{day.narrow}
))}
{api.weeks.map((week, i) => (
{week.map((day, j) => (
{day.day}
))}
))}
>
)}
)
}
```
### Toast
```tsx
import { Toaster, createToaster } from '@ark-ui/react'
const toaster = createToaster({
placement: 'bottom-end',
overlap: true,
gap: 16,
})
function ToastDemo() {
return (
<>
{(toast) => (
{toast.title}
{toast.description}
Close
)}
>
)
}
```
## Controlled vs Uncontrolled
```tsx
// Uncontrolled (internal state)
{/* ... */}
// Controlled (external state)
const [value, setValue] = useState(['item-1'])
setValue(details.value)}>
{/* ... */}
```
## API Patterns
### onValueChange
```tsx
{
console.log(details.value) // Selected value(s)
console.log(details.items) // Selected item(s)
}}
>
```
### onOpenChange
```tsx
{
console.log(details.open) // boolean
}}
>
```
## Best Practices
1. **Use Portal** - Wrap overlays in Portal for proper stacking
2. **Style with data attributes** - Use `data-[state=open]` patterns
3. **Provide accessible labels** - Use Label components
4. **Handle keyboard** - All components have built-in keyboard support
5. **Use HiddenInput** - For form integration with checkboxes/switches
## Reference Files
- [references/components.md](references/components.md) - Complete component list
- [references/patterns.md](references/patterns.md) - Common patterns