## How to use these docs Vinicunca is a set of open source packages for building Vue and TypeScript applications. Each package has its own section on this site. - **Pohon UI** (`pohon-ui`): styled, accessible Vue and Nuxt components built on Akar and UnoCSS. Use it for application UI: forms, tables, overlays, dashboards, docs and chat layouts. - **Akar** (`akar`): unstyled, accessible Vue primitives (a fork of Reka UI). Use it to build your own design system, or when Pohon UI is too opinionated. - **Perkakas** (`@vinicunca/perkakas`): typed data-first and data-last utility functions (a fork of Remeda). Use it instead of lodash or ramda. - **Taman** (`create-taman`, `@vinicunca/taman-*`, `@vinicunca/request`): a full-stack Vue admin template with oRPC, better-auth, Drizzle and Cloudflare Workers. - **ESLint Config** (`@vinicunca/eslint-config`): a flat ESLint config that also formats code. Use `vinicuncaESLint()` in `eslint.config.js`. - **UnoCSS Preset** (`@vinicunca/unocss-preset`): `presetVinicunca()`, the UnoCSS preset every Vinicunca project uses, with fluid sizing, animations and scrollbars. - **UnoCSS Variants** (`unocss-variants`): `uv()` for variants, slots and compound styles with UnoCSS, a port of Tailwind Variants. How an agent should read this site: - Read any documentation page as Markdown: prefix its path with `/raw` and add `.md` (`https://vinicunca.dev/raw/pohon/components/button.md`). - Start from the Markdown sitemap at https://vinicunca.dev/sitemap.md, or the full documentation at https://vinicunca.dev/llms-full.txt. - For Pohon UI conventions and component selection, load the agent skill at https://vinicunca.dev/.well-known/skills/pohon-ui/SKILL.md. - For ESLint Config setup and the style rules it enforces, load the agent skill at https://vinicunca.dev/.well-known/skills/eslint-config/SKILL.md. - For Taman project layout and the add-a-feature checklist, load the agent skill at https://vinicunca.dev/.well-known/skills/taman/SKILL.md. - For UnoCSS Preset setup, fluid utilities and theme tokens, load the agent skill at https://vinicunca.dev/.well-known/skills/unocss-preset/SKILL.md. - For Perkakas imports, pipe, and data-first versus data-last, load the agent skill at https://vinicunca.dev/.well-known/skills/perkakas/SKILL.md. - For Akar composition (Root/Trigger/Content, asChild, data attributes), load the agent skill at https://vinicunca.dev/.well-known/skills/akar/SKILL.md. - For UnoCSS Variants (`uv`, slots, compound variants, no class merging), load the agent skill at https://vinicunca.dev/.well-known/skills/unocss-variants/SKILL.md. - For setting up or troubleshooting a Windows (WSL) dev machine, load the agent skill at https://vinicunca.dev/.well-known/skills/windows-dev/SKILL.md. Entry points: - [Pohon UI installation (Nuxt)](https://vinicunca.dev/raw/pohon/getting-started/installation/nuxt.md): Add Pohon UI to a Nuxt application - [Pohon UI installation (Vue)](https://vinicunca.dev/raw/pohon/getting-started/installation/vue.md): Add Pohon UI to a Vue application with Vite - [Pohon UI agent skill](https://vinicunca.dev/.well-known/skills/pohon-ui/SKILL.md): Conventions, component selection and layout recipes - [ESLint Config](https://vinicunca.dev/raw/eslint/getting-started.md): Install vinicuncaESLint and set up the editor - [ESLint Config agent skill](https://vinicunca.dev/.well-known/skills/eslint-config/SKILL.md): Factory options and the style conventions it enforces - [Taman](https://vinicunca.dev/raw/taman/getting-started.md): Create a Taman project and run it locally - [Taman agent skill](https://vinicunca.dev/.well-known/skills/taman/SKILL.md): Where code goes and the add-a-feature checklist - [UnoCSS Preset agent skill](https://vinicunca.dev/.well-known/skills/unocss-preset/SKILL.md): presetVinicunca options, fluid utilities and theme tokens - [Perkakas](https://vinicunca.dev/raw/perkakas/getting-started.md): Install Perkakas and the function reference - [Perkakas agent skill](https://vinicunca.dev/.well-known/skills/perkakas/SKILL.md): Data-first and data-last, pipe, and common functions - [Akar](https://vinicunca.dev/raw/akar/overview.md): Install Akar and the component anatomy - [Akar agent skill](https://vinicunca.dev/.well-known/skills/akar/SKILL.md): When to use Akar, composition, and data attributes - [UnoCSS Variants](https://vinicunca.dev/raw/unocss-variants/getting-started.md): uv() variants, slots, and the no-merge layer setup - [UnoCSS Variants agent skill](https://vinicunca.dev/.well-known/skills/unocss-variants/SKILL.md): uv API, slots, compound variants, and the no-merge caveat - [Markdown sitemap](https://vinicunca.dev/sitemap.md): Every page on the site, as Markdown links # Vinicunca > Documentation for every @vinicunca package. ## How to use these docs Vinicunca is a set of open source packages for building Vue and TypeScript applications. Each package has its own section on this site. - **Pohon UI** (`pohon-ui`): styled, accessible Vue and Nuxt components built on Akar and UnoCSS. Use it for application UI: forms, tables, overlays, dashboards, docs and chat layouts. - **Akar** (`akar`): unstyled, accessible Vue primitives (a fork of Reka UI). Use it to build your own design system, or when Pohon UI is too opinionated. - **Perkakas** (`@vinicunca/perkakas`): typed data-first and data-last utility functions (a fork of Remeda). Use it instead of lodash or ramda. - **Taman** (`create-taman`, `@vinicunca/taman-*`, `@vinicunca/request`): a full-stack Vue admin template with oRPC, better-auth, Drizzle and Cloudflare Workers. - **ESLint Config** (`@vinicunca/eslint-config`): a flat ESLint config that also formats code. Use `vinicuncaESLint()` in `eslint.config.js`. - **UnoCSS Preset** (`@vinicunca/unocss-preset`): `presetVinicunca()`, the UnoCSS preset every Vinicunca project uses, with fluid sizing, animations and scrollbars. - **UnoCSS Variants** (`unocss-variants`): `uv()` for variants, slots and compound styles with UnoCSS, a port of Tailwind Variants. How an agent should read this site: - Read any documentation page as Markdown: prefix its path with `/raw` and add `.md` (`https://vinicunca.dev/raw/pohon/components/button.md`). - Start from the Markdown sitemap at https://vinicunca.dev/sitemap.md, or the full documentation at https://vinicunca.dev/llms-full.txt. - For Pohon UI conventions and component selection, load the agent skill at https://vinicunca.dev/.well-known/skills/pohon-ui/SKILL.md. - For ESLint Config setup and the style rules it enforces, load the agent skill at https://vinicunca.dev/.well-known/skills/eslint-config/SKILL.md. - For Taman project layout and the add-a-feature checklist, load the agent skill at https://vinicunca.dev/.well-known/skills/taman/SKILL.md. - For UnoCSS Preset setup, fluid utilities and theme tokens, load the agent skill at https://vinicunca.dev/.well-known/skills/unocss-preset/SKILL.md. - For Perkakas imports, pipe, and data-first versus data-last, load the agent skill at https://vinicunca.dev/.well-known/skills/perkakas/SKILL.md. - For Akar composition (Root/Trigger/Content, asChild, data attributes), load the agent skill at https://vinicunca.dev/.well-known/skills/akar/SKILL.md. - For UnoCSS Variants (`uv`, slots, compound variants, no class merging), load the agent skill at https://vinicunca.dev/.well-known/skills/unocss-variants/SKILL.md. - For setting up or troubleshooting a Windows (WSL) dev machine, load the agent skill at https://vinicunca.dev/.well-known/skills/windows-dev/SKILL.md. Entry points: - [Pohon UI installation (Nuxt)](https://vinicunca.dev/raw/pohon/getting-started/installation/nuxt.md): Add Pohon UI to a Nuxt application - [Pohon UI installation (Vue)](https://vinicunca.dev/raw/pohon/getting-started/installation/vue.md): Add Pohon UI to a Vue application with Vite - [Pohon UI agent skill](https://vinicunca.dev/.well-known/skills/pohon-ui/SKILL.md): Conventions, component selection and layout recipes - [ESLint Config](https://vinicunca.dev/raw/eslint/getting-started.md): Install vinicuncaESLint and set up the editor - [ESLint Config agent skill](https://vinicunca.dev/.well-known/skills/eslint-config/SKILL.md): Factory options and the style conventions it enforces - [Taman](https://vinicunca.dev/raw/taman/getting-started.md): Create a Taman project and run it locally - [Taman agent skill](https://vinicunca.dev/.well-known/skills/taman/SKILL.md): Where code goes and the add-a-feature checklist - [UnoCSS Preset agent skill](https://vinicunca.dev/.well-known/skills/unocss-preset/SKILL.md): presetVinicunca options, fluid utilities and theme tokens - [Perkakas](https://vinicunca.dev/raw/perkakas/getting-started.md): Install Perkakas and the function reference - [Perkakas agent skill](https://vinicunca.dev/.well-known/skills/perkakas/SKILL.md): Data-first and data-last, pipe, and common functions - [Akar](https://vinicunca.dev/raw/akar/overview.md): Install Akar and the component anatomy - [Akar agent skill](https://vinicunca.dev/.well-known/skills/akar/SKILL.md): When to use Akar, composition, and data attributes - [UnoCSS Variants](https://vinicunca.dev/raw/unocss-variants/getting-started.md): uv() variants, slots, and the no-merge layer setup - [UnoCSS Variants agent skill](https://vinicunca.dev/.well-known/skills/unocss-variants/SKILL.md): uv API, slots, compound variants, and the no-merge caveat - [Markdown sitemap](https://vinicunca.dev/sitemap.md): Every page on the site, as Markdown links ## Packages - [Akar](https://vinicunca.dev/raw/akar/overview.md): Unstyled, accessible Vue primitives for building design systems. - [Pohon UI](https://vinicunca.dev/raw/pohon/getting-started.md): A Vue and Nuxt component library styled with UnoCSS, built on Akar. - [Taman](https://vinicunca.dev/raw/taman/getting-started.md): A full-stack Vue admin template with oRPC, better-auth and Cloudflare. - [Perkakas](https://vinicunca.dev/raw/perkakas/getting-started.md): A typed, data-first and data-last utility library for TypeScript. - [ESLint Config](https://vinicunca.dev/raw/eslint/getting-started.md): Vinicunca's flat ESLint config with formatting, TypeScript, Vue and more. - [UnoCSS Preset](https://vinicunca.dev/raw/unocss-preset/getting-started.md): The Vinicunca UnoCSS preset: fluid sizing, animations, scrollbars and more. - [UnoCSS Variants](https://vinicunca.dev/raw/unocss-variants/getting-started.md): Variants, slots and compound styles for UnoCSS, a port of Tailwind Variants. - [Windows Dev Setup](https://vinicunca.dev/raw/windows-dev/guide.md): Set up a web development environment on Windows with WSL. ## Links - Website: - GitHub: ## Resources for Agents - [API catalog: every service document this site publishes](https://vinicunca.dev/.well-known/api-catalog) - [Sitemap (XML)](https://vinicunca.dev/sitemap.xml) - [Sitemap (Markdown): every page on the site](https://vinicunca.dev/sitemap.md) - [llms.txt: index of the documentation for LLMs](https://vinicunca.dev/llms.txt) - [llms-full.txt: the full documentation as a single file](https://vinicunca.dev/llms-full.txt) - [Agent skills index: every skill published by this site](https://vinicunca.dev/.well-known/skills/index.json) - [Agent skill: akar](https://vinicunca.dev/.well-known/skills/akar/SKILL.md) - [Agent skill: eslint-config](https://vinicunca.dev/.well-known/skills/eslint-config/SKILL.md) - [Agent skill: perkakas](https://vinicunca.dev/.well-known/skills/perkakas/SKILL.md) - [Agent skill: pohon-ui](https://vinicunca.dev/.well-known/skills/pohon-ui/SKILL.md) - [Agent skill: taman](https://vinicunca.dev/.well-known/skills/taman/SKILL.md) - [Agent skill: unocss-preset](https://vinicunca.dev/.well-known/skills/unocss-preset/SKILL.md) - [Agent skill: unocss-variants](https://vinicunca.dev/.well-known/skills/unocss-variants/SKILL.md) - [Agent skill: windows-dev](https://vinicunca.dev/.well-known/skills/windows-dev/SKILL.md) - [Homepage](https://vinicunca.dev/raw/index.md) Every page on this site is available as raw markdown: append `.md` to its URL or send `Accept: text/markdown`. # Installation > Learn how to install and configure Pohon UI in your Nuxt application. > [!NOTE] > See: /pohon/getting-started/installation/vue > > Looking for the **Vue** version? > [!TIP] > See: https://ui.nuxt.com > > Pohon UI is styled with UnoCSS. If your project uses Tailwind CSS, use **Nuxt UI** instead. ## Setup ### Add to a Nuxt project #### Install the Pohon UI package ```bash [pnpm] pnpm add pohon-ui unocss @vinicunca/unocss-preset ``` ```bash [yarn] yarn add pohon-ui unocss @vinicunca/unocss-preset ``` ```bash [npm] npm install pohon-ui unocss @vinicunca/unocss-preset ``` ```bash [bun] bun add pohon-ui unocss @vinicunca/unocss-preset ``` #### Add the Pohon UI module in your `nuxt.config.ts` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['pohon-ui'] }); ``` > [!NOTE] > > There is no need to add `@nuxt/icon`, `@nuxt/fonts` or `@nuxtjs/color-mode` to your `modules` array as Pohon UI registers them automatically. You can still configure these modules in your `nuxt.config.ts` using the `icon`, `fonts` and `colorMode` keys. #### Configure the UnoCSS preset The Pohon module registers `@unocss/nuxt`. Create an UnoCSS configuration for the semantic utilities used by the components: ```ts [uno.config.ts] import { presetVinicunca } from '@vinicunca/unocss-preset'; import { pohonColors } from 'pohon-ui/unocss'; import { defineConfig } from 'unocss'; export default defineConfig({ presets: [ presetVinicunca() ], theme: { colors: pohonColors }, }); ``` #### Wrap your app with App component ```vue [app.vue] ``` > [!NOTE] > See: /pohon/components/app > > The `App` component sets up global config and is required for **Toast**, **Tooltip** and **programmatic overlays**. ### Explore working examples See the [Nuxt playground](https://github.com/vinicunca/pohon/tree/main/playgrounds/nuxt) and [Vue playground](https://github.com/vinicunca/pohon/tree/main/playgrounds/vue) for complete Pohon UI setups. ## Options You can customize Pohon UI by providing options in your `nuxt.config.ts`. ### `prefix` Use the `prefix` option to change the prefix of the components. - Default: `P` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['pohon-ui'], css: ['~/assets/css/main.css'], ui: { prefix: 'Nuxt' } }); ``` ### `fonts` Use the `fonts` option to enable or disable the [`@nuxt/fonts`](https://github.com/nuxt/fonts) module. - Default: `true` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['pohon-ui'], css: ['~/assets/css/main.css'], ui: { fonts: false } }); ``` ### `colorMode` Use the `colorMode` option to enable or disable the [`@nuxt/color-mode`](https://github.com/nuxt-modules/color-mode) module. - Default: `true` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['pohon-ui'], css: ['~/assets/css/main.css'], ui: { colorMode: false } }); ``` ### `theme.colors` Use the `theme.colors` option to define the dynamic color aliases used to generate components theme. - Default: `['primary', 'secondary', 'success', 'info', 'warning', 'error']` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['pohon-ui'], css: ['~/assets/css/main.css'], ui: { theme: { colors: ['primary', 'error'] } } }); ``` > [!NOTE] > > Each alias adds a color variant to every component theme that has one, whether your app uses it or not. Trim the list to the aliases you actually use, and keep `error` if you use forms since validation styles rely on it. `primary` is always included. > > The `--ui-color--*` shades themselves are not generated: define them in your CSS (see [CSS Variables](https://vinicunca.dev/pohon/getting-started/theme/css-variables)). > [!TIP] > See: /pohon/getting-started/theme/design-system#color-system > > Learn more about color customization and theming in the Theme section. ### `theme.transitions` Use the `theme.transitions` option to enable or disable transitions on components. - Default: `true` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['pohon-ui'], css: ['~/assets/css/main.css'], ui: { theme: { transitions: false } } }); ``` > [!NOTE] > > This option adds the `transition-colors` class on components with hover or active states. ### `theme.unstyled` Use the `theme.unstyled` option to remove all default theme classes from components, keeping only their structure and the classes you provide through `class`, `ui` or `app.config.ui`. - Default: `false` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['pohon-ui'], css: ['~/assets/css/main.css'], ui: { theme: { unstyled: true } } }); ``` > [!WARNING] > > This strips **structural** classes too (positioning, transitions, flex/grid), not just cosmetic ones. Layout-heavy components like `Modal`, `Drawer` or `Calendar` will need you to re-supply their layout, similar to PrimeVue's unstyled mode. ### `theme.defaultVariants` Use the `theme.defaultVariants` option to override the default `color` and `size` variants for components. Only defaults that are exactly `primary` or `md` are replaced, so Avatar keeps `color: 'neutral'` and Separator keeps `size: 'xs'`. - Default: `{ color: 'primary', size: 'md' }` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['pohon-ui'], css: ['~/assets/css/main.css'], ui: { theme: { defaultVariants: { color: 'neutral', size: 'sm' } } } }); ``` ### `prose` Use the `prose` option to force the import of Pohon UI [`Prose` components](https://vinicunca.dev/pohon/typography) even if `@nuxtjs/mdc`, `@nuxt/content` or `@comark/nuxt` is not installed. - Default: `false` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['pohon-ui'], css: ['~/assets/css/main.css'], ui: { prose: true } }); ``` ### `content` Use the `content` option to force the import of the Pohon UI prose and content components even if `@nuxt/content` is not installed. - Default: `false` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['pohon-ui'], css: ['~/assets/css/main.css'], ui: { content: true } }); ``` ## Continuous releases Pohon UI uses [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases. Automatic preview releases are created for all commits and PRs to the `main` branch. Use them by replacing your package version with the specific commit hash or PR number. ```diff [package.json] { "dependencies": { - "pohon-ui": "^2.0.0-rc", + "pohon-ui": "https://pkg.pr.new/pohon-ui@4c96909", } } ``` > [!NOTE] > > **pkg.pr.new** will automatically comment on PRs with the installation URL, making it easy to test changes. # Installation > Learn how to install and configure Pohon UI in your Vue application, compatible with both plain Vite and Inertia. > [!NOTE] > See: /pohon/getting-started/installation/nuxt > > Looking for the **Nuxt** version? > [!TIP] > See: https://ui.nuxt.com > > Pohon UI is styled with UnoCSS. If your project uses Tailwind CSS, use **Nuxt UI** instead, which also works in plain Vue. ## Setup ### Add to a Vue project #### Install the Pohon UI package ```bash [pnpm] pnpm add pohon-ui unocss @vinicunca/unocss-preset ``` ```bash [yarn] yarn add pohon-ui unocss @vinicunca/unocss-preset ``` ```bash [npm] npm install pohon-ui unocss @vinicunca/unocss-preset ``` ```bash [bun] bun add pohon-ui unocss @vinicunca/unocss-preset ``` #### Add the Pohon UI Vite plugin in your `vite.config.ts` ```ts [vite.config.ts (Vite)] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui() ] }); ``` ```ts [vite.config.ts (Laravel Inertia)] import vue from '@vitejs/plugin-vue'; import laravel from 'laravel-vite-plugin'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), laravel({ input: ['resources/js/app.ts'], refresh: true }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false } } }), ui({ router: 'inertia' }) ] }); ``` ```ts [vite.config.ts (AdonisJS Inertia)] import inertia from '@adonisjs/inertia/client'; import adonisjs from '@adonisjs/vite/client'; import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), adonisjs({ entrypoints: ['inertia/app/app.ts'], reload: ['resources/views/**/*.edge'] }), inertia(), vue(), ui({ router: 'inertia' }) ] }); ``` > [!TIP] > > Pohon UI registers `unplugin-auto-import` and `unplugin-vue-components`, which will generate `auto-imports.d.ts` and `components.d.ts` type declaration files. You will likely want to gitignore these, and add them to your `tsconfig`. > > ```json [tsconfig.app.json] > { > "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "auto-imports.d.ts", "components.d.ts"] > } > ``` > > ```bash [.gitignore] > # Auto-generated type declarations > auto-imports.d.ts > components.d.ts > ``` > [!WARNING] > > These declaration files are only written when Vite runs. The default `create-vue` `build` script runs `vue-tsc` in parallel with `vite build` (`run-p type-check "build-only {@}"`), so on a clean checkout type-checking can start before the files exist and fail with errors like `Cannot find name 'useToast'`. Run the type-check after the build instead so the declarations are generated first. > > ```json [package.json] > { > "scripts": { > "build": "run-s build-only type-check" > } > } > ``` > [!TIP] > > Internally, Pohon UI relies on custom aliases to resolve the theme types. If you're using TypeScript, add these aliases to your `tsconfig` files to enable auto-completion in your `vite.config.ts`. > > ```json [tsconfig.node.json] > { > "compilerOptions": { > "paths": { > "#build/ui": [ > "./node_modules/.pohon-ui/ui" > ] > } > } > } > ``` > > ```json [tsconfig.app.json] > { > "compilerOptions": { > "paths": { > "#build/ui/*": [ > "./node_modules/.pohon-ui/ui/*" > ] > } > } > } > ``` #### Use the Pohon UI Vue plugin ```ts [src/main.ts (Vite)] import ui from 'pohon-ui/vue-plugin'; import { createApp } from 'vue'; import { createRouter, createWebHistory } from 'vue-router'; import App from './App.vue'; const app = createApp(App); const router = createRouter({ routes: [], history: createWebHistory() }); app.use(router); app.use(ui); app.mount('#app'); ``` ```ts [resources/js/app.ts (Laravel Inertia)] import type { DefineComponent } from 'vue'; import { createInertiaApp } from '@inertiajs/vue3'; import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'; import ui from 'pohon-ui/vue-plugin'; import { createApp, h } from 'vue'; const appName = import.meta.env.VITE_APP_NAME || 'Laravel x Pohon UI'; createInertiaApp({ title: (title) => (title ? `${title} - ${appName}` : appName), resolve: (name) => resolvePageComponent( `./pages/${name}.vue`, import.meta.glob('./pages/**/*.vue') ), setup({ el, App, props, plugin }) { createApp({ render: () => h(App, props) }) .use(plugin) .use(ui) .mount(el); } }); ``` ```ts [inertia/app/app.ts (AdonisJS Inertia)] import type { DefineComponent } from 'vue'; import { resolvePageComponent } from '@adonisjs/inertia/helpers'; import { createInertiaApp } from '@inertiajs/vue3'; import ui from 'pohon-ui/vue-plugin'; import { createApp, h } from 'vue'; const appName = import.meta.env.VITE_APP_NAME || 'AdonisJS x Pohon UI'; createInertiaApp({ title: (title) => (title ? `${title} - ${appName}` : appName), resolve: (name) => resolvePageComponent( `../pages/${name}.vue`, import.meta.glob('../pages/**/*.vue') ), setup({ el, App, props, plugin }) { createApp({ render: () => h(App, props) }) .use(plugin) .use(ui) .mount(el); } }); ``` #### Configure UnoCSS ```ts [uno.config.ts] import { presetVinicunca } from '@vinicunca/unocss-preset'; import { pohonColors } from 'pohon-ui/unocss'; import { defineConfig } from 'unocss'; export default defineConfig({ presets: [presetVinicunca()], theme: { colors: pohonColors }, }); ``` Import `virtual:uno.css` in your Vue or Inertia entrypoint before mounting the application: ```ts [src/main.ts] import 'virtual:uno.css'; ``` #### Wrap your app with App component ```vue [src/App.vue (Vite)] ``` ```vue [resources/js/pages/index.vue (Laravel Inertia)] ``` ```vue [inertia/pages/index.vue (AdonisJS Inertia)] ``` > [!NOTE] > See: /pohon/components/app > > The `App` component sets up global config and is required for **Toast**, **Tooltip** and **programmatic overlays**. #### Add the `isolate` class to your root container ```html [index.html (Vite)] Pohon UI
``` ```blade [resources/views/app.blade.php (Laravel Inertia)] @inertiaHead @vite('resources/js/app.ts')
@inertia
``` ```edge [resources/views/inertia_layout.edge (AdonisJS Inertia)] @inertiaHead() @vite(['inertia/app/app.ts', `inertia/pages/${page.component}.vue`]) @inertia({ class: 'isolate' }) ``` > [!NOTE] > > This ensures styles are scoped to your app and prevents issues with overlays and stacking contexts. ### Explore working examples See the [Nuxt playground](https://github.com/vinicunca/pohon/tree/main/playgrounds/nuxt) and [Vue playground](https://github.com/vinicunca/pohon/tree/main/playgrounds/vue) for complete Pohon UI setups. ## Options You can customize Pohon UI by providing options in your `vite.config.ts`. ### `prefix` Use the `prefix` option to change the prefix of the components. - Default: `P` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ prefix: 'Nuxt' }) ] }); ``` ### `ui` Use the `ui` option to provide configuration for Pohon UI. This is the Vue equivalent of the `ui` key in Nuxt's `app.config.ts`. ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ ui: { colors: { primary: 'green', neutral: 'slate' } } }) ] }); ``` ### `dts` Use the `dts` option to enable or disable the generation of declaration files for auto-imported components and composables. - Default: `true` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ dts: false }) ] }); ``` ### `icon` Use the `icon` option to set default props for the [Icon](https://vinicunca.dev/pohon/components/icon) component (`size`, `mode`, `customize`) and to configure build-time icon bundling through `clientBundle`. Bundling of Pohon UI's own icons is enabled by default when their collection is installed. Set `clientBundle: false` to opt out. - Default: `{}` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ icon: { mode: 'svg', clientBundle: { scan: true } } }) ] }); ``` > [!NOTE] > See: /pohon/getting-started/integrations/icons/vue#collections > > Learn more about icon collections and client bundling in the **Icons** documentation. ### `colorMode` Use the `colorMode` option to enable or disable the color mode integration from `@vueuse/core`. - Default: `true` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ colorMode: false }) ] }); ``` ### `theme.colors` Use the `theme.colors` option to define the dynamic color aliases used to generate components theme. - Default: `['primary', 'secondary', 'success', 'info', 'warning', 'error']` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ theme: { colors: ['primary', 'error'] } }) ] }); ``` > [!NOTE] > > Each alias adds a color variant to every component theme that has one, whether your app uses it or not. Trim the list to the aliases you actually use, and keep `error` if you use forms since validation styles rely on it. `primary` is always included. > > The `--ui-color--*` shades themselves are not generated: define them in your CSS (see [CSS Variables](https://vinicunca.dev/pohon/getting-started/theme/css-variables)). > [!TIP] > See: /pohon/getting-started/theme/design-system#color-system > > Learn more about color customization and theming in the Theme section. ### `theme.transitions` Use the `theme.transitions` option to enable or disable transitions on components. - Default: `true` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ theme: { transitions: false } }) ] }); ``` > [!NOTE] > > This option adds the `transition-colors` class on components with hover or active states. ### `theme.unstyled` Use the `theme.unstyled` option to remove all default theme classes from components, keeping only their structure and the classes you provide through `class`, `ui` or `app.config.ui`. - Default: `false` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ theme: { unstyled: true } }) ] }); ``` > [!WARNING] > > This strips **structural** classes too (positioning, transitions, flex/grid), not just cosmetic ones. Layout-heavy components like `Modal`, `Drawer` or `Calendar` will need you to re-supply their layout, similar to PrimeVue's unstyled mode. ### `theme.defaultVariants` Use the `theme.defaultVariants` option to override the default `color` and `size` variants for components. Only defaults that are exactly `primary` or `md` are replaced, so Avatar keeps `color: 'neutral'` and Separator keeps `size: 'xs'`. - Default: `{ color: 'primary', size: 'md' }` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ theme: { defaultVariants: { color: 'neutral', size: 'sm' } } }) ] }); ``` ### `prose` Use the `prose` option to enable Pohon UI [`Prose` components](https://vinicunca.dev/pohon/typography) and their theme. - Default: `false` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ prose: true }) ] }); ``` ### `autoImport` Use the `autoImport` option to disable composable auto-imports or to customize [`unplugin-auto-import`](https://github.com/unplugin/unplugin-auto-import) options. - Default: `{}` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ autoImport: false }) ] }); ``` > [!NOTE] > > When disabled, you can still import composables explicitly from `pohon-ui/composables`. ### `components` Use the `components` option to disable component auto-imports or to customize [`unplugin-vue-components`](https://github.com/unplugin/unplugin-vue-components) options. - Default: `{}` ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ components: false }) ] }); ``` > [!NOTE] > > When disabled, you can still import components explicitly, e.g. `import Button from 'pohon-ui/components/Button.vue'` or `import ProseCode from 'pohon-ui/components/prose/Code.vue'`. ### `router` Use the `router` option to configure routing integration. This is useful for applications that don't use `vue-router`, such as Electron apps, MPAs, or frameworks like [Inertia.js](https://inertiajs.com/) or [Hybridly](https://hybridly.dev/). - Default: `true` | Value | Description | | --- | --- | | `true` | Uses `vue-router` for navigation with `RouterLink` component. | | `false` | Disables routing integration, links render as plain `` tags. | | `'inertia'` | Uses Inertia.js for navigation with its `Link` component. | ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ router: false }) ] }); ``` > [!TIP] > > You can provide custom navigation logic for frameworks like **Hybridly** by setting `router: false` in the Vite config and passing a function when installing the Vue plugin: > > ```ts [src/main.ts] > import { router } from 'hybridly'; > import ui from 'pohon-ui/vue-plugin'; > > app.use(ui, { > router: (event, { href, external }) => { > if (external) { > return; > } > > event.preventDefault(); > > router.navigate({ url: href }); > } > }); > ``` > [!NOTE] > > When set to `false` or `'inertia'`, `vue-router` is not required as a dependency. ### `scanPackages` Use the `scanPackages` option to specify additional npm packages that should be scanned for components using Pohon UI. This is useful when you have a shared component library that uses Pohon UI components internally. ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ UnoCSS(), vue(), ui({ scanPackages: ['@my-org/ui-components'] }) ] }); ``` > [!NOTE] > > By default, only `pohon-ui` is scanned. Use this option when your external packages contain Vue components that use Pohon UI. ### `root` Use the `root` option to override the directory where Pohon UI generates its `.pohon-ui` directory (containing the theme templates). By default it uses Vite's `root`, but in setups like [`electron-vite`](https://electron-vite.org/) the renderer's `root` points to a sub-directory (e.g. `src/renderer`), so the templates land in `src/renderer/node_modules/.pohon-ui` where UnoCSS doesn't scan them, causing theme classes like `bg-background`, `ring-border` and `divide-border` to be missing. ```ts [electron.vite.config.ts] import vue from '@vitejs/plugin-vue'; import { defineConfig } from 'electron-vite'; import ui from 'pohon-ui/vite'; import UnoCSS from 'unocss/vite'; export default defineConfig({ renderer: { root: 'src/renderer', plugins: [ vue(), ui({ root: __dirname }) ] } }); ``` > [!NOTE] > > Point `root` at your project root so the generated `.pohon-ui` directory ends up in a `node_modules` that UnoCSS scans. ## Continuous releases Pohon UI uses [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases. Automatic preview releases are created for all commits and PRs to the `main` branch. Use them by replacing your package version with the specific commit hash or PR number. ```diff [package.json] { "dependencies": { - "pohon-ui": "^2.0.0-rc", + "pohon-ui": "https://pkg.pr.new/pohon-ui@4c96909", } } ``` > [!NOTE] > > **pkg.pr.new** will automatically comment on PRs with the installation URL, making it easy to test changes. # Introduction > Install @vinicunca/eslint-config, a flat ESLint config that lints and formats JavaScript, TypeScript, Vue and more in one call. `@vinicunca/eslint-config` is Vinicunca's shareable [flat config](https://eslint.org/docs/latest/use/configure/configuration-files) for ESLint. It lints **and** formats your code, so you don't need Prettier for JavaScript, TypeScript, Vue, JSON, YAML, TOML or Markdown. > [!NOTE] > > This config is a fork of [antfu/eslint-config](https://github.com/antfu/eslint-config). Most integrations and plugins come from Anthony Fu's work; this fork changes the code style and some defaults. See [Differences from antfu/eslint-config](https://vinicunca.dev/eslint/guides/differences-from-antfu). ## Features - **One call**: `vinicuncaESLint()` returns a complete flat config with sensible defaults. - **Formatting without Prettier**: powered by [ESLint Stylistic](https://eslint.style/), with auto-fix for everything. - **Code style**: 2-space indent, single quotes, semicolons, `} else {` on one line, braces around every block, parentheses around arrow parameters, trailing commas, sorted imports and exports. - **Auto-detected**: TypeScript (when `typescript` is installed), Vue (when `vue`, `nuxt`, `vitepress` or `@slidev/cli` is installed) and pnpm workspace rules (when a `pnpm-workspace.yaml` exists). - **On by default**: JSON, JSONC, JSON5, YAML, TOML, Markdown (including code blocks), test files (via the Vitest plugin), Node.js, JSDoc, regular expressions, [e18e](https://e18e.dev/) modernization rules and [anti-slop rules](https://vinicunca.dev/eslint/configuration/optional-configs#antislop). - **Opt-in**: [React, Next.js, Svelte, Solid, Astro and UnoCSS](https://vinicunca.dev/eslint/configuration/frameworks), [external formatters](https://vinicunca.dev/eslint/configuration/formatters) for CSS/HTML/XML/GraphQL and [type-aware rules](https://vinicunca.dev/eslint/configuration/typescript). - **Respects .gitignore** by default. - Requires ESLint `^10.0.0`. Upgrading from v5? See [Upgrading to v6](https://vinicunca.dev/eslint/guides/migrating#upgrading-from-v5-to-v6). ## Installation ```bash [pnpm] pnpm add -D eslint @vinicunca/eslint-config ``` ```bash [npm] npm install -D eslint @vinicunca/eslint-config ``` ```bash [yarn] yarn add -D eslint @vinicunca/eslint-config ``` ```bash [bun] bun add -d eslint @vinicunca/eslint-config ``` Framework integrations need their own plugins (for example `eslint-plugin-svelte` for Svelte). When you run ESLint in an interactive terminal, the config asks to install any missing plugin for the options you enabled. Each [framework section](https://vinicunca.dev/eslint/configuration/frameworks) lists the exact packages. ## Usage Create `eslint.config.js` in your project root: ```js [eslint.config.js] import { vinicuncaESLint } from '@vinicunca/eslint-config'; export default vinicuncaESLint(); ``` > [!TIP] > > `vinicuncaESLint` is a named export; the package has no default export. If your `package.json` does not set `"type": "module"`, name the file `eslint.config.mjs`. You can also write [`eslint.config.ts`](https://eslint.org/docs/latest/use/configure/configuration-files#typescript-configuration-files) for typed options. Pass options to tune the integrations, and extra flat configs to add your own rules: ```js [eslint.config.js] import { vinicuncaESLint } from '@vinicunca/eslint-config'; export default vinicuncaESLint( { type: 'lib', ignores: ['**/fixtures'], vue: { a11y: true }, }, { files: ['**/*.ts'], rules: { 'ts/no-explicit-any': 'error', }, }, ); ``` See [Configuration](https://vinicunca.dev/eslint/configuration) for how options and extra configs combine, and the [options reference](https://vinicunca.dev/eslint/configuration/options) for every option. ## Scripts Add lint scripts to `package.json`: ```json [package.json] { "scripts": { "lint": "eslint", "lint:fix": "eslint --fix" } } ``` Then run them with your package manager: ```bash pnpm lint pnpm lint:fix ``` > [!NOTE] > > Use `pnpm eslint` (or `npx eslint`) to run the ESLint binary installed in your project. `pnpx eslint` / `pnpm dlx eslint` downloads a separate copy that can't see your local config dependencies. ## Editor setup ### VS Code Install the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint), then add the following to `.vscode/settings.json`: ```jsonc [.vscode/settings.json] { // Disable the default formatter, use ESLint instead "prettier.enable": false, "editor.formatOnSave": false, // Auto fix on save "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit", "source.organizeImports": "never" }, // Silence the stylistic rules in the editor, but still auto fix them "eslint.rules.customizations": [ { "rule": "style/*", "severity": "off", "fixable": true }, { "rule": "format/*", "severity": "off", "fixable": true }, { "rule": "*-indent", "severity": "off", "fixable": true }, { "rule": "*-spacing", "severity": "off", "fixable": true }, { "rule": "*-spaces", "severity": "off", "fixable": true }, { "rule": "*-order", "severity": "off", "fixable": true }, { "rule": "*-dangle", "severity": "off", "fixable": true }, { "rule": "*-newline", "severity": "off", "fixable": true }, { "rule": "*quotes", "severity": "off", "fixable": true }, { "rule": "*semi", "severity": "off", "fixable": true } ], // Enable ESLint for all supported languages "eslint.validate": [ "javascript", "javascriptreact", "typescript", "typescriptreact", "vue", "html", "markdown", "json", "json5", "jsonc", "yaml", "toml", "xml", "gql", "graphql", "astro", "svelte", "css", "less", "scss", "pcss", "postcss" ] } ``` `source.organizeImports` is turned off because import sorting is handled by the `perfectionist/sort-imports` rule. With [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig), enable the ESLint language server for every supported file type and silence stylistic rules while keeping them fixable: ```lua local customizations = { { rule = 'style/*', severity = 'off', fixable = true }, { rule = 'format/*', severity = 'off', fixable = true }, { rule = '*-indent', severity = 'off', fixable = true }, { rule = '*-spacing', severity = 'off', fixable = true }, { rule = '*-spaces', severity = 'off', fixable = true }, { rule = '*-order', severity = 'off', fixable = true }, { rule = '*-dangle', severity = 'off', fixable = true }, { rule = '*-newline', severity = 'off', fixable = true }, { rule = '*quotes', severity = 'off', fixable = true }, { rule = '*semi', severity = 'off', fixable = true }, } local lspconfig = require('lspconfig') lspconfig.eslint.setup({ filetypes = { 'javascript', 'javascriptreact', 'javascript.jsx', 'typescript', 'typescriptreact', 'typescript.tsx', 'vue', 'html', 'markdown', 'json', 'jsonc', 'yaml', 'toml', 'xml', 'gql', 'graphql', 'astro', 'svelte', 'css', 'less', 'scss', 'pcss', 'postcss', }, settings = { rulesCustomizations = customizations, }, -- Fix the buffer before saving on_attach = function(client, bufnr) vim.api.nvim_create_autocmd('BufWritePre', { buffer = bufnr, command = 'EslintFixAll', }) end, }) ``` You can also format on save with [conform.nvim](https://github.com/stevearc/conform.nvim), [none-ls](https://github.com/nvimtools/none-ls.nvim) or [nvim-lint](https://github.com/mfussenegger/nvim-lint). ### Editor-specific behavior The config detects when ESLint runs inside an editor (VS Code, JetBrains IDEs, Vim, Neovim or Zed) and makes three rules non-fixable there, so saving a file doesn't delete code you are still working on: - [`prefer-const`](https://eslint.org/docs/latest/rules/prefer-const) - [`unused-imports/no-unused-imports`](https://github.com/sweepline/eslint-plugin-unused-imports) - `test/no-only-tests` These rules still report problems (as warnings in the editor), and they are fixed normally when you run ESLint from the terminal, in CI or in a git hook. To turn this behavior off, pass `isInEditor: false`: ```js [eslint.config.js] import { vinicuncaESLint } from '@vinicunca/eslint-config'; export default vinicuncaESLint({ isInEditor: false, }); ``` ## Git hooks To lint and fix staged files before every commit, use [lint-staged](https://github.com/lint-staged/lint-staged) with [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks): ```bash [pnpm] pnpm add -D lint-staged simple-git-hooks ``` ```bash [npm] npm install -D lint-staged simple-git-hooks ``` ```bash [yarn] yarn add -D lint-staged simple-git-hooks ``` ```bash [bun] bun add -d lint-staged simple-git-hooks ``` ```json [package.json] { "simple-git-hooks": { "pre-commit": "pnpm lint-staged" }, "lint-staged": { "*": "eslint --fix" } } ``` Then register the hook once: ```bash # Activate the hooks pnpm simple-git-hooks ``` Editor detection is skipped inside git hooks and lint-staged, so every fix is applied on commit. ## Next steps [**Configuration**](https://vinicunca.dev/eslint/configuration) Learn how options, extra configs and the composer API fit together. [**Options reference**](https://vinicunca.dev/eslint/configuration/options) Every option, with its type and default. [**Frameworks**](https://vinicunca.dev/eslint/configuration/frameworks) Enable Vue, React, Next.js, Svelte, Solid, Astro or UnoCSS. [**Agent skill**](https://vinicunca.dev/.well-known/skills/eslint-config/SKILL.md) Conventions for AI agents writing code linted by this config. --- - [GitHub](https://github.com/vinicunca/eslint-config) - [npm](https://www.npmjs.com/package/@vinicunca/eslint-config) # Introduction > Taman is a full-stack Vue admin template you own after generate — published @vinicunca packages keep receiving updates. Taman is an admin-app **monorepo template** plus a set of published npm packages. You generate a project with `pnpm create taman my-app`, then own every file in that tree. Only `@vinicunca/*` packages keep receiving updates via `pnpm update`. It is for teams that want a Vue 3 SPA, a Cloudflare-ready API, contract-first RPC, auth with organizations, and Postgres — without starting from a blank repo. ## What you get **Vue admin SPA** Vite 8, vue-router 5, Pinia 4, vue-i18n 11, TanStack Vue Query and Vue Form, Zod 4, AG Grid. UI is [Pohon](https://vinicunca.dev/pohon/getting-started) + [Akar](https://vinicunca.dev/akar/overview) + [UnoCSS](https://vinicunca.dev/unocss-preset/getting-started). **Nitro API on Workers** Standalone Nitro v3 beta built as `cloudflare-module`. Durable Object publisher, email queues, and a `send_email` binding. **Auth and orgs** better-auth 1.7 with the admin and organization/teams plugins, Google OAuth, and email verification. **Postgres + Drizzle** Postgres 18 via Docker Compose (host port `5437`, database `taman_db`) and Drizzle ORM. ## Stack | Layer | Choice | | --- | --- | | Web | Vue 3.5 SPA, Vite 8, vue-router 5, Pinia 4 (`persistedstate` + `secure-ls`), vue-i18n 11, TanStack Vue Query + Vue Form, Zod 4, AG Grid | | UI | pohon-ui, akar, UnoCSS with `@vinicunca/unocss-preset` | | API | Nitro v3 beta, Cloudflare Workers (`cloudflare-module`) | | RPC | Contract-first oRPC 1.15 | | Auth | better-auth 1.7 (admin + organization/teams, Google OAuth, email verification) | | Data | Postgres 18, drizzle-orm 0.45, drizzle-kit 0.31 | | Email | Maizzle templates, Cloudflare Email Routing or console in dev | | Tooling | nx, pnpm 12, vitest, Playwright, changesets, commitlint | ## Layout of a generated project - `apps/web` (`@/web`) — Vue admin app - `apps/api` (`@/api`) — Nitro API - `packages/shell/*` — browser packages (access, app-ui, composables, designs, layouts, locales, stores, types, utils) - `packages/server/*` — `db-pg` and `emails` - `packages/shared/*` — `api-contract`, `rbac`, `constants` - Published packages stay on npm: `@vinicunca/taman-core`, `@vinicunca/taman-ui`, `@vinicunca/request`, plus `@vinicunca/{vite-config,tsconfig,node-utils,commitlint-config}` The template repo also contains `packages/{taman-core,taman-ui,request,create-taman}` and `internal/*`. Those are **removed** from generated projects and installed from npm instead. ## Published packages Current versions on npm: 0.1.0 for the Taman packages (0.1.1 for `@vinicunca/taman-ui`) and 1.0.1 for the tooling packages. | Package | Role | | --- | --- | | `create-taman` | CLI that scaffolds the monorepo | | `@vinicunca/taman-core` | Utils, cache, preferences, typings, composables | | `@vinicunca/taman-ui` | Admin components, forms, dialogs, layout, menu, tabs | | `@vinicunca/request` | oRPC and REST clients with TanStack Query helpers | | `@vinicunca/vite-config` | Opinionated Vite config for the web app | | `@vinicunca/tsconfig` | Shared TypeScript configs | | `@vinicunca/node-utils` | Node helpers used by tooling | | `@vinicunca/commitlint-config` | Conventional commits + workspace scopes | See [Packages](https://vinicunca.dev/taman/packages) for API reference. ## Who this is for - You want a **shadcn-style** starter: generated code is yours to change. - You are fine with **no optional feature flags** — the CLI always emits the same stack. - You will add product features by copying the **todo** walkthrough (contract → schema → repo/service → RPC → page). > [!NOTE] > > The generated web app has a login page and the todo reference feature. There are **no** profile, onboarding, or organization-management views yet. The API already runs better-auth's organization plugin; the client does not install `organizationClient`. See [Authentication](https://vinicunca.dev/taman/guides/authentication-and-organizations). # Introduction > Install @vinicunca/perkakas, a typed utility library with data-first and data-last APIs, pipes, and lazy evaluation. `@vinicunca/perkakas` is a TypeScript utility library. Every helper is written in TypeScript, so types are part of the implementation rather than a later add-on. You can call the same function **data-first** (data as the first argument) or **data-last** (to drop into a [`pipe`](https://vinicunca.dev/perkakas/functions#pipe)). It is a fork of [Remeda](https://remeda.org). The runtime API is the Remeda surface plus a few Perkakas-only helpers. The one rename to know: Remeda's `purry` is [`curry`](https://vinicunca.dev/perkakas/functions#curry) here. ## Installation ```bash [pnpm] pnpm add @vinicunca/perkakas ``` ```bash [npm] npm install @vinicunca/perkakas ``` ```bash [yarn] yarn add @vinicunca/perkakas ``` ```bash [bun] bun add @vinicunca/perkakas ``` Import the functions you need. Tree-shaking drops the rest. ```ts import { filter, map, pipe } from '@vinicunca/perkakas'; ``` ## Data-first and data-last Libraries like Lodash put data first (`_.pick(obj, keys)`). Ramda puts data last (`R.pick(keys, obj)`). Perkakas ships **both** on the same import. Data-first is the usual call. Data-last omits the data argument and returns a function — that is what you pass to `pipe`. ```ts import { pick, pipe } from '@vinicunca/perkakas'; pick(obj, ['firstName', 'lastName']); // data-first pipe(obj, pick(['firstName', 'lastName'])); // data-last ``` Data-first is kinder to autocomplete: your editor already knows the object's keys when you type the second argument. ```ts import { filter, groupBy, pipe } from '@vinicunca/perkakas'; const DATA = [ { name: 'john', age: 20, gender: 'm' }, { name: 'marry', age: 22, gender: 'f' }, { name: 'samara', age: 24, gender: 'f' }, { name: 'bill', age: 33, gender: 'm' } ]; pipe( DATA, filter((x) => x.gender === 'f'), groupBy((x) => x.age) ); ``` ## Pipe [`pipe`](https://vinicunca.dev/perkakas/functions#pipe) runs functions left to right. You read the transformation in the order it runs, without naming every intermediate value. ```ts import { filter, map, pipe } from '@vinicunca/perkakas'; pipe( [1, 2, 3, 4], filter((n) => n % 2 === 0), map((n) => n * 2) ); // => [4, 8] ``` Any function that takes one argument works in a pipe, not only Perkakas helpers. Wrap other calls in an arrow if they are not data-last: `($) => validate($, CONFIG)`. A headless variant, [`piped`](https://vinicunca.dev/perkakas/functions#piped), builds a reusable pipeline without the initial data. ## Lazy evaluation When consecutive **lazy** helpers sit in a `pipe` in their data-last form (`map`, `filter`, `take`, `unique`, and others tagged Lazy on the [Functions](https://vinicunca.dev/perkakas/functions) page), Perkakas walks items one at a time. Later steps can stop early so the rest of the input is never visited. ```ts import { map, pipe, take, unique } from '@vinicunca/perkakas'; pipe( [1, 2, 2, 3, 3, 4, 5, 6], map((x) => { console.log('iterate', x); return x; }), unique(), take(3) ); // => [1, 2, 3] // Console: // iterate 1 // iterate 2 // iterate 2 // iterate 3 ``` To force eager evaluation of a lazy helper, call it data-first inside an arrow: `($) => map($, callback)` instead of `map(callback)`. ## Type guards Functions in the Guard category are type predicates. After `isString(value)` (or `filter(isString)`), TypeScript narrows the value to `string`. ```ts import { filter, isString } from '@vinicunca/perkakas'; isString('ok'); // => true isString(1); // => false filter(['a', 1, 'b'], isString); // => ['a', 'b'] ``` - [`hasProp`](https://vinicunca.dev/perkakas/functions#hasProp) — Checks if `data` has a prop `key`. - [`hasSubObject`](https://vinicunca.dev/perkakas/functions#hasSubObject) — Checks if `subObject` is a sub-object of `object`, which means for every - [`isArray`](https://vinicunca.dev/perkakas/functions#isArray) — A function that checks if the passed parameter is an Array and narrows its type accordingly. - [`isBigInt`](https://vinicunca.dev/perkakas/functions#isBigInt) — A function that checks if the passed parameter is a bigint and narrows its - [`isBoolean`](https://vinicunca.dev/perkakas/functions#isBoolean) — A function that checks if the passed parameter is a boolean and narrows its type accordingly. - [`isDate`](https://vinicunca.dev/perkakas/functions#isDate) — A function that checks if the passed parameter is a Date and narrows its type accordingly. - [`isDeepEqual`](https://vinicunca.dev/perkakas/functions#isDeepEqual) — Performs a *deep structural* comparison between two values to determine if - [`isDefined`](https://vinicunca.dev/perkakas/functions#isDefined) — A function that checks if the passed parameter is defined (`!== undefined`) - [`isEmpty`](https://vinicunca.dev/perkakas/functions#isEmpty) — A function that checks if the passed parameter is empty. - [`isEmptyish`](https://vinicunca.dev/perkakas/functions#isEmptyish) — A function that checks if the input is empty. Empty is defined as anything - [`isError`](https://vinicunca.dev/perkakas/functions#isError) — A function that checks if the passed parameter is an Error and narrows its type accordingly. - [`isFunction`](https://vinicunca.dev/perkakas/functions#isFunction) — A function that checks if the passed parameter is a Function and narrows its type accordingly. - [`isIncludedIn`](https://vinicunca.dev/perkakas/functions#isIncludedIn) — Checks if the item is included in the container. This is a wrapper around - [`isNonNull`](https://vinicunca.dev/perkakas/functions#isNonNull) — A function that checks if the passed parameter is not `null` and narrows its type accordingly. - [`isNonNullish`](https://vinicunca.dev/perkakas/functions#isNonNullish) — A function that checks if the passed parameter is defined *AND* isn't `null` - [`isNot`](https://vinicunca.dev/perkakas/functions#isNot) — A function that takes a guard function as predicate and returns a guard that negates it. - [`isNullish`](https://vinicunca.dev/perkakas/functions#isNullish) — A function that checks if the passed parameter is either `null` or - [`isNumber`](https://vinicunca.dev/perkakas/functions#isNumber) — A function that checks if the passed parameter is a number and narrows its - [`isObjectType`](https://vinicunca.dev/perkakas/functions#isObjectType) — Checks if the given parameter is of type `"object"` via `typeof`, excluding `null`. - [`isPlainObject`](https://vinicunca.dev/perkakas/functions#isPlainObject) — Checks if `data` is a "plain" object. A plain object is defined as an object with string keys and values of any type, including primitives, other objects, functions, classes, etc (aka struct/shape/record/simple). Technically, a plain object is one whose prototype is either `Object.prototype` or `null`, ensuring it does not inherit properties or methods from other object types. - [`isPromise`](https://vinicunca.dev/perkakas/functions#isPromise) — A function that checks if the passed parameter is a Promise and narrows its type accordingly. - [`isShallowEqual`](https://vinicunca.dev/perkakas/functions#isShallowEqual) — Performs a *shallow structural* comparison between two values to determine if - [`isStrictEqual`](https://vinicunca.dev/perkakas/functions#isStrictEqual) — Determines whether two values are *functionally identical* in all contexts. - [`isString`](https://vinicunca.dev/perkakas/functions#isString) — A function that checks if the passed parameter is a string and narrows its type accordingly. - [`isSymbol`](https://vinicunca.dev/perkakas/functions#isSymbol) — A function that checks if the passed parameter is a symbol and narrows its type accordingly. - [`isTruthy`](https://vinicunca.dev/perkakas/functions#isTruthy) — A function that checks if the passed parameter is truthy and narrows its type accordingly. ## Types that stay strict Helpers are written so mapped tuples stay tuples, and filters keep the narrowed type. You often do not need extra libraries just to get the type you already expected. ```ts import { map } from '@vinicunca/perkakas'; const DATA = [1, 2, 3] as const; DATA.map((x) => x.toString()); // => string[] map(DATA, (x) => x.toString()); // => [string, string, string] ``` ## Next - Browse every export on the [Functions](https://vinicunca.dev/perkakas/functions) page (search and jump by category). - Switching from Remeda, Lodash, Ramda, or Just? Start at [Migrate](https://vinicunca.dev/perkakas/migrate). --- - [GitHub](https://github.com/vinicunca/perkakas) - [npm](https://www.npmjs.com/package/@vinicunca/perkakas) # Introduction > Unstyled, accessible Vue primitives for building design systems and web apps. Akar is an open-source library of unstyled, accessible Vue primitives. Use the parts as the foundation of a design system, or adopt them one component at a time. It started as a fork of [Reka UI](https://reka-ui.com) (itself descended from [Radix Vue](https://www.radix-vue.com/)) and is published as the `akar` package. Component names match Reka's (`AccordionRoot`, `DialogTrigger`, no prefix). Style them with whatever CSS you already use. ## Why a fork? Akar is the foundation of [Pohon UI](https://vinicunca.dev/pohon/getting-started). Owning the primitives lets the Vinicunca ecosystem move at its own pace: - **Ship fixes when Pohon needs them.** Accessibility and behavior fixes land in Akar and release right away, without waiting on an upstream review cycle. - **Add primitives Pohon builds on.** Akar includes parts such as [Field](https://vinicunca.dev/akar/components/field), [Form](https://vinicunca.dev/akar/components/form), [Tag Group](https://vinicunca.dev/akar/components/tag-group), and a [toast](https://vinicunca.dev/akar/components/toast) manager. - **Share one toolchain.** Akar uses the same utilities ([Perkakas](https://github.com/vinicunca/perkakas)), release workflow, and docs as the rest of Vinicunca, so versions stay in step. The API stays close to Reka's on purpose. Moving from `reka-ui` or `radix-vue` is mostly an import swap; see the [migration guide](https://vinicunca.dev/akar/guides/migration). ## Principles ### Accessibility first Components follow [WAI-ARIA design patterns](https://www.w3.org/WAI/ARIA/apg/). Akar handles aria attributes, keyboard navigation, and focus management so you can concentrate on layout and visuals. ### Unstyled and open Nothing ships with opinions about color, spacing, or typography. Wrap, extend, or restyle every part. See the [styling](https://vinicunca.dev/akar/guides/styling) and [composition](https://vinicunca.dev/akar/guides/composition) guides. ### Controlled or uncontrolled Primitives work uncontrolled out of the box (`defaultValue`) and accept `v-model` when you need to own the state. See [controlled state](https://vinicunca.dev/akar/guides/controlled-state). ### Predictable API Every part that renders a DOM node accepts `as` / `asChild`. The library is fully typed and tree-shaken: unused components do not land in the bundle. ## Start here [**Getting started**](https://vinicunca.dev/akar/overview/getting-started) Install Akar and assemble a Popover in a few minutes. [**Installation**](https://vinicunca.dev/akar/overview/installation) Package install, the Nuxt module, and the unplugin resolver. [**Components**](https://vinicunca.dev/akar/components) Sixty primitives covering overlays, forms, dates, menus, and more. [**Guides**](https://vinicunca.dev/akar/guides) Composition, styling, animation, dates, i18n, SSR, and virtualization. ## Credits Akar is a fork of [Reka UI](https://reka-ui.com). Reka UI is MIT-licensed. Further upstream inspiration: - [Radix UI](https://www.radix-ui.com) - [React Aria](https://react-spectrum.adobe.com/react-aria) - [Floating UI](https://floating-ui.com) - [VueUse](https://vueuse.org) - [Headless UI](https://headlessui.com) - [Ariakit](https://ariakit.org) --- - [GitHub](https://github.com/vinicunca/akar) - [npm](https://www.npmjs.com/package/akar) # Introduction > First-class variants, slots, and compound styles for UnoCSS — a port of Tailwind Variants that leaves conflict resolution to the CSS cascade. **UnoCSS Variants** (`unocss-variants`) is a first-class variant API for [UnoCSS](https://unocss.dev/). You define a component recipe once — base styles, variants, defaults, slots, and compound rules — and call it anywhere with typed props. It is a port of [Tailwind Variants](https://www.tailwind-variants.org/). The important difference: **classes are never merged**. Conflicting utilities stay in the class string; you resolve them with UnoCSS [layers](https://vinicunca.dev/unocss-variants/concepts/layers) and the CSS cascade. > [!NOTE] > > `uv(options)` takes **one** argument. There is no config object, no `twMerge`, no `/lite` build, and no responsive-variant map. Put breakpoint prefixes such as `md:` in the class strings yourself. ## Why UnoCSS Variants **One recipe, many call sites** Change `color` or `size` at the call site instead of editing long class strings. **Slots for multi-part UI** Cards, alerts, and pagination get named parts, each with its own classes and variants. **Compound rules** Apply extra classes when several variant keys match, or to several slots at once. **TypeScript-first** Infer call-site props with `VariantProps`. Slotted recipes return typed slot functions. ## Key features ### Variants Define axes like `color`, `size`, or boolean flags such as `disabled`. Combine them independently. ```vue ``` ```vue ``` ```ts button({ size: 'sm', color: 'secondary' }); // font-medium bg-blue-500 color-white rounded-full active:opacity-80 bg-purple-500 color-white text-sm px-3 py-1 ``` Every class is kept, including both `bg-blue-500` from `base` and `bg-purple-500` from the variant. See [Layers](https://vinicunca.dev/unocss-variants/concepts/layers) for how to make the variant win. See [Variants](https://vinicunca.dev/unocss-variants/concepts/variants) for boolean variants, compound variants, and defaults. ### Slots Split a component into named parts and style each one. ```vue ``` See [Slots](https://vinicunca.dev/unocss-variants/concepts/slots). ### Overrides Pass `class` or `className` when you call the recipe. The extra classes are **appended** — they do not replace conflicting utilities. ```ts button({ color: 'secondary', class: 'bg-pink-500 hover:bg-pink-500' }); // font-semibold color-white py-1 px-3 rounded-full active:opacity-80 bg-purple-500 hover:bg-purple-700 bg-pink-500 hover:bg-pink-500 ``` See [Overriding styles](https://vinicunca.dev/unocss-variants/concepts/overriding-styles). ### Composition `extend` merges another recipe's `base`, `slots`, `variants`, `defaultVariants`, `compoundVariants`, and `compoundSlots`. ```vue ``` Child classes that must win over the parent should use the `uno-layer-uv:` prefix. See [Composing components](https://vinicunca.dev/unocss-variants/concepts/composing-components) and [Layers](https://vinicunca.dev/unocss-variants/concepts/layers). ## What is not included - **No class merging** — unlike default Tailwind Variants, `uv` never drops conflicting utilities. - **No second config argument** — and no `createTV` / `twMerge` / `cnMerge`. - **No /lite entry** — there is a single build. - **No responsiveVariants map** — write `sm:` / `md:` in the class strings. - **No breakpoint autocompletion** — TypeScript completes variant keys and slot names, not media queries. Coming from Tailwind Variants? Read the [migration guide](https://vinicunca.dev/unocss-variants/guides/migration). ## Credits UnoCSS Variants is a fork of [Tailwind Variants](https://www.tailwind-variants.org/). Credit to the original authors, and to [Stitches](https://stitches.dev/) and [CVA](https://cva.style/) for the variant model. --- - [Source](https://github.com/praburangki/unocss-variants) - [npm](https://www.npmjs.com/package/unocss-variants) # Components > Unstyled, accessible Vue primitives. Sixty components covering overlays, forms, dates, menus, and more. Each page includes anatomy, API tables generated from Akar v2.0.20 source, keyboard interactions, and a CSS demo when one exists. [**Accordion**](https://vinicunca.dev/akar/components/accordion) A vertically stacked set of interactive headings that each reveal an associated section of content. [**Alert Dialog**](https://vinicunca.dev/akar/components/alert-dialog) A modal dialog that interrupts the user with important content and expects a response. [**Aspect Ratio**](https://vinicunca.dev/akar/components/aspect-ratio) Displays content within a desired ratio. [**Autocomplete**](https://vinicunca.dev/akar/components/autocomplete) An input with suggestions that allows free-form text entry. Unlike Combobox, the value is the input text itself rather than a selected item. [**Avatar**](https://vinicunca.dev/akar/components/avatar) An image element with a fallback for representing the user. [**Calendar**](https://vinicunca.dev/akar/components/calendar) Displays dates and days of the week, facilitating date-related interactions. [**Checkbox**](https://vinicunca.dev/akar/components/checkbox) A control that allows the user to toggle between checked and not checked. [**Collapsible**](https://vinicunca.dev/akar/components/collapsible) An interactive component which expands/collapses a panel. [**Color Area**](https://vinicunca.dev/akar/components/color-area) A two-dimensional area for selecting color values in a specific color space. [**Color Field**](https://vinicunca.dev/akar/components/color-field) An input field for entering and editing color values in various formats. [**Color Slider**](https://vinicunca.dev/akar/components/color-slider) A slider control for adjusting individual color channels. [**Color Swatch Picker**](https://vinicunca.dev/akar/components/color-swatch-picker) A component that allows users to select from a set of predefined colors, often used for themes or branding. [**Color Swatch**](https://vinicunca.dev/akar/components/color-swatch) A predefined color block that allows users to quickly select commonly used or brand-specific colors. [**Combobox**](https://vinicunca.dev/akar/components/combobox) Choose from a list of suggested values with full keyboard support. [**Context Menu**](https://vinicunca.dev/akar/components/context-menu) Displays a menu located at the pointer, triggered by a right-click or a long-press. [**Date Field**](https://vinicunca.dev/akar/components/date-field) Enables users to input specific dates within a designated field. [**Date Picker**](https://vinicunca.dev/akar/components/date-picker) Facilitates the selection of dates through an input and calendar-based interface. [**Date Range Field**](https://vinicunca.dev/akar/components/date-range-field) Allows users to input a range of dates within a designated field. [**Date Range Picker**](https://vinicunca.dev/akar/components/date-range-picker) Facilitates the selection of date ranges through an input and calendar-based interface. [**Dialog**](https://vinicunca.dev/akar/components/dialog) A window overlaid on either the primary window or another dialog window, rendering the content underneath inert. [**Drawer**](https://vinicunca.dev/akar/components/drawer) A panel that slides in from the edge of the screen, with support for swipe-to-dismiss, snap points, and nested drawers. [**Dropdown Menu**](https://vinicunca.dev/akar/components/dropdown-menu) Displays a menu to the user—such as a set of actions or functions—triggered by a button. [**Editable**](https://vinicunca.dev/akar/components/editable) Displays an input field used for editing a single line of text, rendering as static text on load. [**Field**](https://vinicunca.dev/akar/components/field) Accessible wiring between a label, control, description, and error message, with built-in validation. [**Form**](https://vinicunca.dev/akar/components/form) Extends the native form element with server error display and submit-time validation gating. [**Hover Card**](https://vinicunca.dev/akar/components/hover-card) For sighted users to preview content available behind a link. [**Label**](https://vinicunca.dev/akar/components/label) Renders an accessible label associated with controls. [**Listbox**](https://vinicunca.dev/akar/components/listbox) A control that allows the user to toggle between checked and not checked. [**Menubar**](https://vinicunca.dev/akar/components/menubar) A visually persistent menu common in desktop applications that provides quick [**MonthPicker**](https://vinicunca.dev/akar/components/month-picker) Presents a calendar view tailored for selecting months. [**MonthRangePicker**](https://vinicunca.dev/akar/components/month-range-picker) Presents a calendar view tailored for selecting month ranges. [**Navigation Menu**](https://vinicunca.dev/akar/components/navigation-menu) A collection of links for navigating websites. [**Number Field**](https://vinicunca.dev/akar/components/number-field) A number field allows a user to enter a number and increment or decrement the value using stepper buttons. [**Pagination**](https://vinicunca.dev/akar/components/pagination) Displays data in paged format and provides navigation between pages. [**Pin Input**](https://vinicunca.dev/akar/components/pin-input) A sequence of one-character alphanumeric inputs. [**Popover**](https://vinicunca.dev/akar/components/popover) Displays rich content in a portal, triggered by a button. [**Progress**](https://vinicunca.dev/akar/components/progress) Displays an indicator showing the completion progress of a task, typically displayed as a progress bar. [**Radio Group**](https://vinicunca.dev/akar/components/radio-group) A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time. [**RangeCalendar**](https://vinicunca.dev/akar/components/range-calendar) Presents a calendar view tailored for selecting date ranges. [**Rating**](https://vinicunca.dev/akar/components/rating) A star-rating input where the user selects a score, with support for fractional values. [**Scroll Area**](https://vinicunca.dev/akar/components/scroll-area) Augments native scroll functionality for custom, cross-browser styling. [**Select**](https://vinicunca.dev/akar/components/select) Displays a list of options for the user to pick from—triggered by a button. [**Separator**](https://vinicunca.dev/akar/components/separator) Visually or semantically separates content. [**Slider**](https://vinicunca.dev/akar/components/slider) An input where the user selects a value from within a given range. [**Splitter**](https://vinicunca.dev/akar/components/splitter) A component that divides your layout into resizable sections. [**Stepper**](https://vinicunca.dev/akar/components/stepper) A set of steps that are used to indicate progress through a multi-step process. [**Switch**](https://vinicunca.dev/akar/components/switch) A control that allows the user to toggle between checked and not checked. [**Tabs**](https://vinicunca.dev/akar/components/tabs) A set of layered sections of content—known as tab panels—that are displayed one at a time. [**Tag Group**](https://vinicunca.dev/akar/components/tag-group) A focusable list of tags that can be navigated, selected and removed with the keyboard. [**Tags Input**](https://vinicunca.dev/akar/components/tags-input) Tags input render tags inside an input, followed by an actual text input. [**Time Field**](https://vinicunca.dev/akar/components/time-field) Enables users to input specific times within a designated field. [**Time Range Field**](https://vinicunca.dev/akar/components/time-range-field) Allows users to input a range of times within a designated field. [**Toast**](https://vinicunca.dev/akar/components/toast) A succinct message that is displayed temporarily. [**Toggle Group**](https://vinicunca.dev/akar/components/toggle-group) A set of two-state buttons that can be toggled on or off. [**Toggle**](https://vinicunca.dev/akar/components/toggle) A two-state button that can be either on or off. [**Toolbar**](https://vinicunca.dev/akar/components/toolbar) A container for grouping a set of controls, such as buttons, toggle groups or dropdown menus. [**Tooltip**](https://vinicunca.dev/akar/components/tooltip) A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it. [**Tree**](https://vinicunca.dev/akar/components/tree) A tree view widget displays a hierarchical list of items that can be expanded or collapsed to show or hide their child items, such as in a file system navigator. [**YearPicker**](https://vinicunca.dev/akar/components/year-picker) Presents a calendar view tailored for selecting years. [**YearRangePicker**](https://vinicunca.dev/akar/components/year-range-picker) Presents a calendar view tailored for selecting year ranges. # Accordion > A vertically stacked set of interactive headings that each reveal an associated section of content. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Accordion) { /* reset */ button, h3 { all: unset; } .AccordionRoot { border-radius: 6px; width: 300px; background-color: var(--mauve-6); box-shadow: 0 2px 10px var(--black-a4); } .AccordionItem { overflow: hidden; margin-top: 1px; } .AccordionItem:first-child { margin-top: 0; border-top-left-radius: 4px; border-top-right-radius: 4px; } .AccordionItem:last-child { border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; } .AccordionItem:focus-within { position: relative; z-index: 1; box-shadow: 0 0 0 2px var(--mauve-12); } .AccordionHeader { display: flex; } .AccordionTrigger { font-family: inherit; background-color: transparent; padding: 0 20px; height: 45px; flex: 1; display: flex; align-items: center; justify-content: space-between; font-size: 15px; line-height: 1; color: var(--grass-11); box-shadow: 0 1px 0 var(--mauve-6); background-color: white; } .AccordionTrigger:hover { background-color: var(--mauve-2); } .AccordionContent { overflow: hidden; font-size: 15px; color: var(--mauve-11); background-color: var(--mauve-2); } .AccordionContent[data-state='open'] { animation: slideDown 300ms cubic-bezier(0.87, 0, 0.13, 1); } .AccordionContent[data-state='closed'] { animation: slideUp 300ms cubic-bezier(0.87, 0, 0.13, 1); } .AccordionContentText { padding: 15px 20px; } .AccordionChevron { color: var(--grass-10); transition: transform 300ms cubic-bezier(0.87, 0, 0.13, 1); } .AccordionTrigger[data-state='open'] > .AccordionChevron { transform: rotate(180deg); } @keyframes slideDown { from { height: 0; } to { height: var(--akar-accordion-content-height); } } @keyframes slideUp { from { height: var(--akar-accordion-content-height); } to { height: 0; } } } ``` ## Features - Full keyboard navigation. - Supports horizontal/vertical orientation. - Supports Right to Left direction. - Can expand one or multiple items. - Can be controlled or uncontrolled. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of an Accordion **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `collapsible` | `false` | `boolean` | When type is "single", allows closing content when clicking trigger for an open item.
When type is "multiple", this prop has no effect. | | `defaultValue` | | `T` | The default active value of the item(s).

Use when you do not need to control the state of the item(s). | | `dir` | `"ltr"` | `"ltr" \| "rtl"` | The reading direction of the accordion when applicable. If omitted, assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the accordion and all its items | | `modelValue` | | `T` | The controlled value of the active item(s).

Use this when you need to control the state of the items. Can be binded with `v-model` | | `orientation` | `"vertical"` | `"vertical" \| "horizontal"` | The orientation of the accordion. | | `type` | | `"single" \| "multiple"` | Determines whether a "single" or "multiple" items can be selected at a time.

This prop will overwrite the inferred type from `modelValue` and `defaultValue`. | | `unmountOnHide` | `true` | `boolean` | When `true`, the element will be unmounted on closed state. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `value: (ExplicitType extends "single" ? string : string[])` | Event handler called when the expanded state of an item changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `AcceptableValue \| AcceptableValue[]` | Current active value | [AccordionRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Accordion/AccordionRoot.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Item Contains all the parts of a collapsible section. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | `false` | `boolean` | Whether or not an accordion item is disabled from user interaction.
When `true`, prevents the user from interacting with the item. | | `unmountOnHide` | | `boolean` | When `true`, the element will be unmounted on closed state. | | `value*` | | `string` | A string value for the accordion item. All items within an accordion should use a unique value. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | [AccordionItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Accordion/AccordionItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Header Wraps an `AccordionTrigger`. Use the `asChild` prop to update it to the appropriate heading level for your page. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"h3"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [AccordionHeader.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Accordion/AccordionHeader.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Trigger Toggles the collapsed state of its associated item. It should be nested inside of an `AccordionHeader`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [AccordionTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Accordion/AccordionTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Content Contains the collapsible content for an item. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [AccordionContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Accordion/AccordionContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | | CSS variable | Description | | --- | --- | | `--akar-accordion-content-width` | The width of the content when it opens/closes | | `--akar-accordion-content-height` | The height of the content when it opens/closes | ## Examples ### Expanded by default Use the `defaultValue` prop to define the open item by default. ```vue ``` ### Allow collapsing all items Use the `collapsible` prop to allow all items to close. ```vue ``` ### Multiple items open at the same time Set the `type` prop to `multiple` to enable opening multiple items at once. ```vue ``` ### Rotated icon when open You can add extra decorative elements, such as chevrons, and rotate it when the item is open. ```vue // index.vue ``` ```css /* styles.css */ .AccordionChevron { transition: transform 300ms; } .AccordionTrigger[data-state="open"] > .AccordionChevron { transform: rotate(180deg); } ``` ### Horizontal orientation Use the `orientation` prop to create a horizontal Accordion ```vue ``` ### Animating content size Use the `--akar-accordion-content-width` and/or `--akar-accordion-content-height` CSS variables to animate the size of the content when it opens/closes: ```vue // index.vue ``` ```css /* styles.css */ .AccordionContent { overflow: hidden; } .AccordionContent[data-state="open"] { animation: slideDown 300ms ease-out; } .AccordionContent[data-state="closed"] { animation: slideUp 300ms ease-out; } @keyframes slideDown { from { height: 0; } to { height: var(--akar-accordion-content-height); } } @keyframes slideUp { from { height: var(--akar-accordion-content-height); } to { height: 0; } } ``` ### Render content even when closed By default hidden content will be removed, use `:unmountOnHide="false"` to keep the content always available. This will also allow browser to search the hidden text, and open the accordion. ```vue ``` ## Accessibility Adheres to the [Accordion WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion). ### Keyboard Interactions | Key | Description | | --- | --- | | Space | When focus is on an `AccordionTrigger` of a collapsed section, expands the section. | | Enter | When focus is on an `AccordionTrigger` of a collapsed section, expands the section. | | Tab | Moves focus to the next focusable element. | | Shift + Tab | Moves focus to the previous focusable element. | | ArrowDown | Moves focus to the next `AccordionTrigger` when `orientation` is `vertical`. | | ArrowUp | Moves focus to the previous `AccordionTrigger` when `orientation` is `vertical`. | | ArrowRight | Moves focus to the next `AccordionTrigger` when `orientation` is `horizontal`. | | ArrowLeft | Moves focus to the previous `AccordionTrigger` when `orientation` is `horizontal`. | | Home | When focus is on an `AccordionTrigger`, moves focus to the start `AccordionTrigger`. | | End | When focus is on an `AccordionTrigger`, moves focus to the last `AccordionTrigger`. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/accordion) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Accordion) - [npm](https://www.npmjs.com/package/akar) # Alert Dialog > A modal dialog that interrupts the user with important content and expects a response. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/red.css'; @import '../_colors/green.css'; @scope (.akar-demo-AlertDialog) { /* reset */ button { all: unset; } .AlertDialogOverlay { background-color: var(--black-a9); position: fixed; inset: 0; animation: overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1); } .AlertDialogContent { background-color: white; border-radius: 6px; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90vw; max-width: 500px; max-height: 85vh; padding: 25px; animation: contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1); } .AlertDialogContent:focus { outline: none; } .AlertDialogTitle { margin: 0; color: var(--mauve-12); font-size: 17px; font-weight: 500; } .AlertDialogDescription { margin-bottom: 20px; color: var(--mauve-11); font-size: 15px; line-height: 1.5; } .Button { display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; padding: 0 15px; font-size: 15px; line-height: 1; font-weight: 500; height: 35px; } .Button.green { background-color: white; color: var(--green-11); box-shadow: 0 2px 10px var(--black-a7); } .Button.green:hover { background-color: var(--mauve-3); } .Button.green:focus { box-shadow: 0 0 0 2px black; } .Button.red { background-color: var(--red-4); color: var(--red-11); } .Button.red:hover { background-color: var(--red-5); } .Button.red:focus { box-shadow: 0 0 0 2px var(--red-7); } .Button.mauve { background-color: var(--mauve-4); color: var(--mauve-11); } .Button.mauve:hover { background-color: var(--mauve-5); } .Button.mauve:focus { box-shadow: 0 0 0 2px var(--mauve-7); } @keyframes overlayShow { from { opacity: 0; } to { opacity: 1; } } @keyframes contentShow { from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); } to { opacity: 1; transform: translate(-50%, -50%) scale(1); } } } ``` ## Features - Focus is automatically trapped. - Can be controlled or uncontrolled. - Manages screen reader announcements with `Title` and `Description` components. - Esc closes the component automatically. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of an alert dialog. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defaultOpen` | | `boolean` | The open state of the dialog when it is initially rendered. Use when you do not need to control its open state. | | `open` | | `boolean` | The controlled open state of the dialog. Can be binded as `v-model:open`. | | `unmountOnHide` | `true` | `boolean` | When set to `false`, the dialog content will not be unmounted when closed, but instead hidden with CSS.

Useful for SEO or when you want to improve performance by not remounting the component on every open. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `value: boolean` | Event handler called when the open state of the dialog changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | | `close` | `(): void` | Close the dialog | [AlertDialogRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AlertDialog/AlertDialogRoot.vue) ### Trigger A button that opens the dialog. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [AlertDialogTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AlertDialog/AlertDialogTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### Portal When used, portals your overlay and content parts into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [AlertDialogPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AlertDialog/AlertDialogPortal.vue) ### Overlay A layer that covers the inert portion of the view when the dialog is open. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [AlertDialogOverlay.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AlertDialog/AlertDialogOverlay.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### Content Contains content to be rendered when the dialog is open. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disableOutsidePointerEvents` | | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside
the `DismissableLayer`. Users will need to click twice on outside elements to
interact with them: once to close the `DismissableLayer`, and again to trigger the element. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | Event handler called when auto-focusing on open.
Can be prevented. | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [AlertDialogContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AlertDialog/AlertDialogContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### Cancel A button that closes the dialog. This button should be distinguished visually from `AlertDialogAction` buttons. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [AlertDialogCancel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AlertDialog/AlertDialogCancel.vue) ### Action A button that closes the dialog. These buttons should be distinguished visually from the `AlertDialogCancel` button. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [AlertDialogAction.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AlertDialog/AlertDialogAction.vue) ### Title An accessible name to be announced when the dialog is opened. Alternatively, you can provide `aria-label` or `aria-labelledby` to `AlertDialogContent` and exclude this component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"h2"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [AlertDialogTitle.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AlertDialog/AlertDialogTitle.vue) ### Description An accessible description to be announced when the dialog is opened. Alternatively, you can provide `aria-describedby` to `AlertDialogContent` and exclude this component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"p"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [AlertDialogDescription.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AlertDialog/AlertDialogDescription.vue) ## Examples ### Close after asynchronous form submission Use the controlled props to programmatically close the Alert Dialog after an async operation has completed. ```vue ``` :br### Custom portal container Customise the element that your alert dialog portals into. ```vue ``` ## Accessibility Adheres to the [Alert and Message Dialogs WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog). ### Keyboard Interactions | Key | Description | | --- | --- | | Space | Opens/closes the dialog. | | Enter | Opens/closes the dialog. | | Tab | Moves focus to the next focusable element. | | Shift + Tab | Moves focus to the previous focusable element. | | Esc | Closes the dialog and moves focus to `AlertDialogTrigger`. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AlertDialog) - [npm](https://www.npmjs.com/package/akar) # Aspect Ratio > Displays content within a desired ratio. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @scope (.akar-demo-AspectRatio) { .Container { width: 300px; border-radius: 6px; overflow: hidden; box-shadow: 0 2px 10px var(--black-a7); } .Image { object-fit: cover; width: 100%; height: 100%; } } ``` ## Features - Accepts any custom ratio. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import the component. ```vue ``` ## API Reference ### Root Contains the content you want to constrain to a given ratio. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `ratio` | `1` | `number` | The desired ratio. Eg: 16/9 | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `aspect` | `number` | Current aspect ratio (in %) | [AspectRatio.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AspectRatio/AspectRatio.vue) --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/AspectRatio) - [npm](https://www.npmjs.com/package/akar) # Autocomplete > An input with suggestions that allows free-form text entry. Unlike Combobox, the value is the input text itself rather than a selected item. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Autocomplete) { /* reset */ button, input { all: unset; } .AutocompleteRoot { position: relative; } .AutocompleteAnchor { display: inline-flex; align-items: center; justify-content: space-between; font-size: 13px; line-height: 1; height: 35px; padding: 0 15px; gap: 5px; background-color: white; color: var(--grass-11); border-radius: 4px; box-shadow: 0 2px 10px var(--black-a7); } .AutocompleteAnchor:hover { background-color: var(--mauve-3); } .AutocompleteInput { height: 100%; background-color: transparent; color: var(--grass-11); } .AutocompleteInput[data-placeholder] { color: var(--grass-9); } .AutocompleteIcon { width: 16px; height: 16px; color: var(--grass-11); } .AutocompleteContent { z-index: 10; width: 100%; position: absolute; overflow: hidden; background-color: white; border-radius: 6px; margin-top: 8px; box-shadow: 0px 10px 38px -10px rgb(22 23 24 / 35%), 0px 10px 20px -15px rgb(22 23 24 / 20%); } .AutocompleteViewport { padding: 5px; } .AutocompleteEmpty { padding-top: 0.5rem; padding-bottom: 0.5rem; text-align: center; font-size: 0.75rem; line-height: 1rem; font-weight: 500; color: var(--mauve-11); } .AutocompleteItem { font-size: 13px; line-height: 1; color: var(--grass-11); border-radius: 3px; display: flex; align-items: center; height: 25px; padding: 0 35px 0 25px; position: relative; user-select: none; } .AutocompleteItem[data-disabled] { color: var(--mauve-8); pointer-events: none; } .AutocompleteItem[data-highlighted] { outline: none; background-color: var(--grass-9); color: var(--grass-1); } .AutocompleteLabel { padding: 0 25px; font-size: 12px; line-height: 25px; color: var(--mauve-11); } .AutocompleteSeparator { height: 1px; background-color: var(--grass-6); margin: 5px; } } ``` ## Features - Can be controlled or uncontrolled. - Offers 2 positioning modes. - Supports items, labels, groups of items. - Focus is fully managed. - Full keyboard navigation. - Supports custom placeholder. - Supports Right to Left direction. - Free-form text input — value is the typed text, not a selection. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## Autocomplete vs. Combobox The Autocomplete component is similar to the [Combobox](https://vinicunca.dev/akar/components/combobox) but with a key difference: | | Autocomplete | Combobox | | --- | --- | --- | | **`modelValue`** | The input text (`string`) | The selected item (`AcceptableValue`) | | **Free-form text** | Yes — any text is valid | No — must select from the list | | **`multiple`** | Not supported | Supported | | **Input on blur** | Retains typed text by default | Resets to selected value by default | | **Item selection** | Fills the input with the item's text value | Sets `modelValue` to the item's value | Use **Autocomplete** when the user should be able to type anything with optional suggestions. Use **Combobox** when the user must pick from a predefined set of options. ## API Reference ### Root Contains all the parts of an Autocomplete. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `defaultOpen` | | `boolean` | The open state of the autocomplete when it is initially rendered. Use when you do not need to control its open state. | | `defaultValue` | | `string` | The value of the autocomplete when initially rendered. Use when you do not need to control the state. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the autocomplete when applicable. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with autocomplete | | `highlightOnHover` | `true` | `boolean` | When `true`, hover over item will trigger highlight | | `ignoreFilter` | | `boolean` | When `true`, disable the default filters | | `modelValue` | | `string` | The controlled value of the Autocomplete (the input text). Can be bound with `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `open` | | `boolean` | The controlled open state of the Autocomplete. Can be bound with `v-model:open`. | | `openOnClick` | `false` | `boolean` | Whether to open the autocomplete when the input is clicked | | `openOnFocus` | `false` | `boolean` | Whether to open the autocomplete when the input is focused | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `resetSearchTermOnBlur` | `false` | `boolean` | Whether to reset the searchTerm when the Autocomplete input blurred | **Events** | Event | Payload | Description | | --- | --- | --- | | `highlight` | `payload: { ref: HTMLElement; value: string; }` | Event handler when highlighted element changes. | | `update:modelValue` | `value: string` | Event handler called when the value changes. | | `update:open` | `value: boolean` | Event handler called when the open state of the autocomplete changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | | `modelValue` | `string` | Current active value | [AutocompleteRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Autocomplete/AutocompleteRoot.vue) ### Anchor Used as an anchor if you set `AutocompleteContent`'s position to `popper`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `reference` | | `ReferenceElement` | The reference (or anchor) element that is being referred to for positioning.

If not provided will use the current component as anchor. | [ComboboxAnchor.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxAnchor.vue) ### Input The input component to search through the autocomplete items. Typing updates the `modelValue` directly. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `autoFocus` | | `boolean` | Focus on element when mounted. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with item | | `modelValue` | | `string` | The controlled value of the filter. Can be binded with v-model. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `string` | | [AutocompleteInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Autocomplete/AutocompleteInput.vue) ### Trigger The button that toggles the Autocomplete Content. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with item | [ComboboxTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | ### Cancel The button that clears the input text and resets the value. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [ComboboxCancel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxCancel.vue) ### Empty Shown when none of the items match the query. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [ComboboxEmpty.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxEmpty.vue) ### Portal When used, portals the content part into the `body`. You need to set `position="popper"` for `AutocompleteContent` to make sure the position was automatically computed similar to `Popover` or `DropdownMenu`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [ComboboxPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxPortal.vue) ### Content The component that pops out when the autocomplete is open. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.
May change when collisions occur. | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `bodyLock` | | `boolean` | The document.body will be lock, and scrolling will be disabled. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the popper content when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disableOutsidePointerEvents` | | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside
the `DismissableLayer`. Users will need to click twice on outside elements to
interact with them: once to close the `DismissableLayer`, and again to trigger the element. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `hideWhenEmpty` | `false` | `boolean` | When `true`, hides the content when there are no items matching the filter. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `position` | | `"inline" \| "popper"` | The positioning mode to use,

`inline` is the default and you can control the position using CSS.

`popper` positions content in the same way as our other primitives, for example `Popover` or `DropdownMenu`. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `present` | | `boolean` | Whether this kept-mounted content is currently visible. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.
Will be reversed when collisions occur and avoidCollisions
is enabled. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [ComboboxContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | `[data-empty]` | Present when there are no items matching the filter | | CSS variable | Description | | --- | --- | | `--akar-combobox-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets. Only present when `position="popper"`. | | `--akar-combobox-content-available-width` | The remaining width between the trigger and the boundary edge. Only present when `position="popper"`. | | `--akar-combobox-content-available-height` | The remaining height between the trigger and the boundary edge. Only present when `position="popper"`. | | `--akar-combobox-trigger-width` | The width of the trigger. Only present when `position="popper"`. | | `--akar-combobox-trigger-height` | The height of the trigger. Only present when `position="popper"`. | ### Viewport The scrolling viewport that contains all of the items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `nonce` | | `string` | Will add `nonce` attribute to the style tag which can be used by Content Security Policy.

If omitted, inherits globally from `ConfigProvider`. | [ComboboxViewport.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxViewport.vue) ### Item The component that contains the autocomplete items. When selected, the item's string value fills the input. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `textValue` | | `string` | A string representation of the item contents.

If the children are not plain text, then the `textValue` prop must also be set to a plain text representation, which will be used for autocomplete in the ComboBox. | | `value*` | | `T` | The value given as data when submitted with a `name`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: SelectEvent` | Event handler called when the selecting item.

It can be prevented by calling `event.preventDefault`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `selected` | `boolean` | Whether the item is currently selected | [ComboboxItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### Group Used to group multiple items. Use in conjunction with `AutocompleteLabel` to ensure good accessibility via automatic labelling. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [ComboboxGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxGroup.vue) ### Label Used to render the label of a group. It won't be focusable using arrow keys. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `for` | | `string` | | [ComboboxLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxLabel.vue) ### Separator Used to visually separate items in the Autocomplete. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [ComboboxSeparator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxSeparator.vue) ### Arrow An optional arrow element to render alongside the content. This can be used to help visually link the trigger with the `AutocompleteContent`. Must be rendered inside `AutocompleteContent`. Only available when `position` is set to `popper`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` | | `width` | `10` | `number` | The width of the arrow in pixels. | [ComboboxArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxArrow.vue) ### Virtualizer Virtual container to achieve list virtualization. See the [virtualization guide](https://vinicunca.dev/akar/guides/virtualization.md) for more general info on virtualization. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `estimateSize` | | `number \| ((index: number) => number)` | Estimated size (in px) of each item | | `options*` | | `T` | List of items | | `overscan` | | `number` | Number of items rendered outside the visible area | | `textContent` | | `((option: T) => string)` | Text content for each item to achieve type-ahead feature | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `option` | `T` | | | `virtualizer` | `Virtualizer` | | | `virtualItem` | `VirtualItem` | | [ComboboxVirtualizer.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxVirtualizer.vue) ## Examples ### Basic usage The `modelValue` is a string that reflects whatever the user types. Selecting an item fills the input with that item's text. ```vue ``` ### Hide menu when empty Use the `hideWhenEmpty` prop on `AutocompleteContent` to hide the menu when no items match the filter. ```vue ``` ### With form submission The Autocomplete value is submitted as a regular text field in forms. ```vue ``` ## Accessibility Adheres to the [Combobox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox). ### Keyboard Interactions | Key | Description | | --- | --- | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/combobox) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Autocomplete) - [npm](https://www.npmjs.com/package/akar) # Avatar > An image element with a fallback for representing the user. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Avatar) { .AvatarRoot { display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; overflow: hidden; user-select: none; width: 45px; height: 45px; border-radius: 100%; background-color: var(--black-a3); } .AvatarImage { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; } .AvatarFallback { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background-color: white; color: var(--grass-11); font-size: 15px; line-height: 1; font-weight: 500; } } ``` ## Features - Automatic and manual control over when the image renders. - Fallback part accepts any children. - Optionally delay fallback rendering to avoid content flashing. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of an avatar **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [AvatarRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Avatar/AvatarRoot.vue) ### Image The image to render. By default it will only render when it has loaded. You can use the `@loadingStatusChange` handler if you need more control. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"img"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `crossOrigin` | | `"" \| "anonymous" \| "use-credentials"` | | | `referrerPolicy` | | `"" \| "no-referrer" \| "no-referrer-when-downgrade" \| "origin" \| "origin-when-cross-origin" \| "same-origin" \| "strict-origin" \| "strict-origin-when-cross-origin" \| "unsafe-url"` | | | `src*` | | `string` | | **Events** | Event | Payload | Description | | --- | --- | --- | | `loadingStatusChange` | `value: ImageLoadingStatus` | A callback providing information about the loading status of the image.

This is useful in case you want to control more precisely what to render as the image is loading. | [AvatarImage.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Avatar/AvatarImage.vue) ### Fallback An element that renders when the image hasn't loaded. This means whilst it's loading, or if there was an error. If you notice a flash during loading, you can provide a `delayMs` prop to delay its rendering so it only renders for those with slower connections. For more control, use the `@loadingStatusChange` emit on `AvatarImage`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `delayMs` | | `number` | Useful for delaying rendering so it only appears for those with slower connections. | [AvatarFallback.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Avatar/AvatarFallback.vue) ## Examples ### Clickable Avatar with tooltip You can compose the Avatar with a [Tooltip](https://vinicunca.dev/akar/components/tooltip) to display extra information. ```vue ``` --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Avatar) - [npm](https://www.npmjs.com/package/akar) # Calendar > Displays dates and days of the week, facilitating date-related interactions. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Calendar) { .Icon { width: 1.5rem; height: 1.5rem; } .Calendar { margin-top: 1.5rem; border-width: 1px; border-color: #000000; background-color: #ffffff; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); padding: 22px; } .CalendarHeader { display: flex; justify-content: space-between; align-items: center; } .CalendarNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2.5rem; height: 2.5rem; color: #000000; background-color: transparent; cursor: pointer; } .CalendarNavButton:hover { color: #ffffff; background-color: #000000; } .CalendarHeading { font-weight: 500; color: #000000; } .CalendarWrapper { display: flex; padding-top: 1rem; margin-top: 1rem; flex-direction: column; } @media (min-width: 640px) { .CalendarWrapper { margin-left: 1rem; margin-top: 0; flex-direction: row; } } .CalendarGrid { margin-top: 0.25rem; width: 100%; user-select: none; border-collapse: collapse; } .CalendarGridRow { display: grid; margin-bottom: 0.25rem; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; } .CalendarGridRow[data-reka-calendar-month-view] { grid-template-columns: repeat(7, minmax(0, 1fr)); } .CalendarHeadCell { border-radius: 0.375rem; font-size: 0.75rem; line-height: 1rem; color: #000000; font-weight: 400; } .CalendarCell { position: relative; font-size: 0.875rem; line-height: 1.25rem; text-align: center; } .CalendarCellTrigger { display: flex; position: relative; padding: 0.5rem; justify-content: center; align-items: center; border-width: 1px; border-color: transparent; outline-style: none; font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; color: #000000; white-space: nowrap; background-color: transparent; } .CalendarCellTrigger:hover { border-color: #000000; } .CalendarCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .CalendarCellTrigger[data-disabled] { cursor: none; color: rgba(0,0,0,0.3); } .CalendarCellTrigger[data-selected] { background-color: #000000; color: #ffffff; font-weight: 500; } .CalendarCellTrigger[data-selected]::before { background-color: #FFFFFF; } .CalendarCellTrigger[data-unavailable] { color: rgba(0,0,0,0.3); text-decoration: line-through; } .CalendarCellTrigger::before { content: ''; position: absolute; top: 5px; left: 0; width: 0.25rem; height: 0.25rem; border-radius: 9999px; background-color: #FFFFFF; } .CalendarCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Highly composable ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a calendar **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `calendarLabel` | | `string` | The accessible label for the calendar | | `defaultPlaceholder` | | `DateValue` | The default placeholder date | | `defaultValue` | | `DateValue` | The default value for the calendar | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the calendar when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | Whether the calendar is disabled | | `disableDaysOutsideCurrentView` | `false` | `boolean` | Whether or not to disable days outside the current view. | | `fixedWeeks` | `false` | `boolean` | Whether or not to always display 6 weeks in the calendar | | `initialFocus` | `false` | `boolean` | If true, the calendar will focus the selected day, today, or the first day of the month depending on what is visible when the calendar is mounted | | `isDateDisabled` | | `Matcher` | A function that returns whether or not a date is disabled | | `isDateUnavailable` | | `Matcher` | A function that returns whether or not a date is unavailable | | `locale` | | `string` | The locale to use for formatting dates | | `maxValue` | | `DateValue` | The maximum date that can be selected | | `minValue` | | `DateValue` | The minimum date that can be selected | | `modelValue` | | `DateValue \| DateValue[] \| null` | The controlled selected date value of the calendar. Can be bound as `v-model`. | | `multiple` | `false` | `boolean` | Whether multiple dates can be selected | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the next page of the calendar. It receives the current placeholder as an argument inside the component. | | `numberOfMonths` | `1` | `number` | The number of months to display at once | | `pagedNavigation` | `false` | `boolean` | This property causes the previous and next buttons to navigate by the number of months displayed at once, rather than one month | | `placeholder` | | `DateValue` | The placeholder date, which is used to determine what month to display when no date is selected | | `preventDeselect` | `false` | `boolean` | Whether or not to prevent the user from deselecting a date without selecting another date first | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the previous page of the calendar. It receives the current placeholder as an argument inside the component. | | `readonly` | `false` | `boolean` | Whether the calendar is readonly | | `weekdayFormat` | `"narrow"` | `"narrow" \| "short" \| "long"` | The format to use for the weekday strings provided via the weekdays slot prop | | `weekStartsOn` | | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | The day of the week to start the calendar on | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: DateValue` | Event handler called whenever the model value changes | | `update:placeholder` | `date: DateValue` | Event handler called whenever the placeholder value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `date` | `DateValue` | The current date of the placeholder | | `grid` | `Grid[]` | The grid of dates | | `weekDays` | `string[]` | The days of the week | | `weekStartsOn` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | The start of the week | | `locale` | `string` | The calendar locale | | `fixedWeeks` | `boolean` | Whether or not to always display 6 weeks in the calendar | | `modelValue` | `DateValue \| DateValue[]` | The current date of the calendar | [CalendarRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarRoot.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Header Contains the navigation buttons and the heading segments. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [CalendarHeader.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarHeader.vue) ### Prev Button Calendar navigation button. It navigates the calendar one month/year/decade in the past based on the current calendar view. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the prev page. Overwrites the `prevPage` function set on the `CalendarRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [CalendarPrev.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarPrev.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Next Button Calendar navigation button. It navigates the calendar one month/year/decade in the future based on the current calendar view. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the next page. Overwrites the `nextPage` function set on the `CalendarRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [CalendarNext.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarNext.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Heading Heading for displaying the current month and year **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `headingValue` | `string` | Current month and year | [CalendarHeading.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarHeading.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Grid Container for wrapping the calendar grid. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"table"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [CalendarGrid.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarGrid.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | ### Grid Head Container for wrapping the grid head. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"thead"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [CalendarGridHead.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarGridHead.vue) ### Grid Body Container for wrapping the grid body. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tbody"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [CalendarGridBody.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarGridBody.vue) ### Grid Row Container for wrapping the grid row. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tr"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [CalendarGridRow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarGridRow.vue) ### Head Cell Container for wrapping the head cell. Used for displaying the week days. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"th"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [CalendarHeadCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarHeadCell.vue) ### Cell Container for wrapping the calendar cells. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"td"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `date*` | | `DateValue` | The date value for the cell | [CalendarCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarCell.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Cell Trigger Interactable container for displaying the cell dates. Clicking it selects the date. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `day*` | | `DateValue` | The date value provided to the cell trigger | | `month*` | | `DateValue` | The month in which the cell is rendered | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `dayValue` | `string` | Current day | | `disabled` | `boolean` | Current disable state | | `selected` | `boolean` | Current selected state | | `today` | `boolean` | Current today state | | `outsideView` | `boolean` | Current outside view state | | `outsideVisibleView` | `boolean` | Current outside visible view state | | `unavailable` | `boolean` | Current unavailable state | [CalendarCellTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar/CalendarCellTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-selected]` | Present when selected | | `[data-value]` | The ISO string value of the date. | | `[data-disabled]` | Present when disabled | | `[data-unavailable]` | Present when unavailable | | `[data-today]` | Present when today | | `[data-outside-view]` | Present when the date is outside the current month it is displayed in. | | `[data-outside-visible-view]` | Present when the date is outside the months that are visible on the calendar. | | `[data-focused]` | Present when focused | ## Examples ### Calendar with Year Incrementation This example showcases a calendar which allows incrementing the year. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-CalendarYearIncrement) { .Icon { width: 1.5rem; height: 1.5rem; } .Calendar { margin-top: 1.5rem; border-width: 1px; border-color: #000000; background-color: #ffffff; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); padding: 22px; } .CalendarHeader { display: flex; justify-content: space-between; align-items: center; } .CalendarNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2.5rem; height: 2.5rem; color: #000000; background-color: transparent; cursor: pointer; } .CalendarNavButton:hover { color: #ffffff; background-color: #000000; } .CalendarHeading { font-weight: 500; color: #000000; color: 15px; } .CalendarWrapper { display: flex; padding-top: 1rem; margin-top: 1rem; flex-direction: column; } @media (min-width: 640px) { .CalendarWrapper { margin-left: 1rem; margin-top: 0; flex-direction: row; } } .CalendarGrid { margin-top: 0.25rem; width: 100%; user-select: none; border-collapse: collapse; } .CalendarGridRow { display: grid; margin-bottom: 0.25rem; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; } .CalendarGridRow[data-reka-calendar-month-view] { grid-template-columns: repeat(7, minmax(0, 1fr)); } .CalendarHeadCell { border-radius: 0.375rem; font-size: 0.75rem; line-height: 1rem; color: #000000; font-weight: 400; } .CalendarCell { position: relative; font-size: 0.875rem; line-height: 1.25rem; text-align: center; } .CalendarCellTrigger { display: flex; position: relative; padding: 0.5rem; justify-content: center; align-items: center; border-width: 1px; border-color: transparent; outline-style: none; font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; color: #000000; white-space: nowrap; background-color: transparent; } .CalendarCellTrigger:hover { border-color: #000000; } .CalendarCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .CalendarCellTrigger[data-disabled] { cursor: none; color: rgba(0,0,0,0.3); } .CalendarCellTrigger[data-selected] { background-color: #000000; color: #ffffff; font-weight: 500; } .CalendarCellTrigger[data-selected]::before { background-color: #FFFFFF; } .CalendarCellTrigger[data-unavailable] { color: rgba(0,0,0,0.3); text-decoration: line-through; } .CalendarCellTrigger::before { content: ''; position: absolute; top: 5px; left: 0; width: 0.25rem; height: 0.25rem; border-radius: 9999px; background-color: #FFFFFF; } .CalendarCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } /* reset */ button { all: unset; } .Wrapper { display: flex; flex-direction: column; gap: 1rem; } .Label { color: #fff; } .SelectTrigger { display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; padding: 0 15px; font-size: 13px; line-height: 1; height: 35px; gap: 5px; background-color: white; color: var(--grass-11); box-shadow: 0 2px 10px var(--black-a7); } .SelectTrigger:hover { background-color: var(--mauve-3); } .SelectTrigger:focus { box-shadow: 0 0 0 2px black; } .SelectTrigger[data-placeholder] { color: var(--grass-9); } .SelectIcon { color: Var(--grass-11); } .SelectContent { overflow: hidden; background-color: white; border-radius: 6px; box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2); } .SelectViewport { padding: 5px; } .SelectItem { font-size: 13px; line-height: 1; color: var(--grass-11); border-radius: 3px; display: flex; align-items: center; height: 25px; padding: 0 35px 0 25px; position: relative; user-select: none; } .SelectItem[data-disabled] { color: var(--mauve-8); pointer-events: none; } .SelectItem[data-highlighted] { outline: none; background-color: var(--grass-9); color: var(--grass-1); } .SelectLabel { padding: 0 25px; font-size: 12px; line-height: 25px; color: var(--mauve-11); } .SelectSeparator { height: 1px; background-color: var(--grass-6); margin: 5px; } .SelectItemIndicator { position: absolute; left: 0; width: 25px; display: inline-flex; align-items: center; justify-content: center; } .SelectScrollButton { display: flex; align-items: center; justify-content: center; height: 25px; background-color: white; color: var(--grass-11); cursor: default; } } ``` ### Calendar with Locale and Calendar System Selection This example showcases some of the available locales and how the calendar systems are displayed. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-CalendarSelect) { .Icon { width: 1.5rem; height: 1.5rem; } .Calendar { margin-top: 1.5rem; border-width: 1px; border-color: #000000; background-color: #ffffff; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); padding: 22px; } .CalendarHeader { display: flex; justify-content: space-between; align-items: center; } .CalendarNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2.5rem; height: 2.5rem; color: #000000; background-color: transparent; cursor: pointer; } .CalendarNavButton:hover { color: #ffffff; background-color: #000000; } .CalendarHeading { font-weight: 500; color: #000000; color: 15px; } .CalendarWrapper { display: flex; padding-top: 1rem; margin-top: 1rem; flex-direction: column; } @media (min-width: 640px) { .CalendarWrapper { margin-left: 1rem; margin-top: 0; flex-direction: row; } } .CalendarGrid { margin-top: 0.25rem; width: 100%; user-select: none; border-collapse: collapse; } .CalendarGridRow { display: grid; margin-bottom: 0.25rem; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; } .CalendarGridRow[data-reka-calendar-month-view] { grid-template-columns: repeat(7, minmax(0, 1fr)); } .CalendarHeadCell { border-radius: 0.375rem; font-size: 0.75rem; line-height: 1rem; color: #000000; font-weight: 400; } .CalendarCell { position: relative; font-size: 0.875rem; line-height: 1.25rem; text-align: center; } .CalendarCellTrigger { display: flex; position: relative; padding: 0.5rem; justify-content: center; align-items: center; border-width: 1px; border-color: transparent; outline-style: none; font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; color: #000000; white-space: nowrap; background-color: transparent; } .CalendarCellTrigger:hover { border-color: #000000; } .CalendarCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .CalendarCellTrigger[data-disabled] { cursor: none; color: rgba(0,0,0,0.3); } .CalendarCellTrigger[data-selected] { background-color: #000000; color: #ffffff; font-weight: 500; } .CalendarCellTrigger[data-selected]::before { background-color: #FFFFFF; } .CalendarCellTrigger[data-unavailable] { color: rgba(0,0,0,0.3); text-decoration: line-through; } .CalendarCellTrigger::before { content: ''; position: absolute; top: 5px; left: 0; width: 0.25rem; height: 0.25rem; border-radius: 9999px; background-color: #FFFFFF; } .CalendarCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } /* reset */ button { all: unset; } .Wrapper { display: flex; flex-direction: column; gap: 1rem; } .Label { color: #fff; } .SelectTrigger { display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; padding: 0 15px; font-size: 13px; line-height: 1; height: 35px; gap: 5px; background-color: white; color: var(--grass-11); box-shadow: 0 2px 10px var(--black-a7); } .SelectTrigger:hover { background-color: var(--mauve-3); } .SelectTrigger:focus { box-shadow: 0 0 0 2px black; } .SelectTrigger[data-placeholder] { color: var(--grass-9); } .SelectIcon { color: Var(--grass-11); } .SelectContent { overflow: hidden; background-color: white; border-radius: 6px; box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2); } .SelectViewport { padding: 5px; } .SelectItem { font-size: 13px; line-height: 1; color: var(--grass-11); border-radius: 3px; display: flex; align-items: center; height: 25px; padding: 0 35px 0 25px; position: relative; user-select: none; } .SelectItem[data-disabled] { color: var(--mauve-8); pointer-events: none; } .SelectItem[data-highlighted] { outline: none; background-color: var(--grass-9); color: var(--grass-1); } .SelectLabel { padding: 0 25px; font-size: 12px; line-height: 25px; color: var(--mauve-11); } .SelectSeparator { height: 1px; background-color: var(--grass-6); margin: 5px; } .SelectItemIndicator { position: absolute; left: 0; width: 25px; display: inline-flex; align-items: center; justify-content: center; } .SelectScrollButton { display: flex; align-items: center; justify-content: center; height: 25px; background-color: white; color: var(--grass-11); cursor: default; } } ``` ### Calendar swipe gesture navigation This component demonstrates intuitive calendar navigation using touch-based swipe gestures, user-friendly way to browse through months. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-CalendarSwipe) { .Icon { width: 1.5rem; height: 1.5rem; } .Calendar { margin-top: 1.5rem; border-width: 1px; border-color: #000000; background-color: #ffffff; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); padding: 22px; } .CalendarHeader { display: flex; justify-content: space-between; align-items: center; } .CalendarNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2.5rem; height: 2.5rem; color: #000000; background-color: transparent; cursor: pointer; } .CalendarNavButton:hover { color: #ffffff; background-color: #000000; } .CalendarHeading { font-weight: 500; color: #000000; } .CalendarWrapper { display: flex; padding-top: 1rem; margin-top: 1rem; flex-direction: column; } @media (min-width: 640px) { .CalendarWrapper { margin-left: 1rem; margin-top: 0; flex-direction: row; } } .CalendarGrid { margin-top: 0.25rem; width: 100%; user-select: none; border-collapse: collapse; } .CalendarGridRow { display: grid; margin-bottom: 0.25rem; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; } .CalendarGridRow[data-reka-calendar-month-view] { grid-template-columns: repeat(7, minmax(0, 1fr)); } .CalendarHeadCell { border-radius: 0.375rem; font-size: 0.75rem; line-height: 1rem; color: #000000; font-weight: 400; } .CalendarCell { position: relative; font-size: 0.875rem; line-height: 1.25rem; text-align: center; } .CalendarCellTrigger { display: flex; position: relative; padding: 0.5rem; justify-content: center; align-items: center; border-width: 1px; border-color: transparent; outline-style: none; font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; color: #000000; white-space: nowrap; background-color: transparent; } .CalendarCellTrigger:hover { border-color: #000000; } .CalendarCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .CalendarCellTrigger[data-disabled] { cursor: none; color: rgba(0,0,0,0.3); } .CalendarCellTrigger[data-selected] { background-color: #000000; color: #ffffff; font-weight: 500; } .CalendarCellTrigger[data-selected]::before { background-color: #FFFFFF; } .CalendarCellTrigger[data-unavailable] { color: rgba(0,0,0,0.3); text-decoration: line-through; } .CalendarCellTrigger::before { content: ''; position: absolute; top: 5px; left: 0; width: 0.25rem; height: 0.25rem; border-radius: 9999px; background-color: #FFFFFF; } .CalendarCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } } ``` ### Calendar week numbers This example showcases usage of the CalendarWeek component used to display the number of the week. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-CalendarWeeks) { .Icon { width: 1.5rem; height: 1.5rem; } .Calendar { margin-top: 1.5rem; border-width: 1px; border-color: #000000; background-color: #ffffff; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); padding: 22px; } .CalendarHeader { display: flex; justify-content: space-between; align-items: center; } .CalendarNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2.5rem; height: 2.5rem; color: #000000; background-color: transparent; cursor: pointer; } .CalendarNavButton:hover { color: #ffffff; background-color: #000000; } .CalendarHeading { font-weight: 500; color: #000000; color: 15px; } .CalendarWrapper { display: flex; padding-top: 1rem; margin-top: 1rem; flex-direction: column; } @media (min-width: 640px) { .CalendarWrapper { margin-left: 1rem; margin-top: 0; flex-direction: row; } } .CalendarGrid { margin-top: 0.25rem; width: 100%; user-select: none; border-collapse: collapse; } .CalendarGridRow { display: grid; margin-bottom: 0.25rem; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; } .CalendarGridRow[data-reka-calendar-month-view] { grid-template-columns: repeat(8, minmax(0, 1fr)); } .CalendarHeadCell { border-radius: 0.375rem; font-size: 0.75rem; line-height: 1rem; color: #000000; font-weight: 400; } .CalendarWeek { display: flex; justify-content: center; align-items: center; font-size: 0.875rem; line-height: 1.25rem; } .CalendarCell { position: relative; font-size: 0.875rem; line-height: 1.25rem; text-align: center; } .CalendarCellTrigger { display: flex; position: relative; padding: 0.5rem; justify-content: center; align-items: center; border-width: 1px; border-color: transparent; outline-style: none; font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; color: #000000; white-space: nowrap; background-color: transparent; } .CalendarCellTrigger:hover { border-color: #000000; } .CalendarCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .CalendarCellTrigger[data-disabled] { cursor: none; color: rgba(0,0,0,0.3); } .CalendarCellTrigger[data-selected] { background-color: #000000; color: #ffffff; font-weight: 500; } .CalendarCellTrigger[data-selected]::before { background-color: #FFFFFF; } .CalendarCellTrigger[data-unavailable] { color: rgba(0,0,0,0.3); text-decoration: line-through; } .CalendarCellTrigger::before { content: ''; position: absolute; top: 5px; left: 0; width: 0.25rem; height: 0.25rem; border-radius: 9999px; background-color: #FFFFFF; } .CalendarCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } /* reset */ button { all: unset; } } ``` ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the calendar, focuses the first navigation button. | | Space | When the focus is on either `CalendarNext` or `CalendarPrev`, it navigates the calendar. Otherwise, it selects the date. | | Enter | When the focus is on either `CalendarNext` or `CalendarPrev`, it navigates the calendar. Otherwise, it selects the date. | | ArrowLeft / ArrowRight / ArrowUp / ArrowDown | When the focus is on `CalendarCellTrigger`, it navigates the dates, changing the month/year/decade if necessary. | | Home | When the focus is on `CalendarCellTrigger`, it moves focus to the first day of the current week. | | End | When the focus is on `CalendarCellTrigger`, it moves focus to the last day of the current week. | | PageUp | When the focus is on `CalendarCellTrigger`, it moves to the previous month while preserving the day of the month when possible, or clamps to the last day of the month. | | PageDown | When the focus is on `CalendarCellTrigger`, it moves to the next month while preserving the day of the month when possible, or clamps to the last day of the month. | | Shift+PageUp | When the focus is on `CalendarCellTrigger`, it moves to the previous year while preserving the month and day when possible, or clamps to the last day of the month. | | Shift+PageDown | When the focus is on `CalendarCellTrigger`, it moves to the next year while preserving the month and day when possible, or clamps to the last day of the month. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Calendar) - [npm](https://www.npmjs.com/package/akar) # Checkbox > A control that allows the user to toggle between checked and not checked. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Checkbox) { /* reset */ button { all: unset; } .CheckboxRoot { background-color: white; width: 25px; height: 25px; border-radius: 4px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 10px var(--black-a7); } .CheckboxRoot:hover { background-color: var(--grass-3); } .CheckboxRoot:focus { box-shadow: 0 0 0 2px black; } .CheckboxIndicator { color: var(--grass-11); } .Label { color: white; padding-left: 15px; font-size: 15px; line-height: 1; } } ``` ## Features - Supports indeterminate state. - Full keyboard navigation. - Can be controlled or uncontrolled. - Supports custom true/false values. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a checkbox. An `input` will also render when used within a `form` to ensure events propagate correctly. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `T \| "indeterminate"` | The value of the checkbox when it is initially rendered. Use when you do not need to control its value. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the checkbox | | `falseValue` | `(() => false) as unknown as undefined` | `T` | The value used when the checkbox is unchecked. Defaults to `false`. | | `id` | | `string` | Id of the element | | `modelValue` | | `null \| T \| "indeterminate"` | The controlled value of the checkbox. Can be binded with v-model. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `trueValue` | `(() => true) as unknown as undefined` | `T` | The value used when the checkbox is checked. Defaults to `true`. | | `value` | `"on"` | `AcceptableValue` | The value given as data when submitted with a `name`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `value: T \| "indeterminate"` | Event handler called when the value of the checkbox changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `T \| "indeterminate"` | Current value | | `state` | `false \| true \| "indeterminate"` | Current state | [CheckboxRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Checkbox/CheckboxRoot.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" | | `[data-disabled]` | Present when disabled | ### Indicator Renders when the checkbox is in a checked or indeterminate state. You can style this element directly, or you can use it as a wrapper to put an icon into, or both. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [CheckboxIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Checkbox/CheckboxIndicator.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" | | `[data-disabled]` | Present when disabled | ### Group Root Wrapper around `CheckboxRoot` to support array of `modelValue` **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `T[]` | The value of the checkbox when it is initially rendered. Use when you do not need to control its value. | | `dir` | | `"ltr" \| "rtl"` | The direction of navigation between items. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the checkboxes | | `loop` | `false` | `boolean` | Whether keyboard navigation should loop around | | `max` | | `number \| null` | The maximum number of values that can be selected. Once reached, the unchecked
checkboxes get `aria-disabled` but stay focusable, so consider telling users
about the limit. Style them with `[aria-disabled="true"]`. | | `modelValue` | | `T[]` | The controlled value of the checkbox. Can be binded with v-model. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `orientation` | | `"vertical" \| "horizontal"` | The orientation of the group.
Mainly so arrow navigation is done accordingly (left & right vs. up & down) | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `rovingFocus` | `true` | `boolean` | When `false`, navigating through the items using arrow keys will be disabled. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `value: T[]` | Event handler called when the value of the checkbox changes. | [CheckboxGroupRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Checkbox/CheckboxGroupRoot.vue) ## Examples ### Custom Values Use the `trueValue` and `falseValue` props to specify custom values for the checked and unchecked states instead of the default `true`/`false`. ```vue ``` ### Indeterminate You can set the checkbox to `indeterminate` by taking control of its state. ```vue ``` ## Accessibility Adheres to the [tri-state Checkbox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox). ### Keyboard Interactions | Key | Description | | --- | --- | | Space | Checks/unchecks the checkbox | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Checkbox) - [npm](https://www.npmjs.com/package/akar) # Collapsible > An interactive component which expands/collapses a panel. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Collapsible) { /* reset */ button { all: unset; } .CollapsibleRoot { width: 300px; } .IconButton { font-family: inherit; border-radius: 100%; height: 25px; width: 25px; display: inline-flex; align-items: center; justify-content: center; color: var(--grass-11); box-shadow: 0 2px 10px var(--black-a7); } .IconButton[data-state='closed'] { background-color: white; } .IconButton[data-state='open'] { background-color: var(--grass-3); } .IconButton:hover { background-color: var(--grass-3); } .IconButton:focus { box-shadow: 0 0 0 2px black; } .Text { color: var(--grass-11); font-size: 15px; line-height: 25px; } .Repository { background-color: white; border-radius: 4px; margin: 10px 0; padding: 10px; box-shadow: 0 2px 10px var(--black-a7); } } ``` ## Features - Full keyboard navigation. - Can be controlled or uncontrolled. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import the components and piece the parts together. ```vue ``` ## API Reference ### Root Contains all the parts of a collapsible **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultOpen` | `false` | `boolean` | The open state of the collapsible when it is initially rendered.

Use when you do not need to control its open state. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the collapsible. | | `open` | | `boolean` | The controlled open state of the collapsible. Can be binded with `v-model`. | | `unmountOnHide` | `true` | `boolean` | When `true`, the element will be unmounted on closed state. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `value: boolean` | Event handler called when the open state of the collapsible changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | [CollapsibleRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Collapsible/CollapsibleRoot.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | ### Trigger The button that toggles the collapsible **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [CollapsibleTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Collapsible/CollapsibleTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | ### Content The component that contains the collapsible content. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | **Events** | Event | Payload | Description | | --- | --- | --- | | `contentFound` | `(void)?` | | [CollapsibleContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Collapsible/CollapsibleContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | | CSS variable | Description | | --- | --- | | `--akar-collapsible-content-width` | The width of the content when it opens/closes | | `--akar-collapsible-content-height` | The height of the content when it opens/closes | ## Examples ### Animating content size Use the `--akar-collapsible-content-width` and/or `--akar-collapsible-content-height` CSS variables to animate the size of the content when it opens/closes. Here's a demo: ```vue // index.vue ``` ```css /* styles.css */ .CollapsibleContent { overflow: hidden; } .CollapsibleContent[data-state="open"] { animation: slideDown 300ms ease-out; } .CollapsibleContent[data-state="closed"] { animation: slideUp 300ms ease-out; } @keyframes slideDown { from { height: 0; } to { height: var(--akar-collapsible-content-height); } } @keyframes slideUp { from { height: var(--akar-collapsible-content-height); } to { height: 0; } } ``` ### Render content even when collapsed By default hidden content will be removed, use `:unmountOnHide="false"` to keep the content always available. This will also allow browser to search the hidden text, and open the collapsible. ```vue ``` ## Accessibility Adheres to the [Disclosure WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure). ### Keyboard Interactions | Key | Description | | --- | --- | | Space | Opens/closes the collapsible | | Enter | Opens/closes the collapsible | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Collapsible) - [npm](https://www.npmjs.com/package/akar) # Color Area > A two-dimensional area for selecting color values in a specific color space. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @import '../_colors/mauve.css'; @scope (.akar-demo-ColorArea) { .ColorAreaDemo { display: flex; flex-direction: column; gap: 16px; } .ColorAreaValue { color: var(--mauve-11); font-size: 14px; } .ColorAreaRoot { position: relative; } .ColorAreaArea { position: relative; width: 200px; height: 200px; overflow: hidden; border-radius: 8px; } .ColorAreaArea:focus { outline: none; box-shadow: 0 0 0 2px var(--grass-7); } .ColorAreaThumb { display: block; width: 16px; height: 16px; cursor: pointer; background-color: white; border: 2px solid var(--mauve-8); border-radius: 9999px; box-shadow: 0 2px 10px var(--black-a7); } } ``` ## Features - Supports HSL, HSB, and RGB color spaces. - Configurable channels for horizontal (x) and vertical (y) axes. - Full keyboard navigation support. - Pointer/touch interaction for value selection. - Preserves hue information when saturation is 0. - Form integration with hidden inputs. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` > [!TIP] > > Looking for a complete color picker? Check out the [Color Picker example](https://vinicunca.dev/examples/color-picker) that combines Color Area, Color Slider, Color Field, and Color Swatch components. ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### ColorAreaRoot The root component that provides the color area context and state management. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `colorSpace` | `"hsl"` | `"hsl" \| "rgb" \| "hsb"` | The color space to operate in. | | `defaultValue` | `"#ff0000"` | `string \| Color` | The default color value (uncontrolled). | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the area. | | `modelValue` | | `string \| Color` | The color value (controlled). Can be a hex string or Color object. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `xChannel` | `"hue"` | `"hue" \| "saturation" \| "red" \| "green" \| "blue" \| "alpha" \| "lightness" \| "brightness"` | Color channel for the horizontal (x) axis. | | `xName` | | `string` | The name of the x channel input element for form submission. | | `yChannel` | `"saturation"` | `"hue" \| "saturation" \| "red" \| "green" \| "blue" \| "alpha" \| "lightness" \| "brightness"` | Color channel for the vertical (y) axis. | | `yName` | | `string` | The name of the y channel input element for form submission. | **Events** | Event | Payload | Description | | --- | --- | --- | | `change` | `value: string` | | | `changeEnd` | `value: string` | | | `update:color` | `value: Color` | | | `update:modelValue` | `value: string` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `style` | `CSSProperties` | CSS styles for the color area background gradient | [ColorAreaRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorArea/ColorAreaRoot.vue) ### ColorAreaArea The interactive area component where users can select color values by clicking or dragging. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [ColorAreaArea.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorArea/ColorAreaArea.vue) ### ColorAreaThumb The draggable thumb component that indicates the current position in the color area. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [ColorAreaThumb.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorArea/ColorAreaThumb.vue) ## Examples ### HSL Saturation/Lightness A common use case for color area is selecting saturation and lightness in HSL color space. ```vue ``` ### RGB Red/Green Selector Using RGB color space with red and green channels. ```vue ``` ### Disabled State Disable interaction with the color area. ```vue ``` ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | `ArrowLeft` | Decreases the x-axis channel value by one step. | | `ArrowRight` | Increases the x-axis channel value by one step. | | `ArrowUp` | Increases the y-axis channel value by one step. | | `ArrowDown` | Decreases the y-axis channel value by one step. | | `Shift + ArrowKey` | Changes values by 10 steps at a time. | | `PageUp` | Increases the y-axis channel value by a larger step. | | `PageDown` | Decreases the y-axis channel value by a larger step. | | `Home` | Jumps left (decreases x-axis value). | | `End` | Jumps right (increases x-axis value). | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorArea) - [npm](https://www.npmjs.com/package/akar) # Color Field > An input field for entering and editing color values in various formats. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @import '../_colors/mauve.css'; @scope (.akar-demo-ColorField) { .ColorFieldDemo { display: flex; flex-direction: column; gap: 12px; } .ColorFieldRoot { display: inline-flex; flex-direction: column; gap: 4px; } .ColorFieldLabel { color: var(--mauve-12); font-size: 14px; font-weight: 500; } .ColorFieldControl { display: flex; gap: 8px; align-items: center; } .ColorFieldSwatch { flex-shrink: 0; width: 32px; height: 32px; border-radius: 4px; box-shadow: inset 0 0 0 1px var(--black-a7); } .ColorFieldInput { width: 128px; padding: 8px 12px; color: var(--mauve-12); font-size: 14px; background-color: var(--black-a5); border: none; border-radius: 6px; box-shadow: 0 0 0 1px var(--black-a9); } .ColorFieldInput:focus { outline: none; box-shadow: 0 0 0 2px var(--grass-7); } .ColorFieldInput:disabled { cursor: not-allowed; opacity: 0.5; } } ``` ## Features - Supports hex color input mode. - Individual color channel editing mode. - Keyboard navigation with arrow keys. - Mouse wheel support for increment/decrement. - Page Up/Down for larger value changes. - Home/End keys to jump to min/max values. - Form integration with hidden inputs. - Support for HSL, HSB, and RGB color spaces. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` > [!TIP] > > Looking for a complete color picker? Check out the [Color Picker example](https://vinicunca.dev/examples/color-picker) that combines Color Area, Color Slider, Color Field, and Color Swatch components. ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### ColorFieldRoot The root component that provides the color field context and state management. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `channel` | | `"hue" \| "saturation" \| "red" \| "green" \| "blue" \| "alpha" \| "lightness" \| "brightness"` | The color channel to display. If not provided, displays hex value. | | `colorSpace` | `"hsl"` | `"hsl" \| "rgb" \| "hsb"` | The color space to operate in when displaying a channel. | | `defaultValue` | `"#000000"` | `string \| Color` | The default color value (uncontrolled). | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the field. | | `disableWheelChange` | `false` | `boolean` | When `true`, prevents the value from changing on wheel scroll. | | `locale` | | `string` | The locale to use for number formatting. | | `modelValue` | | `string \| Color` | The color value (controlled). Can be a hex string or Color object. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `placeholder` | | `string` | Placeholder text when the field is empty. | | `readonly` | `false` | `boolean` | When `true`, the field is read-only. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | | `number` | Custom step value for increment/decrement. Defaults to channel step or 1 for hex. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:color` | `value: Color` | | | `update:modelValue` | `value: string` | | [ColorFieldRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorField/ColorFieldRoot.vue) ### ColorFieldInput The input element for entering color values. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [ColorFieldInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorField/ColorFieldInput.vue) ## Examples ### Hex Color Input Basic hex color input field. ```vue ``` ### Channel Input Input for a specific color channel (e.g., hue). ```vue ``` ### With Wheel Control Disabled Prevent changing values with mouse wheel. ```vue ``` ### Read-only Mode Display the color value without allowing edits. ```vue ``` ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | `ArrowUp` | Increases the value by one step. | | `ArrowDown` | Decreases the value by one step. | | `PageUp` | Increases the value by 10 steps. | | `PageDown` | Decreases the value by 10 steps. | | `Home` | Sets the value to minimum. | | `End` | Sets the value to maximum. | | `Enter` | Commits the current input value. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorField) - [npm](https://www.npmjs.com/package/akar) # Color Slider > A slider control for adjusting individual color channels. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @import '../_colors/mauve.css'; @scope (.akar-demo-ColorSlider) { .ColorSliderDemo { display: flex; flex-direction: column; gap: 16px; } .ColorSliderRoot { position: relative; display: flex; align-items: center; width: 200px; height: 20px; touch-action: none; user-select: none; } .ColorSliderTrack { position: relative; flex: 1; height: 12px; border-radius: 9999px; } .ColorSliderTrackFill { position: absolute; inset: 0; border-radius: 9999px; } .ColorSliderThumb { display: block; width: 20px; height: 20px; cursor: pointer; background-color: white; border: 2px solid var(--mauve-8); border-radius: 9999px; box-shadow: 0 2px 10px var(--black-a7); transition: transform 150ms; } .ColorSliderThumb:hover { transform: scale(1.1); } .ColorSliderThumb:focus { outline: none; box-shadow: 0 0 0 2px var(--grass-7); } .ColorSliderValue { display: flex; gap: 8px; align-items: center; color: var(--mauve-11); font-size: 12px; } .ColorSliderSwatch { flex-shrink: 0; width: 20px; height: 20px; border: 1px solid var(--mauve-6); border-radius: 4px; } .ColorSliderCode { font-family: monospace; } } ``` ## Features - Supports all color channels (hue, saturation, lightness, brightness, red, green, blue, alpha). - Automatic gradient background based on current color. - Horizontal and vertical orientations. - Full keyboard navigation support. - Configurable step values. - Preserves color precision during drag operations. - Form integration with hidden inputs. - Support for HSL, HSB, and RGB color spaces. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` > [!TIP] > > Looking for a complete color picker? Check out the [Color Picker example](https://vinicunca.dev/examples/color-picker) that combines Color Area, Color Slider, Color Field, and Color Swatch components. ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### ColorSliderRoot The root component that provides the slider functionality and context. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `channel*` | | `"hue" \| "saturation" \| "red" \| "green" \| "blue" \| "alpha" \| "lightness" \| "brightness"` | The color channel that this slider manipulates. | | `colorSpace` | `"hsl"` | `"hsl" \| "rgb" \| "hsb"` | The color space to operate in. | | `defaultValue` | `"#000000"` | `string \| Color` | The default color value (uncontrolled). | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the slider. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the slider. | | `inverted` | `false` | `boolean` | Whether the slider is visually inverted. | | `modelValue` | | `string \| Color` | The color value (controlled). Can be a hex string or Color object. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation of the slider. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | | `number` | Custom step value for increment/decrement. Defaults to the channel's natural step. | **Events** | Event | Payload | Description | | --- | --- | --- | | `change` | `value: string` | | | `changeEnd` | `value: string` | | | `update:color` | `value: Color` | | | `update:modelValue` | `value: string \| Color` | | [ColorSliderRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSlider/ColorSliderRoot.vue) ### ColorSliderTrack The track component that displays the color gradient background. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [ColorSliderTrack.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSlider/ColorSliderTrack.vue) ### ColorSliderThumb The draggable thumb component for selecting values. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `channelName` | `string` | The display name of the current channel | | `channelValue` | `number` | The current numeric value of the channel | [ColorSliderThumb.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSlider/ColorSliderThumb.vue) ## Examples ### Hue Slider A horizontal hue slider in HSL color space. ```vue ``` ### Alpha Channel Slider for adjusting the alpha (opacity) channel. ```vue ``` ### Vertical Orientation A vertical slider for space-constrained layouts. ```vue ``` ### RGB Channel Sliders Sliders for individual RGB channels. ```vue ``` ### Custom Step Value Use a custom step increment for finer or coarser control. ```vue ``` ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | `ArrowLeft` | Decreases the value in horizontal orientation. | | `ArrowRight` | Increases the value in horizontal orientation. | | `ArrowUp` | Increases the value in vertical orientation. | | `ArrowDown` | Decreases the value in vertical orientation. | | `PageUp` | Increases the value by a larger step. | | `PageDown` | Decreases the value by a larger step. | | `Home` | Sets the value to minimum. | | `End` | Sets the value to maximum. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSlider) - [npm](https://www.npmjs.com/package/akar) # Color Swatch > A predefined color block that allows users to quickly select commonly used or brand-specific colors. `````vue [index.vue] ``` ```css [styles.css] @scope (.akar-demo-ColorSwatch) { .swatch { width: 32px; height: 32px; border-radius: 4px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15); flex-shrink: 0; } .dark .swatch { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15); } } ``` ## Features - Supports custom colors - Provides an accessible label for screen readers - Provides a color contrast for better visibility ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` > [!TIP] > > Looking for a complete color picker? Check out the [Color Picker example](https://vinicunca.dev/examples/color-picker) that combines Color Area, Color Slider, Color Field, and Color Swatch components. ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### ColorSwatch The main component that displays a color swatch. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `color` | `""` | `string \| Color` | The color to display in the swatch as a hex string or Color object.
Example: `#16a372`, `#ff5733`, or `{ space: 'hsl', h: 120, s: 100, l: 50, alpha: 1 }`. | | `label` | | `string` | Optional accessible label for the color. If omitted, the color name will be derived from the color value. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `color` | `string` | | | `alpha` | `number` | | [ColorSwatch.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSwatch/ColorSwatch.vue) --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSwatch) - [npm](https://www.npmjs.com/package/akar) # Color Swatch Picker > A component that allows users to select from a set of predefined colors, often used for themes or branding. `````vue [index.vue] ``` ```css [styles.css] @scope (.akar-demo-ColorSwatchPicker) { .root { display: flex; gap: 8px; } .item { position: relative; } .swatch { height: 32px; width: 32px; border-radius: 4px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15); flex-shrink: 0; cursor: pointer; } .dark .swatch { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15); } .indicator { position: absolute; bottom: 4px; right: 4px; color: white; } .swatch[data-color-contrast='dark'] ~ .indicator { color: black; } } ``` ## Features - Can be controlled or uncontrolled. - Focus is fully managed. - Full keyboard navigation. - Supports Right to Left direction. - Different selection behavior. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` > [!TIP] > > Looking for a complete color picker? Check out the [Color Picker example](https://vinicunca.dev/examples/color-picker) that combines Color Area, Color Slider, Color Field, and Color Swatch components. ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### ColorSwatchPickerRoot The main component that displays a color swatch picker. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `defaultValue` | | `string \| string[]` | The value of the listbox when initially rendered. Use when you do not need to control the state of the Listbox | | `dir` | `"ltr"` | `"ltr" \| "rtl"` | The reading direction of the listbox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with listbox | | `highlightOnHover` | | `boolean` | When `true`, hover over item will trigger highlight | | `modelValue` | | `string \| string[]` | The controlled value of the listbox. Can be binded with `v-model`. | | `multiple` | | `boolean` | Whether multiple options can be selected or not. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation of the listbox.

Mainly so arrow navigation is done accordingly (left & right vs. up & down) | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `selectionBehavior` | `'toggle'` | `"replace" \| "toggle"` | How multiple selection should behave in the collection. | **Events** | Event | Payload | Description | | --- | --- | --- | | `entryFocus` | `event: CustomEvent` | Event handler called when container is being focused. Can be prevented. | | `highlight` | `payload: { ref: HTMLElement; value: AcceptableValue; }` | Event handler when highlighted element changes. | | `leave` | `event: Event` | Event handler called when the mouse leave the container | | `update:modelValue` | `value: AcceptableValue` | Event handler called when the value changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `string \| string[]` | | [ColorSwatchPickerRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSwatchPicker/ColorSwatchPickerRoot.vue) ### ColorSwatchPickerItem The item that represents a selectable color swatch. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `value*` | | `string` | The color to display in the swatch as a hex string.
Example: `#16a372` or `#ff5733`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: SelectEvent` | Event handler called when the selecting item.

It can be prevented by calling `event.preventDefault`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `selected` | `boolean` | Whether the item is currently selected | [ColorSwatchPickerItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSwatchPicker/ColorSwatchPickerItem.vue) ### ColorSwatchPickerItemSwatch The component that displays the color swatch within an item. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `label` | | `string` | Optional accessible label for the color. If omitted, the color name will be derived from the color value. | [ColorSwatchPickerItemSwatch.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSwatchPicker/ColorSwatchPickerItemSwatch.vue) ### ColorSwatchPickerItemIndicator The component that indicates the selected color swatch within an item. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [ColorSwatchPickerItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSwatchPicker/ColorSwatchPickerItemIndicator.vue) --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ColorSwatchPicker) - [npm](https://www.npmjs.com/package/akar) # Combobox > Choose from a list of suggested values with full keyboard support. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Combobox) { /* reset */ button, input { all: unset; } .ComboboxRoot { position: relative; } .ComboboxAnchor { display: inline-flex; align-items: center; justify-content: between; font-size: 13px; line-height: 1; height: 35px; padding: 0 15px; gap: 5px; background-color: white; color: var(--grass-11); border-radius: 4px; box-shadow: 0 2px 10px var(--black-a7); } .ComboboxAnchor:hover { background-color: var(--mauve-3); } .ComboboxInput { height: 100%; background-color: transparent; color: var(--grass-11); } .ComboboxInput[data-placeholder] { color: var(--grass-9); } .ComboboxIcon { width: 16px; height: 16px; color: var(--grass-11); } .ComboboxContent { z-index: 10; width: 100%; position: absolute; overflow: hidden; background-color: white; border-radius: 6px; margin-top: 8px; box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2); } .ComboboxViewport { padding: 5px; } .ComboboxEmpty { padding-top: 0.5rem; padding-bottom: 0.5rem; text-align: center; font-size: 0.75rem; line-height: 1rem; font-weight: 500; color: var(--mauve-11) } .ComboboxItem { font-size: 13px; line-height: 1; color: var(--grass-11); border-radius: 3px; display: flex; align-items: center; height: 25px; padding: 0 35px 0 25px; position: relative; user-Combobox: none; } .ComboboxItem[data-disabled] { color: var(--mauve-8); pointer-events: none; } .ComboboxItem[data-highlighted] { outline: none; background-color: var(--grass-9); color: var(--grass-1); } .ComboboxLabel { padding: 0 25px; font-size: 12px; line-height: 25px; color: var(--mauve-11); } .ComboboxSeparator { height: 1px; background-color: var(--grass-6); margin: 5px; } .ComboboxItemIndicator { position: absolute; left: 0; width: 25px; display: inline-flex; align-items: center; justify-content: center; } } ``` ## Features - Can be controlled or uncontrolled. - Offers 2 positioning modes. - Supports items, labels, groups of items. - Focus is fully managed. - Full keyboard navigation. - Supports custom placeholder. - Supports Right to Left direction. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a Combobox **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `by` | | `string \| ((a: T, b: T) => boolean)` | Use this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared. | | `defaultOpen` | | `boolean` | The open state of the combobox when it is initially rendered.

Use when you do not need to control its open state. | | `defaultValue` | | `T \| T[]` | The value of the listbox when initially rendered. Use when you do not need to control the state of the Listbox | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the listbox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with listbox | | `highlightOnHover` | `true` | `boolean` | When `true`, hover over item will trigger highlight | | `ignoreFilter` | | `boolean` | When `true`, disable the default filters | | `modelValue` | | `T \| T[]` | The controlled value of the listbox. Can be binded with `v-model`. | | `multiple` | | `boolean` | Whether multiple options can be selected or not. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `open` | | `boolean` | The controlled open state of the Combobox. Can be binded with `v-model:open`. | | `openOnClick` | `false` | `boolean` | Whether to open the combobox when the input is clicked | | `openOnFocus` | `false` | `boolean` | Whether to open the combobox when the input is focused | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `resetModelValueOnClear` | `false` | `boolean` | When `true` the `modelValue` will be reset to `null` (or `[]` if `multiple`) | | `resetSearchTermOnBlur` | `true` | `boolean` | Whether to reset the searchTerm when the Combobox input blurred | | `resetSearchTermOnSelect` | `true` | `boolean` | Whether to reset the searchTerm when the Combobox value is selected | | `unmountOnHide` | `true` | `boolean` | When set to `false`, the Combobox content will not be unmounted when closed, but instead hidden with CSS.

Useful when you want to improve performance by not remounting the content on every open. | **Events** | Event | Payload | Description | | --- | --- | --- | | `highlight` | `payload: { ref: HTMLElement; value: T; }` | Event handler when highlighted element changes. | | `update:modelValue` | `value: T` | Event handler called when the value changes. | | `update:open` | `value: boolean` | Event handler called when the open state of the combobox changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | | `modelValue` | `T \| T[]` | Current active value | [ComboboxRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxRoot.vue) ### Anchor Used as an anchor if you set `ComboboxContent`'s position to `popper`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `reference` | | `ReferenceElement` | The reference (or anchor) element that is being referred to for positioning.

If not provided will use the current component as anchor. | [ComboboxAnchor.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxAnchor.vue) ### Input The input component to search through the combobox items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `autoFocus` | | `boolean` | Focus on element when mounted. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with item | | `displayValue` | | `((val: any) => string)` | The display value of input for selected item. Does not work with `multiple`. | | `modelValue` | | `string` | The controlled value of the filter. Can be binded with v-model. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `string` | | [ComboboxInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxInput.vue) ### Trigger The button that toggles the Combobox Content. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with item | [ComboboxTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | ### Cancel The button that clears the search term. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ComboboxCancel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxCancel.vue) ### Empty Shown when none of the items match the query. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ComboboxEmpty.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxEmpty.vue) ### Portal When used, portals the content part into the `body`. You need to set `position="popper"` for `ComboboxContent` to make sure the position was automatically computed similar to `Popover` or `DropdownMenu`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [ComboboxPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxPortal.vue) ### Content The component that pops out when the combobox is open. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.
May change when collisions occur. | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `bodyLock` | | `boolean` | The document.body will be lock, and scrolling will be disabled. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the popper content when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disableOutsidePointerEvents` | | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside
the `DismissableLayer`. Users will need to click twice on outside elements to
interact with them: once to close the `DismissableLayer`, and again to trigger the element. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `hideWhenEmpty` | `false` | `boolean` | When `true`, hides the content when there are no items matching the filter. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `position` | | `"inline" \| "popper"` | The positioning mode to use,

`inline` is the default and you can control the position using CSS.

`popper` positions content in the same way as our other primitives, for example `Popover` or `DropdownMenu`. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `present` | | `boolean` | Whether this kept-mounted content is currently visible. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.
Will be reversed when collisions occur and avoidCollisions
is enabled. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [ComboboxContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | `[data-empty]` | Present when there are no items matching the filter | | CSS variable | Description | | --- | --- | | `--akar-combobox-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets. Only present when `position="popper"`. | | `--akar-combobox-content-available-width` | The remaining width between the trigger and the boundary edge. Only present when `position="popper"`. | | `--akar-combobox-content-available-height` | The remaining height between the trigger and the boundary edge. Only present when `position="popper"`. | | `--akar-combobox-trigger-width` | The width of the trigger. Only present when `position="popper"`. | | `--akar-combobox-trigger-height` | The height of the trigger. Only present when `position="popper"`. | ### Viewport The scrolling viewport that contains all of the items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `nonce` | | `string` | Will add `nonce` attribute to the style tag which can be used by Content Security Policy.

If omitted, inherits globally from `ConfigProvider`. | [ComboboxViewport.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxViewport.vue) ### Item The component that contains the combobox items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `textValue` | | `string` | A string representation of the item contents.

If the children are not plain text, then the `textValue` prop must also be set to a plain text representation, which will be used for autocomplete in the ComboBox. | | `value*` | | `T` | The value given as data when submitted with a `name`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: SelectEvent` | Event handler called when the selecting item.

It can be prevented by calling `event.preventDefault`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `selected` | `boolean` | Whether the item is currently selected | [ComboboxItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### ItemIndicator Renders when the item is selected. You can style this element directly, or you can use it as a wrapper to put an icon into, or both. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [ComboboxItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxItemIndicator.vue) ### Group Used to group multiple items. use in conjunction with `ComboboxLabel` to ensure good accessibility via automatic labelling. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ComboboxGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxGroup.vue) ### Label Used to render the label of a group. It won't be focusable using arrow keys. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `for` | | `string` | | [ComboboxLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxLabel.vue) ### Separator Used to visually separate items in the Combobox **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ComboboxSeparator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxSeparator.vue) ### Arrow An optional arrow element to render alongside the content. This can be used to help visually link the trigger with the `ComboboxContent`. Must be rendered inside `ComboboxContent`. Only available when `position` is set to `popper`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` | | `width` | `10` | `number` | The width of the arrow in pixels. | [ComboboxArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxArrow.vue) ### Virtualizer Virtual container to achieve list virtualization. > [!WARNING] > > Combobox items **must** be filtered manually before passing them over to the virtualizer. See [example below](#virtualized-combobox-with-working-filtering). See the [virtualization guide](https://vinicunca.dev/akar/guides/virtualization.md) for more general info on virtualization. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `estimateSize` | | `number \| ((index: number) => number)` | Estimated size (in px) of each item | | `options*` | | `T` | List of items | | `overscan` | | `number` | Number of items rendered outside the visible area | | `textContent` | | `((option: T) => string)` | Text content for each item to achieve type-ahead feature | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `option` | `T` | | | `virtualizer` | `Virtualizer` | | | `virtualItem` | `VirtualItem` | | [ComboboxVirtualizer.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxVirtualizer.vue) ## Examples ### Binding objects as values Unlike native HTML form controls which only allow you to provide strings as values, Akar supports binding complex objects as well. Make sure to set the `displayValue` prop to set the input value on item selection. ```vue ``` ### Selecting multiple values The `Combobox` component allows you to select multiple values. You can enable this by providing an array of values instead of a single value. ```vue ``` ### Custom filtering Internally, `ComboboxRoot` will filter the item based on the rendered text. However, you may also provide your own custom filtering logic together with setting `ignoreFilter="true"`. ```vue ``` ### Custom label By default the `Combobox` will use the input contents as the label for screenreaders. If you'd like more control over what is announced to assistive technologies, use the [Label](https://vinicunca.dev/akar/components/label) component. ```vue ``` ### With disabled items You can add special styles to disabled items via the `data-disabled` attribute. ```vue ``` ```css /* styles.css */ .ComboboxItem[data-disabled] { color: "gainsboro"; } ``` ### With separators Use the `Separator` part to add a separator between items. ```vue ``` ### With grouped items Use the `Group` and `Label` parts to group items in a section. ```vue ``` ### With complex items You can use custom content in your items. ```vue ``` ### Prevent select behavior By default, selecting `ComboboxItem` would close the content, and update the `modelValue` with the provided value. You can prevent this behavior by preventing default `@select.prevent`. ```vue ``` ### Virtualized combobox with working filtering Combobox items **must** be filtered manually before passing them over to the virtualizer. See the [virtualization guide](https://vinicunca.dev/akar/guides/virtualization.md) for more general info on virtualization. ```vue ``` ## Accessibility Adheres to the [Combobox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/). See the W3C [Combobox Autocomplete List](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-autocomplete-list/) example for more information. ### Keyboard Interactions | Key | Description | | --- | --- | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/listbox) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox) - [npm](https://www.npmjs.com/package/akar) # Context Menu > Displays a menu located at the pointer, triggered by a right-click or a long-press. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-ContextMenu) { .ContextMenuTrigger { display: block; border: 2px white dashed; color: white; border-radius: 4px; font-size: 15px; user-select: none; padding: 45px 0; width: 300px; text-align: center; } .ContextMenuContent, .ContextMenuSubContent { min-width: 220px; background-color: white; border-radius: 6px; overflow: hidden; padding: 5px; box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2); } .ContextMenuItem, .ContextMenuCheckboxItem, .ContextMenuRadioItem, .ContextMenuSubTrigger { font-size: 13px; line-height: 1; color: var(--grass-11); border-radius: 3px; display: flex; align-items: center; height: 25px; padding: 0 5px; position: relative; padding-left: 25px; user-select: none; outline: none; } .ContextMenuSubTrigger[data-state='open'] { background-color: var(--grass-4); color: var(--grass-11); } .ContextMenuItem[data-disabled], .ContextMenuCheckboxItem[data-disabled], .ContextMenuRadioItem[data-disabled], .ContextMenuSubTrigger[data-disabled] { color: var(--mauve-8); pointer-events: 'none'; } .ContextMenuItem[data-highlighted], .ContextMenuCheckboxItem[data-highlighted], .ContextMenuRadioItem[data-highlighted], .ContextMenuSubTrigger[data-highlighted] { background-color: var(--grass-9); color: var(--grass-1); } .ContextMenuLabel { padding-left: 25px; font-size: 12px; line-height: 25px; color: var(--mauve-11); } .ContextMenuSeparator { height: 1px; background-color: var(--grass-6); margin: 5px; } .ContextMenuItemIndicator { position: absolute; left: 0; width: 25px; display: inline-flex; align-items: center; justify-content: center; } .RightSlot { margin-left: auto; padding-left: 20px; color: var(--mauve-11); } [data-highlighted] > .RightSlot { color: white; } [data-disabled] .RightSlot { color: var(--mauve-8); } } ``` ## Features - Supports submenus with configurable reading direction. - Supports items, labels, groups of items. - Supports checkable items (single or multiple) with optional indeterminate state. - Supports modal and non-modal modes. - Customize side, alignment, offsets, collision handling. - Focus is fully managed. - Full keyboard navigation. - Typeahead support. - Dismissing and layering behavior is highly customizable. - Triggers with a long-press on touch devices ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference Adheres to the [Menu WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu) and uses [roving tabindex](https://www.w3.org/TR/wai-aria-practices-1.2/examples/menu-button/menu-button-actions.html) to manage focus movement among menu items. ### Root Contains all the parts of a context menu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `modal` | `true` | `boolean` | The modality of the dropdown menu.

When set to `true`, interaction with outside elements will be disabled and only menu content will be visible to screen readers. | | `pressOpenDelay` | `700` | `number` | The duration from when the trigger is pressed until the menu opens. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `payload: boolean` | | [ContextMenuRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuRoot.vue) ### Trigger The area that opens the context menu. Wrap it around the target you want the context menu to open from when right-clicking (or using the relevant keyboard shortcuts). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | `false` | `boolean` | When `true`, the context menu would not open when right-clicking.

Note that this will also restore the native context menu. | [ContextMenuTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### Portal When used, portals the content part into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [ContextMenuPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuPortal.vue) ### Content The component that pops out in an open context menu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [ContextMenuContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | CSS variable | Description | | --- | --- | | `--akar-context-menu-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets | | `--akar-context-menu-content-available-width` | The remaining width between the trigger and the boundary edge | | `--akar-context-menu-content-available-height` | The remaining height between the trigger and the boundary edge | | `--akar-context-menu-trigger-width` | The width of the trigger | | `--akar-context-menu-trigger-height` | The height of the trigger | ### Arrow An optional arrow element to render alongside a submenu. This can be used to help visually link the trigger item with the `ContextMenu.Content`. Must be rendered inside `ContextMenu.Content`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` | | `width` | `10` | `number` | The width of the arrow in pixels. | [ContextMenuArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuArrow.vue) ### Item The component that contains the context menu items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).

Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. | [ContextMenuItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuItem.vue) | Data attribute | Value | | --- | --- | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### Group Used to group multiple `ContextMenu.Item`s. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ContextMenuGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuGroup.vue) ### Label Used to render a label. It won't be focusable using arrow keys. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ContextMenuLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuLabel.vue) ### CheckboxItem An item that can be controlled and rendered like a checkbox. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `modelValue` | | `false \| true \| "indeterminate"` | The controlled checked state of the item. Can be used as `v-model`. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).

Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. | | `update:modelValue` | `payload: boolean` | Event handler called when the checked state changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `checked` | `false \| true \| "indeterminate"` | Current checked state | | `modelValue` | `CheckedState` | Current modelValue state | [ContextMenuCheckboxItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuCheckboxItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### RadioGroup Used to group multiple `ContextMenu.RadioItem`s. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `modelValue` | | `AcceptableValue` | The value of the selected item in the group. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: AcceptableValue` | Event handler called when the value changes. | [ContextMenuRadioGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuRadioGroup.vue) ### RadioItem An item that can be controlled and rendered like a radio. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | | `value*` | | `AcceptableValue` | The unique value of the item. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).

Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `checked` | `boolean` | Current checked state | [ContextMenuRadioItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuRadioItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### ItemIndicator Renders when the parent `ContextMenu.CheckboxItem` or `ContextMenu.RadioItem` is checked. You can style this element directly, or you can use it as a wrapper to put an icon into, or both. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [ContextMenuItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuItemIndicator.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" | ### Separator Used to visually separate items in the context menu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ContextMenuSeparator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuSeparator.vue) ### Sub Contains all the parts of a submenu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defaultOpen` | | `boolean` | The open state of the submenu when it is initially rendered. Use when you do not need to control its open state. | | `open` | | `boolean` | The controlled open state of the menu. Can be used as `v-model:open`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `payload: boolean` | Event handler called when the open state of the submenu changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | [ContextMenuSub.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuSub.vue) ### SubTrigger An item that opens a submenu. Must be rendered inside `ContextMenu.Sub`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `graceDuration` | `300` | `number` | Time in milliseconds to keep a submenu open while the pointer moves from
its trigger to the submenu. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | [ContextMenuSubTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuSubTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### SubContent The component that pops out when a submenu is open. Must be rendered inside `ContextMenu.Sub`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `entryFocus` | `event: Event` | | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [ContextMenuSubContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuSubContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | CSS variable | Description | | --- | --- | | `--akar-context-menu-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets | | `--akar-context-menu-content-available-width` | The remaining width between the trigger and the boundary edge | | `--akar-context-menu-content-available-height` | The remaining height between the trigger and the boundary edge | | `--akar-context-menu-trigger-width` | The width of the trigger | | `--akar-context-menu-trigger-height` | The height of the trigger | ## Examples ### With submenus You can create submenus by using `ContextMenuSub` in combination with its parts. ```vue ``` ### With disabled items You can add special styles to disabled items via the `data-disabled` attribute. ```vue ``` ```css /* styles.css */ .ContextMenuItem[data-disabled] { color: gainsboro; } ``` ### With separators Use the `Separator` part to add a separator between items. ```vue ``` ### With labels Use the `Label` part to help label a section. ```vue ``` ### With checkbox items Use the `CheckboxItem` part to add an item that can be checked. ```vue ``` ### With radio items Use the `RadioGroup` and `RadioItem` parts to add an item that can be checked amongst others. ```vue ``` ### With complex items You can add extra decorative elements in the `Item` parts, such as images. ```vue ``` ### Constrain the content/sub-content size You may want to constrain the width of the content (or sub-content) so that it matches the trigger (or sub-trigger) width. You may also want to constrain its height to not exceed the viewport. We expose several CSS custom properties such as `--akar-context-menu-trigger-width` and `--akar-context-menu-content-available-height` to support this. Use them to constrain the content dimensions. ```vue ``` ```css /* styles.css */ .ContextMenuContent { width: var(--akar-context-menu-trigger-width); max-height: var(--akar-context-menu-content-available-height); } ``` ### Origin-aware animations We expose a CSS custom property `--akar-context-menu-content-transform-origin`. Use it to animate the content from its computed origin based on `side`, `sideOffset`, `align`, `alignOffset` and any collisions. ```vue ``` ```css /* styles.css */ .ContextMenuContent { transform-origin: var(--akar-context-menu-content-transform-origin); animation: scaleIn 0.5s ease-out; } @keyframes scaleIn { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } } ``` ### Collision-aware animations We expose `data-side` and `data-align` attributes. Their values will change at runtime to reflect collisions. Use them to create collision and direction-aware animations. ```vue ``` ```css /* styles.css */ .ContextMenuContent { animation-duration: 0.6s; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); } .ContextMenuContent[data-side="top"] { animation-name: slideUp; } .ContextMenuContent[data-side="bottom"] { animation-name: slideDown; } @keyframes slideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } ``` ## Accessibility Uses [roving tabindex](https://www.w3.org/WAI/ARIA/apg/patterns/kbd_roving_tabindex) to manage focus movement among menu items. ### Keyboard Interactions | Key | Description | | --- | --- | | Space | Activates the focused item. | | Enter | Activates the focused item. | | ArrowDown | Moves focus to the next item. | | ArrowUp | Moves focus to the previous item. | | ArrowRight / ArrowLeft | When focus is on `ContextMenu.SubTrigger`, opens or closes the submenu depending on reading direction. | | Esc | Closes the context menu | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/menu) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu) - [npm](https://www.npmjs.com/package/akar) # Date Field > Enables users to input specific dates within a designated field. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-DateField) { .DateFieldWrapper { display: flex; flex-direction: column; gap: 0.5rem; } .DateFieldLabel { font-size: 0.875rem; line-height: 1.25rem; color: var(--gray-9); } .DateField { display: flex; padding: 0.5rem; align-items: center; border-radius: 0.25rem; border-width: 1px; text-align: center; background-color: #ffffff; user-select: none; color: var(--green-10); border: 1px solid var(--gray-9); } .DateField::placeholder { color: var(--mauve-5); } .DateField[data-invalid] { border: 1px solid var(--red-500); } .DateFieldLiteral { padding: 0.25rem; } .DateFieldSegment { padding: 0.25rem; } .DateFieldSegment:hover{ background-color: var(--grass-4); } .DateFieldSegment:focus { background-color: var(--grass-2); } .DateFieldSegment:[aria-valuetext='Empty'] { color: var(--grass-6); } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Highly composable - Accessible by default - Supports both date and date-time formats ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a date field **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `defaultPlaceholder` | | `DateValue` | The default placeholder date | | `defaultValue` | | `DateValue` | The default value for the calendar | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the date field when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | Whether or not the date field is disabled | | `granularity` | | `"day" \| "hour" \| "minute" \| "second"` | The granularity to use for formatting times. Defaults to day if a CalendarDate is provided, otherwise defaults to minute. The field will render segments for each part of the date up to and including the specified granularity | | `hideTimeZone` | | `boolean` | Whether or not to hide the time zone segment of the field | | `hourCycle` | | `12 \| 24` | The hour cycle used for formatting times. Defaults to the local preference | | `id` | | `string` | Id of the element | | `isDateUnavailable` | | `Matcher` | A function that returns whether or not a date is unavailable | | `locale` | | `string` | The locale to use for formatting dates | | `maxValue` | | `DateValue` | The maximum date that can be selected | | `minValue` | | `DateValue` | The minimum date that can be selected | | `modelValue` | | `DateValue \| null` | The controlled value of the field. Can be bound as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `placeholder` | | `DateValue` | The placeholder date, which is used to determine what month to display when no date is selected. This updates as the user navigates the calendar and can be used to programmatically control the calendar view | | `readonly` | `false` | `boolean` | Whether or not the date field is readonly | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | | `DateStep` | The stepping interval for the time fields. Defaults to `1`. | | `stepSnapping` | `false` | `boolean` | Whether to enforce snapping the time value to the nearest step increment after input. Defaults to `false`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: DateValue` | Event handler called whenever the model value changes | | `update:placeholder` | `date: DateValue` | Event handler called whenever the placeholder value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `DateValue` | The current date of the field | | `segments` | `{ part: SegmentPart; value: string; }[]` | The date field segment contents | | `isInvalid` | `boolean` | Value if the input is invalid | **Methods** | Method | Type | Description | | --- | --- | --- | | `setFocusedElement` | `(el: HTMLElement) => void` | Helper to set the focused element inside the DateField | [DateFieldRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateField/DateFieldRoot.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Input Contains the date field segments **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `part*` | | `"day" \| "month" \| "year" \| "hour" \| "minute" \| "second" \| "dayPeriod" \| "literal" \| "timeZoneName"` | The part of the date to render | [DateFieldInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateField/DateFieldInput.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-placeholder]` | Present when no value is set | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the date field, focuses the first segment. | | ArrowLeft / ArrowRight | Navigates between the date field segments. | | ArrowUp / ArrowDown | Increments/changes the value of the segment. | | 0-9 | When the focus is on a numeric `DateFieldInput`, it types in the number and focuses the next segment if the next input would result in an invalid value. | | Backspace | Deletes a digit from the focused numeric segments. | | A / P | When the focus is on the day period, it sets it to AM or PM. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateField) - [npm](https://www.npmjs.com/package/akar) # Date Picker > Facilitates the selection of dates through an input and calendar-based interface. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-DatePicker) { .DateFieldWrapper { display: flex; flex-direction: column; gap: 0.5rem; } .DateFieldLabel { font-size: 0.875rem; line-height: 1.25rem; color: var(--gray-9); } .DateField { display: flex; padding: 0.5rem; align-items: center; border-radius: 0.25rem; border-width: 1px; text-align: center; background-color: #ffffff; user-select: none; color: var(--green-10); border: 1px solid var(--gray-9); } .DateField::placeholder { color: var(--mauve-5); } .DateField[data-invalid] { border: 1px solid var(--red-500); } .DateFieldLiteral { padding: 0.25rem; } .DateFieldSegment { padding: 0.25rem; } .DateFieldSegment:hover{ background-color: var(--grass-4); } .DateFieldSegment:focus { background-color: var(--grass-2); } .DateFieldSegment:[aria-valuetext='Empty'] { color: var(--grass-6); } .Icon { width: 1.5rem; height: 1.5rem; } .Calendar { padding: 22px; } .CalendarHeader { display: flex; justify-content: space-between; align-items: center; } .CalendarNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2.5rem; height: 2.5rem; color: #000000; background-color: transparent; cursor: pointer; } .CalendarNavButton:hover { color: #ffffff; background-color: #000000; } .CalendarHeading { font-weight: 500; color: #000000; color: 15px; } .CalendarWrapper { display: flex; padding-top: 1rem; margin-top: 1rem; flex-direction: column; } @media (min-width: 640px) { .CalendarWrapper { margin-left: 1rem; margin-top: 0; flex-direction: row; } } .CalendarGrid { margin-top: 0.25rem; width: 100%; user-select: none; border-collapse: collapse; } .CalendarGridRow { display: grid; margin-bottom: 0.25rem; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; } .CalendarGridRow[data-reka-calendar-month-view] { grid-template-columns: repeat(7, minmax(0, 1fr)); } .CalendarHeadCell { border-radius: 0.375rem; font-size: 0.75rem; line-height: 1rem; color: #000000; font-weight: 400; } .CalendarCell { position: relative; font-size: 0.875rem; line-height: 1.25rem; text-align: center; } .CalendarCellTrigger { display: flex; position: relative; padding: 0.5rem; justify-content: center; align-items: center; border-width: 1px; border-color: transparent; outline-style: none; font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; color: #000000; white-space: nowrap; background-color: transparent; } .CalendarCellTrigger:hover { border-color: #000000; } .CalendarCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .CalendarCellTrigger[data-disabled] { cursor: none; color: rgba(0,0,0,0.3); } .CalendarCellTrigger[data-selected] { background-color: #000000; color: #ffffff; font-weight: 500; } .CalendarCellTrigger[data-selected]::before { background-color: #FFFFFF; } .CalendarCellTrigger[data-unavailable] { color: rgba(0,0,0,0.3); text-decoration: line-through; } .CalendarCellTrigger::before { content: ''; position: absolute; top: 5px; left: 0; width: 0.25rem; height: 0.25rem; border-radius: 9999px; background-color: #FFFFFF; } .CalendarCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } .PopoverTrigger:focus { box-shadow: 0 0 0 2px #000000; } .PopoverContent { border-radius: 4px; padding: 20px; width: 260px; background-color: white; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; animation-duration: 400ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); will-change: transform, opacity; } .PopoverContent:focus { box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px, 0 0 0 2px var(--grass-7); } .PopoverContent[data-state='open'][data-side='top'] { animation-name: slideDownAndFade; } .PopoverContent[data-state='open'][data-side='right'] { animation-name: slideLeftAndFade; } .PopoverContent[data-state='open'][data-side='bottom'] { animation-name: slideUpAndFade; } .PopoverContent[data-state='open'][data-side='left'] { animation-name: slideRightAndFade; } .PopoverArrow { fill: white; } @keyframes slideUpAndFade { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideRightAndFade { from { opacity: 0; transform: translateX(-2px); } to { opacity: 1; transform: translateX(0); } } @keyframes slideDownAndFade { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideLeftAndFade { from { opacity: 0; transform: translateX(2px); } to { opacity: 1; transform: translateX(0); } } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Accessible by default - Supports both date and date-time formats ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a date picker **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `closeOnSelect` | `false` | `boolean` | Whether or not to close the popover on date select | | `defaultOpen` | `false` | `boolean` | The open state of the popover when it is initially rendered. Use when you do not need to control its open state. | | `defaultPlaceholder` | | `DateValue` | The default placeholder date | | `defaultValue` | | `DateValue` | The default value for the calendar | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the date field when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | Whether or not the date field is disabled | | `fixedWeeks` | `false` | `boolean` | Whether or not to always display 6 weeks in the calendar | | `granularity` | | `"day" \| "hour" \| "minute" \| "second"` | The granularity to use for formatting times. Defaults to day if a CalendarDate is provided, otherwise defaults to minute. The field will render segments for each part of the date up to and including the specified granularity | | `hideTimeZone` | | `boolean` | Whether or not to hide the time zone segment of the field | | `hourCycle` | | `12 \| 24` | The hour cycle used for formatting times. Defaults to the local preference | | `id` | | `string` | Id of the element | | `isDateDisabled` | | `Matcher` | A function that returns whether or not a date is disabled | | `isDateUnavailable` | | `Matcher` | A function that returns whether or not a date is unavailable | | `locale` | | `string` | The locale to use for formatting dates | | `maxValue` | | `DateValue` | The maximum date that can be selected | | `minValue` | | `DateValue` | The minimum date that can be selected | | `modal` | `false` | `boolean` | The modality of the popover. When set to true, interaction with outside elements will be disabled and only popover content will be visible to screen readers. | | `modelValue` | | `DateValue \| null` | The controlled value of the field. Can be bound as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `numberOfMonths` | `1` | `number` | The number of months to display at once | | `open` | | `boolean` | The controlled open state of the popover. | | `pagedNavigation` | `false` | `boolean` | This property causes the previous and next buttons to navigate by the number of months displayed at once, rather than one month | | `placeholder` | | `DateValue` | The placeholder date, which is used to determine what month to display when no date is selected. This updates as the user navigates the calendar and can be used to programmatically control the calendar view | | `preventDeselect` | `false` | `boolean` | Whether or not to prevent the user from deselecting a date without selecting another date first | | `readonly` | `false` | `boolean` | Whether or not the date field is readonly | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | | `DateStep` | The stepping interval for the time fields. Defaults to `1`. | | `stepSnapping` | | `boolean` | Whether to enforce snapping the time value to the nearest step increment after input. Defaults to `false`. | | `weekdayFormat` | `"narrow"` | `"narrow" \| "short" \| "long"` | The format to use for the weekday strings provided via the weekdays slot prop | | `weekStartsOn` | | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | The day of the week to start the calendar on | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: DateValue` | Event handler called whenever the model value changes | | `update:open` | `value: boolean` | Event handler called when the open state of the popover changes. | | `update:placeholder` | `date: DateValue` | Event handler called whenever the placeholder value changes | [DatePickerRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerRoot.vue) ### Field Contains the date picker date field segments and trigger **Slots** | Slot | Payload | Description | | --- | --- | --- | | `segments` | `{ part: SegmentPart; value: string; }[]` | | | `modelValue` | `DateValue` | | [DatePickerField.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerField.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Input Contains the date picker date field segments **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `part*` | | `"day" \| "month" \| "year" \| "hour" \| "minute" \| "second" \| "dayPeriod" \| "literal" \| "timeZoneName"` | The part of the date to render | [DatePickerInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerInput.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-placeholder]` | Present when no value is set | ### Trigger The button that toggles the popover. By default, the `DatePickerContent` will position itself against the trigger. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DatePickerTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerTrigger.vue) ### Content The component that pops out when the popover is open. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.
May change when collisions occur. | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the popper content when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disableOutsidePointerEvents` | | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside
the `DismissableLayer`. Users will need to click twice on outside elements to
interact with them: once to close the `DismissableLayer`, and again to trigger the element. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `portal` | | `PopoverPortalProps` | Props to control the portal wrapped around the content. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.
Will be reversed when collisions occur and avoidCollisions
is enabled. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | Event handler called when auto-focusing on open.
Can be prevented. | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [DatePickerContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerContent.vue) ### Arrow An optional arrow element to render alongside the popover. This can be used to help visually link the anchor with the `DatePickerContent`. Must be rendered inside `DatePickerContent`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` | | `width` | `10` | `number` | The width of the arrow in pixels. | [DatePickerArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerArrow.vue) ### Close The button that closes an open date picker. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DatePickerClose.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerClose.vue) ### Anchor An optional element to position the `DatePickerContent` against. If this part is not used, the content will position alongside the `DatePickerTrigger`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `reference` | | `ReferenceElement` | The reference (or anchor) element that is being referred to for positioning.

If not provided will use the current component as anchor. | [DatePickerAnchor.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerAnchor.vue) ### Calendar Contains all the parts of a calendar **Slots** | Slot | Payload | Description | | --- | --- | --- | | `date` | `DateValue` | | | `grid` | `Grid[]` | | | `weekDays` | `string[]` | | | `weekStartsOn` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | | | `locale` | `string` | | | `fixedWeeks` | `boolean` | | [DatePickerCalendar.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerCalendar.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when readonly | ### Header Contains the navigation buttons and the heading segments. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DatePickerHeader.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerHeader.vue) ### Prev Button Calendar navigation button. It navigates the calendar one month/year/decade in the past based on the current calendar view. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the prev page. Overwrites the `prevPage` function set on the `CalendarRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [DatePickerPrev.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerPrev.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Next Button Calendar navigation button. It navigates the calendar one month/year/decade in the future based on the current calendar view. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the next page. Overwrites the `nextPage` function set on the `CalendarRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [DatePickerNext.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerNext.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Heading Heading for displaying the current month and year/ **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `headingValue` | `string` | Current month and year | [DatePickerHeading.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerHeading.vue) ### Grid Container for wrapping the calendar grid. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DatePickerGrid.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerGrid.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when readonly | ### Grid Head Container for wrapping the grid head. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DatePickerGridHead.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerGridHead.vue) ### Grid Body Container for wrapping the grid body. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DatePickerGridBody.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerGridBody.vue) ### Grid Row Container for wrapping the grid row. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DatePickerGridRow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerGridRow.vue) ### Head Cell Container for wrapping the head cell. Used for displaying the week days. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DatePickerHeadCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerHeadCell.vue) ### Cell Container for wrapping the calendar cells. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `date*` | | `DateValue` | The date value for the cell | [DatePickerCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerCell.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Cell Trigger Interactable container for displaying the cell dates. Clicking it selects the date. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `day*` | | `DateValue` | The date value provided to the cell trigger | | `month*` | | `DateValue` | The month in which the cell is rendered | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `dayValue` | `string` | Current day | | `disabled` | `boolean` | Current disable state | | `selected` | `boolean` | Current selected state | | `today` | `boolean` | Current today state | | `outsideView` | `boolean` | Current outside view state | | `outsideVisibleView` | `boolean` | Current outside visible view state | | `unavailable` | `boolean` | Current unavailable state | [DatePickerCellTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker/DatePickerCellTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-selected]` | Present when selected | | `[data-value]` | The ISO string value of the date. | | `[data-disabled]` | Present when disabled | | `[data-unavailable]` | Present when unavailable | | `[data-today]` | Present when today | | `[data-outside-view]` | Present when the date is outside the current month it is displayed in. | | `[data-outside-visible-view]` | Present when the date is outside the months that are visible on the calendar. | | `[data-focused]` | Present when focused | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the date field, focuses the first segment. | | Space | When the focus is on either `DatePickerNext` or `DatePickerPrev`, it navigates the calendar. Otherwise, it selects the date. If the focus is on `DatePickerTrigger`, it opens/closes the popover. | | Enter | When the focus is on either `DatePickerNext` or `DatePickerPrev`, it navigates the calendar. Otherwise, it selects the date. If the focus is on `DatePickerTrigger`, it opens/closes the popover. | | ArrowLeft / ArrowRight | Navigates between the date field segments. If the focus is on the `DatePickerCalendar`, it navigates between the dates. | | ArrowUp / ArrowDown | Increments/changes the value of the segment. If the focus is on the `DatePickerCalendar`, it navigates between the dates. | | 0-9 | When the focus is on a numeric `DatePickerInput`, it types in the number and focuses the next segment if the next input would result in an invalid value. | | Backspace | Deletes a digit from the focused numeric segments. | | A / P | When the focus is on the day period, it sets it to AM or PM. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DatePicker) - [npm](https://www.npmjs.com/package/akar) # Date Range Field > Allows users to input a range of dates within a designated field. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-DateRangeField) { .DateFieldWrapper { display: flex; flex-direction: column; gap: 0.5rem; } .DateFieldLabel { font-size: 0.875rem; line-height: 1.25rem; color: var(--gray-9); } .DateField { display: flex; padding: 0.5rem; align-items: center; border-radius: 0.25rem; border-width: 1px; text-align: center; background-color: #ffffff; user-select: none; color: var(--green-10); border: 1px solid var(--gray-9); } .DateField::placeholder { color: var(--mauve-5); } .DateField[data-invalid] { border: 1px solid var(--red-500); } .DateFieldLiteral { padding: 0.25rem; } .DateFieldSegment { padding: 0.25rem; } .DateFieldSegment:hover{ background-color: var(--grass-4); } .DateFieldSegment:focus { background-color: var(--grass-2); } .DateFieldSegment:[aria-valuetext='Empty'] { color: var(--grass-6); } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Highly composable - Accessible by default - Supports both date and date-time formats ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a date field **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `defaultPlaceholder` | | `DateValue` | The default placeholder date | | `defaultValue` | | `DateRange` | The default value for the calendar | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the date field when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | Whether or not the date field is disabled | | `granularity` | | `"day" \| "hour" \| "minute" \| "second"` | The granularity to use for formatting times. Defaults to day if a CalendarDate is provided, otherwise defaults to minute. The field will render segments for each part of the date up to and including the specified granularity | | `hideTimeZone` | | `boolean` | Whether or not to hide the time zone segment of the field | | `hourCycle` | | `12 \| 24` | The hour cycle used for formatting times. Defaults to the local preference | | `id` | | `string` | Id of the element | | `isDateUnavailable` | | `Matcher` | A function that returns whether or not a date is unavailable | | `locale` | | `string` | The locale to use for formatting dates | | `maxValue` | | `DateValue` | The maximum date that can be selected | | `minValue` | | `DateValue` | The minimum date that can be selected | | `modelValue` | | `DateRange \| null` | The controlled value of the field. Can be bound as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `placeholder` | | `DateValue` | The placeholder date, which is used to determine what month to display when no date is selected. This updates as the user navigates the calendar and can be used to programmatically control the calendar view | | `readonly` | `false` | `boolean` | Whether or not the date field is readonly | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | | `DateStep` | The stepping interval for the time fields. Defaults to `1`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: DateRange` | Event handler called whenever the model value changes | | `update:placeholder` | `date: DateValue` | Event handler called whenever the placeholder value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `DateRange \| null` | The current date range of the field | | `segments` | `{ start: { part: SegmentPart; value: string; }[]; end: { part: SegmentPart; value: string; }[]; }` | The date field segment contents | | `isInvalid` | `boolean` | Value if the input is invalid | **Methods** | Method | Type | Description | | --- | --- | --- | | `setFocusedElement` | `(el: HTMLElement) => void` | | [DateRangeFieldRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangeField/DateRangeFieldRoot.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Input Contains the date field segments **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `part*` | | `"day" \| "month" \| "year" \| "hour" \| "minute" \| "second" \| "dayPeriod" \| "literal" \| "timeZoneName"` | The part of the date to render | | `type*` | | `"start" \| "end"` | The type of field to render (start or end) | [DateRangeFieldInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangeField/DateRangeFieldInput.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-placeholder]` | Present when no value is set | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the date field, focuses the first segment. | | ArrowLeft / ArrowRight | Navigates between the date field segments. | | ArrowUp / ArrowDown | Increments/changes the value of the segment. | | 0-9 | When the focus is on a numeric `DateFieldInput`, it types in the number and focuses the next segment if the next input would result in an invalid value. | | Backspace | Deletes a digit from the focused numeric segments. | | A / P | When the focus is on the day period, it sets it to AM or PM. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangeField) - [npm](https://www.npmjs.com/package/akar) # Date Range Picker > Facilitates the selection of date ranges through an input and calendar-based interface. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-DateRangePicker) { .DateFieldWrapper { display: flex; flex-direction: column; gap: 0.5rem; } .DateFieldLabel { font-size: 0.875rem; line-height: 1.25rem; color: var(--gray-9); } .DateField { display: flex; padding: 0.5rem; align-items: center; border-radius: 0.25rem; border-width: 1px; text-align: center; background-color: #ffffff; user-select: none; color: var(--green-10); border: 1px solid var(--gray-9); } .DateField::placeholder { color: var(--mauve-5); } .DateField[data-invalid] { border: 1px solid var(--red-500); } .DateFieldLiteral { padding: 0.25rem; } .DateFieldSegment { padding: 0.25rem; } .DateFieldSegment:hover{ background-color: var(--grass-4); } .DateFieldSegment:focus { background-color: var(--grass-2); } .DateFieldSegment:[aria-valuetext='Empty'] { color: var(--grass-6); } .Icon { width: 1.5rem; height: 1.5rem; } .Calendar { padding: 22px; } .CalendarHeader { display: flex; justify-content: space-between; align-items: center; } .CalendarNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2.5rem; height: 2.5rem; color: #000000; background-color: transparent; cursor: pointer; } .CalendarNavButton:hover { color: #ffffff; background-color: #000000; } .CalendarHeading { font-weight: 500; color: #000000; color: 15px; } .CalendarWrapper { display: flex; padding-top: 1rem; margin-top: 1rem; flex-direction: column; } @media (min-width: 640px) { .CalendarWrapper { margin-left: 1rem; margin-top: 0; flex-direction: row; } } .CalendarGrid { margin-top: 0.25rem; width: 100%; user-select: none; border-collapse: collapse; } .CalendarGridRow { display: grid; margin-bottom: 0.25rem; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; } .CalendarGridRow[data-reka-calendar-month-view] { grid-template-columns: repeat(7, minmax(0, 1fr)); } .CalendarHeadCell { border-radius: 0.375rem; font-size: 0.75rem; line-height: 1rem; color: #000000; font-weight: 400; } .CalendarCell { position: relative; font-size: 0.875rem; line-height: 1.25rem; text-align: center; } .CalendarCellTrigger { display: flex; position: relative; padding: 0.5rem; justify-content: center; align-items: center; border-width: 1px; border-color: transparent; outline-style: none; font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; color: #000000; white-space: nowrap; background-color: transparent; } .CalendarCellTrigger:hover { border-color: #000000; } .CalendarCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .CalendarCellTrigger[data-disabled] { cursor: none; color: rgba(0,0,0,0.3); } .CalendarCellTrigger[data-selected] { background-color: #000000; color: #ffffff; font-weight: 500; } .CalendarCellTrigger[data-selected]::before { background-color: #FFFFFF; } .CalendarCellTrigger[data-unavailable] { color: rgba(0,0,0,0.3); text-decoration: line-through; } .CalendarCellTrigger::before { content: ''; position: absolute; top: 5px; left: 0; width: 0.25rem; height: 0.25rem; border-radius: 9999px; background-color: #FFFFFF; } .CalendarCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } .PopoverTrigger:focus { box-shadow: 0 0 0 2px #000000; } .PopoverContent { border-radius: 4px; padding: 20px; width: 260px; background-color: white; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; animation-duration: 400ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); will-change: transform, opacity; } .PopoverContent:focus { box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px, 0 0 0 2px var(--grass-7); } .PopoverContent[data-state='open'][data-side='top'] { animation-name: slideDownAndFade; } .PopoverContent[data-state='open'][data-side='right'] { animation-name: slideLeftAndFade; } .PopoverContent[data-state='open'][data-side='bottom'] { animation-name: slideUpAndFade; } .PopoverContent[data-state='open'][data-side='left'] { animation-name: slideRightAndFade; } .PopoverArrow { fill: white; } @keyframes slideUpAndFade { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideRightAndFade { from { opacity: 0; transform: translateX(-2px); } to { opacity: 1; transform: translateX(0); } } @keyframes slideDownAndFade { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideLeftAndFade { from { opacity: 0; transform: translateX(2px); } to { opacity: 1; transform: translateX(0); } } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Accessible by default - Supports both date and date-time formats ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a date picker **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `allowNonContiguousRanges` | `false` | `boolean` | When combined with `isDateUnavailable`, determines whether non-contiguous ranges, i.e. ranges containing unavailable dates, may be selected. | | `closeOnSelect` | `false` | `boolean` | Whether or not to close the popover on range select | | `defaultOpen` | `false` | `boolean` | The open state of the popover when it is initially rendered. Use when you do not need to control its open state. | | `defaultPlaceholder` | | `DateValue` | The default placeholder date | | `defaultValue` | `{ start: undefined, end: undefined }` | `DateRange` | The default value for the calendar | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the date field when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | Whether or not the date field is disabled | | `fixedDate` | | `"start" \| "end"` | Which part of the range should be fixed | | `fixedWeeks` | `false` | `boolean` | Whether or not to always display 6 weeks in the calendar | | `granularity` | | `"day" \| "hour" \| "minute" \| "second"` | The granularity to use for formatting times. Defaults to day if a CalendarDate is provided, otherwise defaults to minute. The field will render segments for each part of the date up to and including the specified granularity | | `hideTimeZone` | | `boolean` | Whether or not to hide the time zone segment of the field | | `hourCycle` | | `12 \| 24` | The hour cycle used for formatting times. Defaults to the local preference | | `id` | | `string` | Id of the element | | `isDateDisabled` | | `Matcher` | A function that returns whether or not a date is disabled | | `isDateHighlightable` | | `Matcher` | A function that returns whether or not a date is hightable | | `isDateUnavailable` | | `Matcher` | A function that returns whether or not a date is unavailable | | `locale` | | `string` | The locale to use for formatting dates | | `maximumDays` | | `number` | The maximum number of days that can be selected in a range | | `maxValue` | | `DateValue` | The maximum date that can be selected | | `minValue` | | `DateValue` | The minimum date that can be selected | | `modal` | `false` | `boolean` | The modality of the popover. When set to true, interaction with outside elements will be disabled and only popover content will be visible to screen readers. | | `modelValue` | | `DateRange \| null` | The controlled value of the field. Can be bound as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `numberOfMonths` | `1` | `number` | The number of months to display at once | | `open` | | `boolean` | The controlled open state of the popover. | | `pagedNavigation` | `false` | `boolean` | This property causes the previous and next buttons to navigate by the number of months displayed at once, rather than one month | | `placeholder` | | `DateValue` | The placeholder date, which is used to determine what month to display when no date is selected. This updates as the user navigates the calendar and can be used to programmatically control the calendar view | | `preventDeselect` | `false` | `boolean` | Whether or not to prevent the user from deselecting a date without selecting another date first | | `readonly` | `false` | `boolean` | Whether or not the date field is readonly | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | | `DateStep` | The stepping interval for the time fields. Defaults to `1`. | | `weekdayFormat` | `"narrow"` | `"narrow" \| "short" \| "long"` | The format to use for the weekday strings provided via the weekdays slot prop | | `weekStartsOn` | | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | The day of the week to start the calendar on | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: DateRange` | Event handler called whenever the model value changes | | `update:open` | `value: boolean` | Event handler called when the open state of the popover changes. | | `update:placeholder` | `date: DateValue` | Event handler called whenever the placeholder value changes | | `update:startValue` | `date: DateValue` | Event handler called whenever the start value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `DateRange` | | | `open` | `boolean` | | [DateRangePickerRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerRoot.vue) ### Field Contains the date picker date field segments and trigger **Slots** | Slot | Payload | Description | | --- | --- | --- | | `segments` | `{ start: { part: SegmentPart; value: string; }[]; end: { part: SegmentPart; value: string; }[]; }` | | | `modelValue` | `DateRange \| null` | | [DateRangePickerField.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerField.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Input Contains the date picker date field segments **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `part*` | | `"day" \| "month" \| "year" \| "hour" \| "minute" \| "second" \| "dayPeriod" \| "literal" \| "timeZoneName"` | The part of the date to render | | `type*` | | `"start" \| "end"` | The type of field to render (start or end) | [DateRangePickerInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerInput.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-placeholder]` | Present when no value is set | ### Trigger The button that toggles the popover. By default, the `DateRangePickerContent` will position itself against the trigger. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DateRangePickerTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerTrigger.vue) ### Content The component that pops out when the popover is open. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.
May change when collisions occur. | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the popper content when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disableOutsidePointerEvents` | | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside
the `DismissableLayer`. Users will need to click twice on outside elements to
interact with them: once to close the `DismissableLayer`, and again to trigger the element. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `portal` | | `PopoverPortalProps` | Props to control the portal wrapped around the content. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.
Will be reversed when collisions occur and avoidCollisions
is enabled. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | Event handler called when auto-focusing on open.
Can be prevented. | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [DateRangePickerContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerContent.vue) ### Arrow An optional arrow element to render alongside the popover. This can be used to help visually link the anchor with the `DateRangePickerContent`. Must be rendered inside `DateRangePickerContent`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` | | `width` | `10` | `number` | The width of the arrow in pixels. | [DateRangePickerArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerArrow.vue) ### Close The button that closes an open date picker. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DateRangePickerClose.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerClose.vue) ### Anchor An optional element to position the `DateRangePickerContent` against. If this part is not used, the content will position alongside the `DateRangePickerTrigger`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `reference` | | `ReferenceElement` | The reference (or anchor) element that is being referred to for positioning.

If not provided will use the current component as anchor. | [DateRangePickerAnchor.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerAnchor.vue) ### Calendar Contains all the parts of a calendar **Slots** | Slot | Payload | Description | | --- | --- | --- | | `date` | `DateValue` | | | `grid` | `Grid[]` | | | `weekDays` | `string[]` | | | `weekStartsOn` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | | | `locale` | `string` | | | `fixedWeeks` | `boolean` | | [DateRangePickerCalendar.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerCalendar.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Header Contains the navigation buttons and the heading segments. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DateRangePickerHeader.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerHeader.vue) ### Prev Button Calendar navigation button. It navigates the calendar one month/year/decade in the past based on the current calendar view. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the prev page. Overwrites the `prevPage` function set on the `RangeCalendarRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [DateRangePickerPrev.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerPrev.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Next Button Calendar navigation button. It navigates the calendar one month/year/decade in the future based on the current calendar view. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the next page. Overwrites the `nextPage` function set on the `RangeCalendarRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [DateRangePickerNext.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerNext.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Heading Heading for displaying the current month and year **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `headingValue` | `string` | Current month and year | [DateRangePickerHeading.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerHeading.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Grid Container for wrapping the calendar grid. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DateRangePickerGrid.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerGrid.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | ### Grid Head Container for wrapping the grid head. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DateRangePickerGridHead.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerGridHead.vue) ### Grid Body Container for wrapping the grid body. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DateRangePickerGridBody.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerGridBody.vue) ### Grid Row Container for wrapping the grid row. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DateRangePickerGridRow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerGridRow.vue) ### Head Cell Container for wrapping the head cell. Used for displaying the week days. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DateRangePickerHeadCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerHeadCell.vue) ### Cell Container for wrapping the calendar cells. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `date*` | | `DateValue` | | [DateRangePickerCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerCell.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Cell Trigger Interactable container for displaying the cell dates. Clicking it selects the date. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `day*` | | `DateValue` | | | `month*` | | `DateValue` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `dayValue` | `string` | Current day | | `disabled` | `boolean` | Current disable state | | `selected` | `boolean` | Current selected state | | `today` | `boolean` | Current today state | | `outsideView` | `boolean` | Current outside view state | | `outsideVisibleView` | `boolean` | Current outside visible view state | | `unavailable` | `boolean` | Current unavailable state | | `highlighted` | `boolean` | Current highlighted state | | `highlightedStart` | `boolean` | Current highlighted start state | | `highlightedEnd` | `boolean` | Current highlighted end state | | `selectionStart` | `boolean` | Current selection start state | | `selectionEnd` | `boolean` | Current selection end state | [DateRangePickerCellTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker/DateRangePickerCellTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-selected]` | Present when selected | | `[data-value]` | The ISO string value of the date. | | `[data-disabled]` | Present when disabled | | `[data-unavailable]` | Present when unavailable | | `[data-today]` | Present when today | | `[data-outside-view]` | Present when the date is outside the current month it is displayed in. | | `[data-outside-visible-view]` | Present when the date is outside the months that are visible on the calendar. | | `[data-selection-start]` | Present when the date is the start of the selection. | | `[data-selection-end]` | Present when the date is the end of the selection. | | `[data-highlighted]` | Present when the date is highlighted by the user as they select a range. | | `[data-highlighted-start]` | Present when the date is the start of the range that is highlighted by the user. | | `[data-highlighted-end]` | Present when the date is the end of the range that is highlighted by the user. | | `[data-focused]` | Present when focused | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the date field, focuses the first segment. | | Space | When the focus is on either `DateRangePickerNext` or `DateRangePickerPrev`, it navigates the calendar. Otherwise, it selects the date. If the focus is on `DateRangePickerTrigger`, it opens/closes the popover. | | Enter | When the focus is on either `DateRangePickerNext` or `DateRangePickerPrev`, it navigates the calendar. Otherwise, it selects the date. If the focus is on `DateRangePickerTrigger`, it opens/closes the popover. | | ArrowLeft / ArrowRight | Navigates between the date field segments. If the focus is on the `DateRangePickerCalendar`, it navigates between the dates. | | ArrowUp / ArrowDown | Increments/changes the value of the segment. If the focus is on the `DateRangePickerCalendar`, it navigates between the dates. | | 0-9 | When the focus is on a numeric `DateRangePickerInput`, it types in the number and focuses the next segment if the next input would result in an invalid value. | | Backspace | Deletes a digit from the focused numeric segments. | | A / P | When the focus is on the day period, it sets it to AM or PM. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DateRangePicker) - [npm](https://www.npmjs.com/package/akar) # Dialog > A window overlaid on either the primary window or another dialog window, rendering the content underneath inert. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/green.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Dialog) { /* reset */ button, fieldset, input { all: unset; } .DialogOverlay { background-color: var(--black-a9); position: fixed; inset: 0; animation: overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1); } .DialogContent { background-color: white; border-radius: 6px; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90vw; max-width: 450px; max-height: 85vh; padding: 25px; animation: contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1); } .DialogContent:focus { outline: none; } .DialogTitle { margin: 0; font-weight: 500; color: var(--mauve-12); font-size: 17px; } .DialogDescription { margin: 10px 0 20px; color: var(--mauve-11); font-size: 15px; line-height: 1.5; } .Button { display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; padding: 0 15px; font-size: 15px; line-height: 1; font-weight: 500; height: 35px; } .Button.grass { background-color: white; color: var(--grass-11); box-shadow: 0 2px 10px var(--black-a7); } .Button.grass:hover { background-color: var(--mauve-3); } .Button.grass:focus { box-shadow: 0 0 0 2px black; } .Button.green { background-color: var(--green-4); color: var(--green-11); } .Button.green:hover { background-color: var(--green-5); } .Button.green:focus { box-shadow: 0 0 0 2px var(--green-7); } .IconButton { font-family: inherit; border-radius: 100%; height: 25px; width: 25px; display: inline-flex; align-items: center; justify-content: center; color: var(--grass-11); position: absolute; top: 10px; right: 10px; } .IconButton:hover { background-color: var(--grass-4); } .IconButton:focus { box-shadow: 0 0 0 2px var(--grass-7); } .Fieldset { display: flex; gap: 20px; align-items: center; margin-bottom: 15px; } .Label { font-size: 15px; color: var(--grass-11); width: 90px; text-align: right; } .Input { width: 100%; flex: 1; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; padding: 0 10px; font-size: 15px; line-height: 1; color: var(--grass-11); box-shadow: 0 0 0 1px var(--grass-7); height: 35px; } .Input:focus { box-shadow: 0 0 0 2px var(--grass-8); } @keyframes overlayShow { from { opacity: 0; } to { opacity: 1; } } @keyframes contentShow { from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); } to { opacity: 1; transform: translate(-50%, -50%) scale(1); } } } ``` ## Features - Supports modal and non-modal modes. - Focus is automatically trapped when modal. - Can be controlled or uncontrolled. - Manages screen reader announcements with `Title` and`Description` components. - Esc closes the component automatically. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a dialog **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defaultOpen` | `false` | `boolean` | The open state of the dialog when it is initially rendered. Use when you do not need to control its open state. | | `modal` | `true` | `boolean` | The modality of the dialog When set to `true`,

interaction with outside elements will be disabled and only dialog content will be visible to screen readers. | | `open` | | `boolean` | The controlled open state of the dialog. Can be binded as `v-model:open`. | | `unmountOnHide` | `true` | `boolean` | When set to `false`, the dialog content will not be unmounted when closed, but instead hidden with CSS.

Useful for SEO or when you want to improve performance by not remounting the component on every open. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `value: boolean` | Event handler called when the open state of the dialog changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | | `close` | `(): void` | Close the dialog | [DialogRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogRoot.vue) ### Trigger The button that opens the dialog **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [DialogTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### Portal When used, portals your overlay and content parts into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [DialogPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogPortal.vue) ### Overlay A layer that covers the inert portion of the view when the dialog is open. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [DialogOverlay.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogOverlay.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### Content Contains content to be rendered in the open dialog > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disableOutsidePointerEvents` | | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside
the `DismissableLayer`. Users will need to click twice on outside elements to
interact with them: once to close the `DismissableLayer`, and again to trigger the element. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | Event handler called when auto-focusing on open.
Can be prevented. | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [DialogContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### Close The button that closes the dialog **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [DialogClose.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogClose.vue) ### Title An accessible title to be announced when the dialog is opened. If you want to hide the title, wrap it inside our Visually Hidden utility like this ``. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"h2"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [DialogTitle.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogTitle.vue) ### Description An optional accessible description to be announced when the dialog is opened. If you want to hide the description, wrap it inside our Visually Hidden utility like this ``. If you want to remove the description entirely, remove this part and pass `:aria-describedby="undefined"` to `DialogContent`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"p"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [DialogDescription.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogDescription.vue) ## Examples ### Nested dialog You can nest multiple layers of dialogs. ```vue [index.vue] ``` ### Close after asynchronous form submission Use the controlled props to programmatically close the Dialog after an async operation has completed. ```vue ``` ### Scrollable overlay Move the content inside the overlay to render a dialog with overflow. ```vue // index.vue ``` ```css /* styles.css */ .DialogOverlay { background: rgba(0 0 0 / 0.5); position: fixed; top: 0; left: 0; right: 0; bottom: 0; display: grid; place-items: center; overflow-y: auto; } .DialogContent { min-width: 300px; background: white; padding: 30px; border-radius: 4px; } ``` However, there's a caveat to this approach, where user might click on the scrollbar and close the dialog unintentionally. There's no universal solution that would fix this issue for now, however you can add the following snippet to `DialogContent` to prevent closing of modal when clicking on scrollbar. ```vue ``` ### Custom portal container Customise the element that your dialog portals into. ```vue ``` ### Disable close on interaction outside If a global toast (or similar overlay) should not dismiss the dialog when clicked, cancel `interact-outside` when the event target is inside that overlay. ```vue … ``` ## Accessibility Adheres to the [Dialog WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/). ### Close icon button When providing an icon (or font icon), remember to label it correctly for screen reader users. ```vue ``` ### Close using slot props Alternatively, you can use the `close` method provided by the `DialogRoot` slot props to programmatically close the dialog. ```vue ``` ### Keyboard Interactions | Key | Description | | --- | --- | | Space | Opens/closes the dialog | | Enter | Opens/closes the dialog | | Tab | Moves focus to the next focusable element. | | Shift + Tab | Moves focus to the previous focusable element. | | Esc | Closes the dialog and moves focus to `DialogTrigger`. | ## Custom APIs Create your own API by abstracting the primitive parts into your own component. ### Abstract the overlay and the close button This example abstracts the `DialogOverlay` and `DialogClose` parts. #### Usage ```vue ``` #### Implementation ```ts export { DialogRoot as Dialog, DialogTrigger } from 'akar'; // your-dialog.ts export { default as DialogContent } from 'DialogContent.vue'; ``` ```vue ``` --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog) - [npm](https://www.npmjs.com/package/akar) # Drawer > A panel that slides in from the edge of the screen, with support for swipe-to-dismiss, snap points, and nested drawers. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/green.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Drawer) { /* reset */ button, fieldset, input { all: unset; } .DrawerOverlay { background-color: var(--black-a9); position: fixed; inset: 0; z-index: 30; } .DrawerOverlay[data-state='open'] { animation: drawerOverlayShow 450ms cubic-bezier(0.32, 0.72, 0, 1); } .DrawerOverlay[data-state='closed'] { animation: drawerOverlayHide 450ms cubic-bezier(0.32, 0.72, 0, 1); } .DrawerContent { /* Extra drawer area that hangs below the viewport edge, kept off-screen by an equal negative margin. Pulling the drawer away from its edge slides the bleed into view instead of exposing the overlay behind it, so the drawer stretches rather than visually detaching while it rubber-bands. */ --bleed: 48px; background-color: white; border-radius: 16px 16px 0 0; position: fixed; inset-inline: 0; bottom: 0; margin-inline: auto; margin-bottom: calc(-1 * var(--bleed)); padding-bottom: calc(env(safe-area-inset-bottom, 0px) + var(--bleed)); max-width: 500px; display: flex; flex-direction: column; outline: none; z-index: 100; /* `--drawer-swipe-movement-y` is written by DrawerContent while dragging. */ transform: translateY(var(--drawer-swipe-movement-y, 0px)); transition: transform 450ms cubic-bezier(0.32, 0.72, 0, 1); will-change: transform; } /* Enter/exit keyframes animate the independent `translate` property so they compose with the inline `transform` carrying the live drag offset. */ .DrawerContent[data-state='open'] { animation: drawerSlideBottomIn 450ms cubic-bezier(0.32, 0.72, 0, 1); } .DrawerContent[data-state='closed'] { animation: drawerSlideBottomOut 450ms cubic-bezier(0.32, 0.72, 0, 1); } /* Silence the transform transition during an active drag so it tracks the pointer in real time. */ .DrawerContent[data-swiping] { transition-duration: 0ms; user-select: none; } .DrawerHandle { width: 48px; height: 6px; margin: 12px auto 0; flex-shrink: 0; border-radius: 9999px; background-color: var(--mauve-6); } .DrawerBody { padding: 24px; } .DrawerTitle { margin: 0; color: var(--mauve-12); font-size: 17px; font-weight: 600; } .DrawerDescription { margin: 10px 0 20px; color: var(--mauve-11); font-size: 15px; line-height: 1.5; } .DrawerFooter { display: flex; margin-top: 25px; justify-content: flex-end; } .Fieldset { display: flex; gap: 20px; align-items: center; margin-bottom: 15px; } .Label { width: 90px; text-align: right; font-size: 15px; color: var(--grass-11); } .Input { width: 100%; flex: 1; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; padding: 0 10px; height: 35px; font-size: 15px; line-height: 1; color: var(--grass-11); background-color: #fafafa; box-shadow: 0 0 0 1px var(--green-7); } .Input:focus { box-shadow: 0 0 0 2px var(--green-8); } .Button { display: inline-flex; align-items: center; justify-content: center; border-radius: 6px; padding: 0 15px; font-size: 15px; line-height: 1; height: 35px; font-weight: 600; cursor: pointer; } .Button.grass { background-color: white; color: var(--grass-11); box-shadow: 0 2px 10px var(--black-a7); } .Button.grass:hover { background-color: var(--mauve-3); } .Button.green { background-color: var(--green-4); color: var(--green-11); } .Button.green:hover { background-color: var(--green-5); } @keyframes drawerOverlayShow { from { opacity: 0; } } @keyframes drawerOverlayHide { to { opacity: 0; } } /* The bleed already sits below the viewport edge, so the drawer only has to travel `height - bleed` to clear it. Translating a full 100% would overshoot by the bleed and make the slide look faster than it is. */ @keyframes drawerSlideBottomIn { from { translate: 0 calc(100% - var(--bleed)); } } @keyframes drawerSlideBottomOut { to { translate: 0 calc(100% - var(--bleed)); } } } ``` ## Features - Slides in from any edge — bottom, top, left or right. - Swipe-to-dismiss with momentum, plus optional swipe-to-open. - Supports snap points for partially-open resting positions. - Modal, focus-trapped non-modal, and fully non-modal modes. - Can be controlled or uncontrolled. - Manages screen reader announcements with `Title` and `Description` components. - Esc closes the component automatically. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## Animating the drawer The Drawer is unstyled, so the enter/exit transitions and the swipe gesture are driven entirely by your CSS. `DrawerContent` exposes the drag offset through CSS custom properties so you can wire up the live transform: - `--drawer-swipe-movement-y` — vertical drag offset (for top/bottom drawers) - `--drawer-swipe-movement-x` — horizontal drag offset (for left/right drawers) - `--drawer-snap-point-offset` — offset of the active snap point, when snap points are used - `--drawer-swipe-progress` — `0` at rest, approaching `1` as the drawer is swiped away ```css .DrawerContent { /* Follow the pointer while dragging. */ transform: translateY(var(--drawer-swipe-movement-y, 0px)); transition: transform 450ms cubic-bezier(0.32, 0.72, 0, 1); } /* Use the independent `translate` property for the enter/exit keyframes so they compose with the `transform` above instead of clobbering the drag offset. */ .DrawerContent[data-state='open'] { animation: slideIn 450ms cubic-bezier(0.32, 0.72, 0, 1); } .DrawerContent[data-state='closed'] { animation: slideOut 450ms cubic-bezier(0.32, 0.72, 0, 1); } /* Cut the transition while actively dragging so the drawer tracks the pointer. */ .DrawerContent[data-swiping] { transition-duration: 0ms; } @keyframes slideIn { from { translate: 0 100%; } } @keyframes slideOut { to { translate: 0 100%; } } ``` ### Bleeding past the edge Dragging a drawer *away* from the edge it is anchored to doesn't dismiss it — the gesture is damped and the drawer rubber-bands back on release. Without extra room the drawer lifts clean off the edge during that pull and the overlay shows through the gap. Give the drawer some **bleed**: extra area past its anchored edge, held off-screen by an equal negative margin. Pulling the drawer now slides the bleed into view instead of the overlay, so it reads as a stretch rather than a detachment. ```css .DrawerContent { --bleed: 48px; padding-bottom: calc(env(safe-area-inset-bottom, 0px) + var(--bleed)); margin-bottom: calc(-1 * var(--bleed)); } /* The bleed already sits below the viewport edge, so the drawer only has to travel `height - bleed` to clear it. */ @keyframes slideIn { from { translate: 0 calc(100% - var(--bleed)); } } @keyframes slideOut { to { translate: 0 calc(100% - var(--bleed)); } } ``` For a side drawer, swap the axis and point the bleed at the edge the drawer is anchored to — a right-anchored drawer bleeds right, a left-anchored one bleeds left: ```css /* Anchored right */ .DrawerContent { padding-inline-end: calc(24px + var(--bleed)); margin-inline-end: calc(-1 * var(--bleed)); } @keyframes slideIn { from { translate: calc(100% - var(--bleed)) 0; } } /* Anchored left */ .DrawerContent { padding-inline-start: calc(24px + var(--bleed)); margin-inline-start: calc(-1 * var(--bleed)); } @keyframes slideIn { from { translate: calc(-100% + var(--bleed)) 0; } } ``` ## Soft keyboard On mobile the software keyboard slides over the bottom of the viewport without resizing it, so a bottom-anchored drawer — and the field the user just tapped — end up underneath it. Wrap the drawer in `DrawerVirtualKeyboardProvider` to make it react. It requires a `DrawerViewport` around `DrawerContent`: the viewport is the measurement root and hosts the keyboard variable, which inherits into the popup and everything in it. ```vue ``` While a field inside the drawer is focused, the provider scrolls it into the band left visible above the keyboard and publishes the keyboard's height as `--drawer-keyboard-inset` on the viewport. - **Keep the popup frame stable** — put header and footer content outside a plain scrollable body so only the body moves. - **Lift a pinned footer** — offset it by `var(--drawer-keyboard-inset, 0px)`, either as padding or as part of its height. - **Always include the 0px fallback** — the variable is only set while the keyboard is aligned, so a bare `var(--drawer-keyboard-inset)` is invalid before the first alignment and after cleanup. ```css .DrawerFooter { padding-bottom: calc(1rem + var(--drawer-keyboard-inset, 0px)); } ``` To lift the whole sheet instead, give up the keyboard's height so its top stays on screen: ```css .DrawerContent { height: calc(90dvh - var(--drawer-keyboard-inset, 0px)); max-height: calc(90dvh - var(--drawer-keyboard-inset, 0px)); } ``` Alignment is suspended while the viewport is pinch-zoomed, and viewport changes under 60px are treated as browser chrome rather than the keyboard. ## API Reference ### Root Contains all the parts of a drawer. Manages open state, modality, swipe direction and snap points, and provides the context consumed by every other part. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defaultOpen` | `false` | `boolean` | | | `defaultSnapPoint` | | `null \| string \| number` | | | `modal` | `true` | `false \| true \| "trap-focus"` | Modality of the drawer.
- `true` (default): modal with focus trap, scroll lock, and outside-press dismiss
- `'trap-focus'`: traps focus but allows outside pointer events (non-modal side panels)
- `false`: non-modal | | `open` | | `boolean` | v-model:open | | `snapPoint` | | `null \| string \| number` | v-model:snapPoint | | `snapPoints` | | `DrawerSnapPoint[]` | Preset snap positions (fractions 0-1, pixels >1, or '148px'/'30rem' strings) | | `snapToSequentialPoints` | `false` | `boolean` | When true, snaps to the next sequential snap point (one step at a time).
When false, snaps to the nearest snap point by distance. | | `swipeDirection` | `"down"` | `"right" \| "left" \| "down" \| "up"` | Direction to swipe to dismiss. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `value: boolean, details?: DrawerOpenChangeDetails` | | | `update:openComplete` | `value: boolean` | | | `update:snapPoint` | `value: DrawerSnapPoint \| null` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | | | `close` | `(): void` | | [DrawerRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerRoot.vue) ### Trigger The button that opens the drawer. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DrawerTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### Portal When used, portals your overlay and content parts into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [DrawerPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerPortal.vue) ### Overlay A layer that covers the inert portion of the view when the drawer is open. Only rendered when the drawer is `modal`. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `forceMount` | `false` | `boolean` | Keep mounted for animation control. | | `forceRender` | `false` | `boolean` | Render even when inside a nested drawer. | [DrawerOverlay.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerOverlay.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-swipe-direction]` | "up" \\| "down" \\| "left" \\| "right" | | `[data-swiping]` | "Present when the drawer is being dragged" | ### Content Contains the content to be rendered in the open drawer. Owns the swipe gesture and exposes the drag offset through CSS custom properties (see [Animating the drawer](#animating-the-drawer)). Also aliased as `DrawerPopup` for Base UI parity. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `disableOutsidePointerEvents` | | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside
the `DismissableLayer`. Users will need to click twice on outside elements to
interact with them: once to close the `DismissableLayer`, and again to trigger the element. | | `finalFocus` | `true` | `boolean \| HTMLElement \| null` | Final focus target when the drawer closes.
- `true` / default: focus the trigger
- `false`: do not restore focus
- element ref: focus that specific element | | `forceMount` | | `boolean` | | | `initialFocus` | `true` | `boolean \| HTMLElement \| null` | Initial focus target when the drawer opens.
- `true` / default: focus the first focusable element inside
- `false`: do not focus anything
- element ref: focus that specific element | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [DrawerContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-swipe-direction]` | "up" \\| "down" \\| "left" \\| "right" | | `[data-swiping]` | "Present while the drawer is being dragged" | | `[data-nested-drawer-open]` | "Present when a nested drawer is open" | ### Close The button that closes the drawer. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DrawerClose.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerClose.vue) ### Title An accessible title to be announced when the drawer is opened. If you want to hide the title, wrap it inside our Visually Hidden utility like this ``. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"h2"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DrawerTitle.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerTitle.vue) ### Description An optional accessible description to be announced when the drawer is opened. If you want to hide the description, wrap it inside our Visually Hidden utility like this ``. If you want to remove the description entirely, remove this part and pass `:aria-describedby="undefined"` to `DrawerContent`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"p"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DrawerDescription.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerDescription.vue) ### Handle A visual grab handle that hints the drawer can be dragged. It is purely decorative (`aria-hidden`) — the whole content is draggable regardless. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DrawerHandle.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerHandle.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### SwipeArea An off-screen edge area that lets users swipe the drawer **open**. By default it listens on the opposite side of the Root's `swipeDirection`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `disabled` | `false` | `boolean` | Disable swipe-to-open. | | `swipeDirection` | | `"right" \| "left" \| "down" \| "up"` | Override the open swipe direction (defaults to opposite of Root's swipeDirection). | [DrawerSwipeArea.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerSwipeArea.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-swipe-direction]` | "up" \\| "down" \\| "left" \\| "right" | ### Viewport An optional wrapper around `DrawerContent`. Mirrors Base UI's `Drawer.Viewport` and carries a `data-drawer-viewport` attribute for downstream selectors. Required when using `VirtualKeyboardProvider`, which measures the keyboard against it. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DrawerViewport.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerViewport.vue) ### VirtualKeyboardProvider Makes the drawer react to the software keyboard: it keeps the focused field visible and exposes `--drawer-keyboard-inset` on `DrawerViewport`, which it requires (see [Soft keyboard](#soft-keyboard)). Takes no props and renders no markup of its own. ### Indent Wraps page content that should visually shift (scale/indent) as the drawer is swiped, mimicking the native iOS "card stack" effect. Reads the visual state from a parent `DrawerProvider` and syncs the `--drawer-swipe-progress` and `--drawer-height` CSS variables onto its element. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DrawerIndent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerIndent.vue) | Data attribute | Value | | --- | --- | | `[data-active]` | "Present when a drawer is open" | | `[data-inactive]` | "Present when no drawer is open" | ### IndentBackground The backdrop layer revealed behind an indented page (typically a solid colour that peeks out as the page scales down). Companion to `Indent`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [DrawerIndentBackground.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer/DrawerIndentBackground.vue) | Data attribute | Value | | --- | --- | | `[data-active]` | "Present when a drawer is open" | | `[data-inactive]` | "Present when no drawer is open" | ## Examples ### Choosing a side `DrawerRoot` slides up from the bottom by default. Set `swipeDirection` to change the edge the drawer attaches to and the direction users swipe to dismiss it. ```vue ``` ```css /* A right-anchored drawer slides along the X axis instead. */ .DrawerContent { position: fixed; inset-block: 0; right: 0; width: 20rem; transform: translateX(var(--drawer-swipe-movement-x, 0px)); transition: transform 450ms cubic-bezier(0.32, 0.72, 0, 1); } .DrawerContent[data-state='open'] { animation: slideInRight 450ms cubic-bezier(0.32, 0.72, 0, 1); } .DrawerContent[data-state='closed'] { animation: slideOutRight 450ms cubic-bezier(0.32, 0.72, 0, 1); } .DrawerContent[data-swiping] { transition-duration: 0ms; } @keyframes slideInRight { from { translate: 100% 0; } } @keyframes slideOutRight { to { translate: 100% 0; } } ``` ### Snap points Provide `snapPoints` to give the drawer intermediate resting positions. Each point is a fraction (`0`–`1`), a pixel value (`> 1`), or a string like `'148px'` / `'30rem'`. Use `v-model:snapPoint` to read or control the active one. ```vue ``` ### Non-modal drawer By default the drawer is `modal`: it traps focus, locks scroll, and dismisses on outside press. Set `modal` to `'trap-focus'` to keep the focus trap while still allowing interaction with the rest of the page (no overlay is rendered), or to `false` for a fully non-modal panel. ```vue ``` ### Reacting to why the drawer closed The `update:open` event carries a `details` object whose `reason` tells you what triggered the change — useful for distinguishing a deliberate close from a swipe. ```vue ``` Possible reasons are `swipe`, `escape-key`, `outside-press`, `click`, `cancel`, `trigger-press` and `close-press`. ### Close using slot props `DrawerRoot` exposes `open` and `close` via its default slot, so you can close the drawer programmatically from anywhere inside it. ```vue ``` ## Accessibility Adheres to the [Dialog WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/). ### Keyboard Interactions | Key | Description | | --- | --- | | Space | Opens/closes the drawer. | | Enter | Opens/closes the drawer. | | Tab | Moves focus to the next focusable element. | | Shift + Tab | Moves focus to the previous focusable element. | | Esc | Closes the drawer and moves focus to `DrawerTrigger`. | ## Custom APIs Create your own API by abstracting the primitive parts into your own component. ### Abstract the overlay and the portal This example abstracts the `DrawerPortal` and `DrawerOverlay` parts. #### Usage ```vue ``` #### Implementation ```ts export { DrawerRoot as Drawer, DrawerTrigger } from 'akar'; // your-drawer.ts export { default as DrawerContent } from 'DrawerContent.vue'; ``` ```vue ``` --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Drawer) - [npm](https://www.npmjs.com/package/akar) # Dropdown Menu > Displays a menu to the user—such as a set of actions or functions—triggered by a button. ## DropdownMenu ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-DropdownMenu) { /* reset */ button { all: unset; } .DropdownMenuContent, .DropdownMenuSubContent { min-width: 220px; background-color: white; border-radius: 6px; padding: 5px; box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2); animation-duration: 400ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); will-change: transform, opacity; } .DropdownMenuContent[data-side='top'], .DropdownMenuSubContent[data-side='top'] { animation-name: slideDownAndFade; } .DropdownMenuContent[data-side='right'], .DropdownMenuSubContent[data-side='right'] { animation-name: slideLeftAndFade; } .DropdownMenuContent[data-side='bottom'], .DropdownMenuSubContent[data-side='bottom'] { animation-name: slideUpAndFade; } .DropdownMenuContent[data-side='left'], .DropdownMenuSubContent[data-side='left'] { animation-name: slideRightAndFade; } .DropdownMenuItem, .DropdownMenuCheckboxItem, .DropdownMenuRadioItem, .DropdownMenuSubTrigger { font-size: 13px; line-height: 1; color: var(--grass-11); border-radius: 3px; display: flex; align-items: center; height: 25px; padding: 0 5px; position: relative; padding-left: 25px; user-select: none; outline: none; } .DropdownMenuSubTrigger[data-state='open'] { background-color: var(--grass-4); color: var(--grass-11); } .DropdownMenuItem[data-disabled], .DropdownMenuCheckboxItem[data-disabled], .DropdownMenuRadioItem[data-disabled], .DropdownMenuSubTrigger[data-disabled] { color: var(--mauve-8); pointer-events: none; } .DropdownMenuItem[data-highlighted], .DropdownMenuCheckboxItem[data-highlighted], .DropdownMenuRadioItem[data-highlighted], .DropdownMenuSubTrigger[data-highlighted] { background-color: var(--grass-9); color: var(--grass-1); } .DropdownMenuLabel { padding-left: 25px; font-size: 12px; line-height: 25px; color: var(--mauve-11); } .DropdownMenuSeparator { height: 1px; background-color: var(--grass-6); margin: 5px; } .DropdownMenuItemIndicator { position: absolute; left: 0; width: 25px; display: inline-flex; align-items: center; justify-content: center; } .DropdownMenuArrow { fill: white; } .IconButton { font-family: inherit; border-radius: 100%; height: 35px; width: 35px; display: inline-flex; align-items: center; justify-content: center; color: var(--grass-11); background-color: white; box-shadow: 0 2px 10px var(--black-a7); } .IconButton:hover { background-color: var(--grass-3); } .IconButton:focus { box-shadow: 0 0 0 2px black; } .RightSlot { margin-left: auto; padding-left: 20px; color: var(--mauve-11); } [data-highlighted] > .RightSlot { color: white; } [data-disabled] .RightSlot { color: var(--mauve-8); } @keyframes slideUpAndFade { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideRightAndFade { from { opacity: 0; transform: translateX(-2px); } to { opacity: 1; transform: translateX(0); } } @keyframes slideDownAndFade { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideLeftAndFade { from { opacity: 0; transform: translateX(2px); } to { opacity: 1; transform: translateX(0); } } } ``` ## Features - Can be controlled or uncontrolled. - Supports submenus with configurable reading direction. - Supports items, labels, groups of items. - Supports checkable items (single or multiple) with optional indeterminate state. - Supports modal and non-modal modes. - Customize side, alignment, offsets, collision handling. - Optionally render a pointing arrow. - Focus is fully managed. - Full keyboard navigation. - Typeahead support. - Dismissing and layering behavior is highly customizable. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a dropdown menu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defaultOpen` | | `boolean` | The open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `modal` | `true` | `boolean` | The modality of the dropdown menu.

When set to `true`, interaction with outside elements will be disabled and only menu content will be visible to screen readers. | | `open` | | `boolean` | The controlled open state of the menu. Can be used as `v-model:open`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `payload: boolean` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | [DropdownMenuRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuRoot.vue) ### Trigger The button that toggles the dropdown menu. By default, the `DropdownMenuContent` will position itself against the trigger. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with item | [DropdownMenuTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | ### Portal When used, portals the content part into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [DropdownMenuPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuPortal.vue) ### Content The component that pops out when the dropdown menu is open. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.
May change when collisions occur. | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.
Will be reversed when collisions occur and avoidCollisions
is enabled. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [DropdownMenuContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | `[data-orientation]` | "vertical" \\| "horizontal" | | CSS variable | Description | | --- | --- | | `--akar-dropdown-menu-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets | | `--akar-dropdown-menu-content-available-width` | The remaining width between the trigger and the boundary edge | | `--akar-dropdown-menu-content-available-height` | The remaining height between the trigger and the boundary edge | | `--akar-dropdown-menu-trigger-width` | The width of the trigger | | `--akar-dropdown-menu-trigger-height` | The height of the trigger | ### Filter An optional search input inside `DropdownMenuContent` or `DropdownMenuSubContent`. It integrates text input with the menu's keyboard navigation. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `autoFocus` | | `boolean` | Focus on element when mounted. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the filter input | | `modelValue` | | `string` | The controlled value of the filter. Can be binded with v-model. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `string` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `string` | Current input values | [DropdownMenuFilter.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuFilter.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Arrow An optional arrow element to render alongside the dropdown menu. This can be used to help visually link the trigger with the `DropdownMenuContent`. Must be rendered inside `DropdownMenuContent`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` | | `width` | `10` | `number` | The width of the arrow in pixels. | [DropdownMenuArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuArrow.vue) ### Item The component that contains the dropdown menu items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).

Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. | [DropdownMenuItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuItem.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### Group Used to group multiple `DropdownMenuItem`s. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [DropdownMenuGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuGroup.vue) ### Label Used to render a label. It won't be focusable using arrow keys. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [DropdownMenuLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuLabel.vue) ### CheckboxItem An item that can be controlled and rendered like a checkbox. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `modelValue` | | `false \| true \| "indeterminate"` | The controlled checked state of the item. Can be used as `v-model`. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).

Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. | | `update:modelValue` | `payload: boolean` | Event handler called when the checked state changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `checked` | `false \| true \| "indeterminate"` | Current checked state | | `modelValue` | `CheckedState` | Current modelValue state | [DropdownMenuCheckboxItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuCheckboxItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### RadioGroup Used to group multiple `DropdownMenuRadioItem`s. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `modelValue` | | `AcceptableValue` | The value of the selected item in the group. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: AcceptableValue` | Event handler called when the value changes. | [DropdownMenuRadioGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuRadioGroup.vue) ### RadioItem An item that can be controlled and rendered like a radio. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | | `value*` | | `AcceptableValue` | The unique value of the item. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).

Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `checked` | `boolean` | Current checked state | [DropdownMenuRadioItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuRadioItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### ItemIndicator Renders when the parent `DropdownMenuCheckboxItem` or `DropdownMenuRadioItem` is checked. You can style this element directly, or you can use it as a wrapper to put an icon into, or both. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [DropdownMenuItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuItemIndicator.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" | ### Separator Used to visually separate items in the dropdown menu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [DropdownMenuSeparator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuSeparator.vue) ### Sub Contains all the parts of a submenu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defaultOpen` | | `boolean` | The open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state. | | `open` | | `boolean` | The controlled open state of the menu. Can be used as `v-model:open`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `payload: boolean` | Event handler called when the open state of the submenu changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | [DropdownMenuSub.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuSub.vue) ### SubTrigger An item that opens a submenu. Must be rendered inside `DropdownMenuSub`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `graceDuration` | `300` | `number` | Time in milliseconds to keep a submenu open while the pointer moves from
its trigger to the submenu. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | [DropdownMenuSubTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuSubTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | | CSS variable | Description | | --- | --- | | `--akar-dropdown-menu-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets | | `--akar-dropdown-menu-content-available-width` | The remaining width between the trigger and the boundary edge | | `--akar-dropdown-menu-content-available-height` | The remaining height between the trigger and the boundary edge | | `--akar-dropdown-menu-trigger-width` | The width of the trigger | | `--akar-dropdown-menu-trigger-height` | The height of the trigger | ### SubContent The component that pops out when a submenu is open. Must be rendered inside `DropdownMenuSub`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `entryFocus` | `event: Event` | | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [DropdownMenuSubContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuSubContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | `[data-orientation]` | "vertical" \\| "horizontal" | ## Examples ### With submenus You can create submenus by using `DropdownMenuSub` in combination with its parts. ```vue ``` ### With disabled items You can add special styles to disabled items via the `data-disabled` attribute. ```vue ``` ```css /* styles.css */ .DropdownMenuItem[data-disabled] { color: gainsboro; } ``` ### With separators Use the `Separator` part to add a separator between items. ```vue ``` ### With labels Use the `Label` part to help label a section. ```vue ``` ### With checkbox items Use the `CheckboxItem` part to add an item that can be checked. ```vue ``` ### With radio items Use the `RadioGroup` and `RadioItem` parts to add an item that can be checked amongst others. ```vue ``` ### With complex items You can add extra decorative elements in the `Item` parts, such as images. ```vue ``` ### Constrain the content/sub-content size You may want to constrain the width of the content (or sub-content) so that it matches the trigger (or sub-trigger) width. You may also want to constrain its height to not exceed the viewport. We expose several CSS custom properties such as `--akar-dropdown-menu-trigger-width` and `--akar-dropdown-menu-content-available-height` to support this. Use them to constrain the content dimensions. ```vue ``` ```css /* styles.css */ .DropdownMenuContent { width: var(--akar-dropdown-menu-trigger-width); max-height: var(--akar-dropdown-menu-content-available-height); } ``` ### Origin-aware animations We expose a CSS custom property `--akar-dropdown-menu-content-transform-origin`. Use it to animate the content from its computed origin based on `side`, `sideOffset`, `align`, `alignOffset` and any collisions. ```vue ``` ```css /* styles.css */ .DropdownMenuContent { transform-origin: var(--akar-dropdown-menu-content-transform-origin); animation: scaleIn 0.5s ease-out; } @keyframes scaleIn { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } } ``` ### Collision-aware animations We expose `data-side` and `data-align` attributes. Their values will change at runtime to reflect collisions. Use them to create collision and direction-aware animations. ```vue ``` ```css /* styles.css */ .DropdownMenuContent { animation-duration: 0.6s; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); } .DropdownMenuContent[data-side="top"] { animation-name: slideUp; } .DropdownMenuContent[data-side="bottom"] { animation-name: slideDown; } @keyframes slideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } ``` ### With filtering Use `DropdownMenuFilter` with a computed list to control which items are displayed. This example matches labels without regard to case and displays a message when no items match. ```vue ``` ## Accessibility Adheres to the [Menu Button WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button) and uses [roving tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex) to manage focus movement among menu items. ### Keyboard Interactions | Key | Description | | --- | --- | ```text When focus is on an item, activates the focused item. `, }, { keys: ['Enter'], description: ` When focus is on DropdownMenuTrigger, opens the dropdown menu and focuses the first item.
When focus is on an item, activates the focused item. `, }, { keys: ['ArrowDown'], description: ` When focus is on DropdownMenuTrigger, opens the dropdown menu.
When focus is on an item, moves focus to the next item. `, }, { keys: ['ArrowUp'], description: ` When focus is on an item, moves focus to the previous item. `, }, { keys: ['ArrowRight', 'ArrowLeft'], description: ` When focus is on DropdownMenuSubTrigger, opens or closes the submenu depending on reading direction. `, }, { keys: ['Esc'], description: ` Closes the dropdown menu and moves focus to{' '} DropdownMenuTrigger. `, }, ``` ]" /> #### When focus is on the filter The input keeps focus while keyboard navigation updates the highlighted item through `aria-activedescendant`. | Key | Description | | --- | --- | | ArrowDown / ArrowUp | Highlights the next or previous enabled item. | | Home / End | Highlights the first or last enabled item. | | Enter | Activates the highlighted item. | | Esc | Clears a non-empty filter without closing the menu. If the filter is empty, closes the menu and returns focus to the trigger. | ## Custom APIs Create your own API by abstracting the primitive parts into your own component. ### Abstract the arrow and item indicators This example abstracts the `DropdownMenuArrow` and `DropdownMenuItemIndicator` parts. It also wraps implementation details for `CheckboxItem` and `RadioItem`. #### Usage ```vue ``` #### Implementation ```ts export { DropdownMenuRoot as DropdownMenu, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuSeparator, DropdownMenuTrigger } from 'akar'; export { default as DropdownMenuCheckboxItem } from 'DropdownMenuCheckboxItem.vue'; // your-dropdown-menu.ts export { default as DropdownMenuContent } from 'DropdownMenuContent.vue'; export { default as DropdownMenuRadioItem } from 'DropdownMenuRadioItem.vue'; ``` ```vue ``` ```vue ``` ```vue ``` --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu) - [npm](https://www.npmjs.com/package/akar) # Editable > Displays an input field used for editing a single line of text, rendering as static text on load. ```vue [index.vue] ``` ```css [styles.css] @scope (.akar-demo-Editable) { .EditableRoot { display: flex; flex-direction: column; gap: 1rem; } .EditableArea { color: var(--white); width: 250px; } .EditableWrapper { display: flex; gap: 1rem; } .EditableSubmitTrigger { display: inline-flex; align-items: center; justify-content: center; border-radius: 0.25rem; font-weight: 500; font-size: 0.9375rem; padding: 0.9375rem 1.25rem; height: 2.1875rem; background-color: var(--grass8); color: var(--white); box-shadow: 0px 2px 1.25rem rgba(0, 0, 0, 0.07), 0px 2px 1.25rem rgba(0, 0, 0, 0.07); outline: none; transition: background-color 0.2s, box-shadow 0.2s; } .EditableTrigger { display: inline-flex; align-items: center; justify-content: center; border-radius: 0.25rem; font-weight: 500; font-size: 0.9375rem; padding: 0.9375rem 1.25rem; height: 2.1875rem; background-color: var(--white); color: var(--grass11); box-shadow: 0px 2px 1.25rem rgba(0, 0, 0, 0.07), 0px 2px 1.25rem rgba(0, 0, 0, 0.07); outline: none; transition: background-color 0.2s, box-shadow 0.2s; } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of an editable component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `activationMode` | `"focus"` | `"dblclick" \| "focus" \| "none"` | The activation event of the editable field | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `autoResize` | `false` | `boolean` | Whether the editable field should auto resize | | `defaultValue` | | `string` | The default value of the editable field | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the calendar when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | Whether the editable field is disabled | | `id` | | `string` | The id of the field | | `maxLength` | | `number` | The maximum number of characters allowed | | `modelValue` | | `string \| null` | The value of the editable field | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `placeholder` | `"Enter text..."` | `string \| { edit: string; preview: string; }` | The placeholder for the editable field | | `readonly` | | `boolean` | Whether the editable field is read-only | | `required` | `false` | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `selectOnFocus` | `false` | `boolean` | Whether to select the text in the input when it is focused. | | `startWithEditMode` | | `boolean` | Whether to start with the edit mode active | | `submitMode` | `"blur"` | `"blur" \| "none" \| "enter" \| "both"` | The submit event of the editable field | **Events** | Event | Payload | Description | | --- | --- | --- | | `submit` | `value: string \| null` | Event handler called when a value is submitted | | `update:modelValue` | `value: string` | Event handler called whenever the model value changes | | `update:state` | `state: "cancel" \| "submit" \| "edit"` | Event handler called when the editable field changes state | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `isEditing` | `boolean` | Whether the editable field is in edit mode | | `modelValue` | `string \| null` | The value of the editable field | | `isEmpty` | `boolean` | Whether the editable field is empty | | `submit` | `(): void` | Function to submit the value of the editable | | `cancel` | `(): void` | Function to cancel the value of the editable | | `edit` | `(): void` | Function to set the editable in edit mode | **Methods** | Method | Type | Description | | --- | --- | --- | | `submit` | `() => void` | Function to submit the value of the editable | | `cancel` | `() => void` | Function to cancel the value of the editable | | `edit` | `() => void` | Function to set the editable in edit mode | [EditableRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Editable/EditableRoot.vue) ### Area Contains the text parts of an editable component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [EditableArea.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Editable/EditableArea.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-placeholder-shown]` | Present when preview is shown | | `[data-empty]` | Present when the input is empty | | `[data-focus]` | Present when the editable field is focused. To be deprecated in favor of [data-focused] | | `[data-focused]` | Present when the editable field is focused | ### Input Contains the input of an editable component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [EditableInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Editable/EditableInput.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | ### Preview Contains the preview of the editable component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [EditablePreview.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Editable/EditablePreview.vue) ### Edit Trigger Contains the edit trigger of the editable component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [EditableEditTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Editable/EditableEditTrigger.vue) ### Submit Trigger Contains the submit trigger of the editable component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [EditableSubmitTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Editable/EditableSubmitTrigger.vue) ### Cancel Trigger Contains the cancel trigger of the editable component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [EditableCancelTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Editable/EditableCancelTrigger.vue) ## Examples ### Change only on submit By default the component will submit when `blur` event triggers. We can modify the `submit-mode` prop to alter this behavior. In this case, we want to submit only when user click on `EditableSubmitTrigger`, so we change the submit mode to `none`. ```vue ``` ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the editable field, switches into the editable mode if the `activation-mode` is set to focus. | | Enter | If the `submit-mode` is set to `enter` or `both`, it submits the changes. | | Escape | When the focus is on the editable field, it cancels the changes. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Editable) - [npm](https://www.npmjs.com/package/akar) # Field > Accessible wiring between a label, control, description, and error message, with built-in validation. ```vue [index.vue] ``` ```css [styles.css] @scope (.akar-demo-Field) { .FieldRoot { display: flex; width: 256px; flex-direction: column; gap: 6px; } .FieldLabel { font-size: 14px; font-weight: 500; color: white; } .FieldControl { border-radius: 6px; border: 1px solid #404040; background-color: #171717; padding: 8px 12px; font-size: 14px; color: white; outline: none; } .FieldControl:focus { box-shadow: 0 0 0 2px #10b981; } .FieldControl[data-invalid] { border-color: #ef4444; } .FieldDescription { font-size: 12px; color: #a3a3a3; } .FieldError { font-size: 12px; color: #ef4444; } } ``` ## Features - Generates and wires up ids/aria-describedby/aria-invalid automatically. - Works with a plain native input, or with existing reka controls (Checkbox, Select, DateField, ...) placed inside it. - Sync or async custom validation, with `onSubmit`/`onBlur`/`onChange` timing and optional debounce. - Validates `required` on non-native controls (Checkbox, Select, DateField) too. - Reads native constraint-validation state (`required`, `pattern`, `type=email`, ...) automatically. - Exposes `data-valid`/`data-invalid`/`data-dirty`/`data-touched`/`data-filled`/`data-focused` on every part for styling. - Shows the browser's validation message by default, or your own per failing constraint. - Fully additive — every reka control behaves exactly as before when used outside a Field. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a field, provides shared ids, and runs validation. Renders a `div` by default. Exposes a `validate()` method through a template ref, which validates the field regardless of `validationMode` and returns whether it's valid. A disabled field skips validation. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `dirty` | | `boolean` | Whether the field's value has changed from its initial value.
Useful when the field state is controlled by an external library. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the field's control. Takes precedence over the `disabled` of the control. | | `invalid` | | `boolean` | When `true`, marks the field invalid regardless of its own validation.
Useful when the field state is controlled by an external library. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a
name/value pair, and used to match server `errors` on a `FormRoot`.
Takes precedence over the `name` of the control. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `touched` | | `boolean` | Whether the field has been touched (its control blurred).
Useful when the field state is controlled by an external library. | | `validate` | | `FieldValidateFn` | Custom validation function. Return an error message (or array of
messages) when invalid, or `null`/`undefined` when valid. Receives the
control's value and the values of every named field in the owning form.

Can be async, but an async `validate` does not prevent form submission
when `validationMode` is `onSubmit`. | | `validationDebounceTime` | | `number` | How long to wait (in ms) between `validate` calls when validating on change. | | `validationMode` | `"onSubmit"` | `"onBlur" \| "onChange" \| "onSubmit"` | When the field (re-)runs validation. Takes precedence over the
`validationMode` of an ancestor `FormRoot`.
- `onSubmit`: when the form is submitted, then on every change after that.
- `onBlur`: when the control loses focus.
- `onChange`: on every change to the control's value. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `invalid` | `boolean` | Whether the field is currently invalid. | | `errors` | `string[]` | All current error messages. | [FieldRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Field/FieldRoot.vue) Every part (and a participating reka control) renders the same data attributes, so any of them can be styled by the field's state. | Data attribute | Value | | --- | --- | | `[data-valid]` | Present once validation has run and the field is valid | | `[data-invalid]` | Present once validation has run and the field is invalid | | `[data-dirty]` | Present while the control's value differs from its initial value | | `[data-touched]` | Present once the control has been blurred | | `[data-filled]` | Present when the control has a non-empty value | | `[data-focused]` | Present while the control is focused | | `[data-disabled]` | Present when disabled | ### Label Renders a [Label](https://vinicunca.dev/akar/components/label), automatically wired to the control via `for`/`id` and the control's `aria-labelledby`. For a button control like `SelectTrigger`, a native `label` forwards clicks and `:hover` to the button. Render another element with `:native-label="false"` instead: it drops `for` and focuses the control on click. ```vue Fruit ``` **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `for` | | `string` | The id of the element the label is associated with. | | `nativeLabel` | `true` | `boolean` | Whether the label renders a native `label` element. Set to `false` when
rendering another element (e.g. `as="div"`): it then drops `for`, focuses
the control on click, and relies on the control's `aria-labelledby`.

Useful for button controls like `SelectTrigger`, where a native label
would forward clicks and `:hover` to the button. | [FieldLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Field/FieldLabel.vue) ### Control A native form control (`input` by default — pass `as="textarea"` or `as="select"` for others). Binds `id`/`name`/`disabled`/`required`/`aria-labelledby`/`aria-describedby`/`aria-invalid` from the Field, and reports focus/blur/input interactions back to it. The Field's `name` takes precedence over the control's; `disabled` and `required` apply when set on either. Bind its value with `v-model`, or set a starting value with `default-value`. A controlled value is validated when it changes, so a value you reject or rewrite never reaches the field. Existing reka controls (`CheckboxRoot`, `SelectRoot`/`SelectTrigger`, `DateFieldRoot`, ...) can be used directly inside a `FieldRoot` instead of `FieldControl` — they pick up the same wiring automatically by optionally reading the Field's context, and behave exactly as before when used outside a Field. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `string \| number` | The value of the control when it is initially rendered. Use when you do not need to control its value. | | `id` | | `string` | Id of the element. Falls back to the id generated by the ancestor `FieldRoot`. | | `modelValue` | | `string \| number` | The controlled value of the control. Can be bound with `v-model`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `value: string` | Event handler called when the value of the control changes. | [FieldControl.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Field/FieldControl.vue) ### Description A description for the field, automatically added to the control's `aria-describedby`. Renders a `p` by default. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"p"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `id` | | `string` | Id of the element. Auto-generated when not provided. | [FieldDescription.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Field/FieldDescription.vue) ### Error An error message for the field, added to the control's `aria-describedby` while shown. Renders a `div` by default. - Without `match`, it shows whenever the field is invalid. Its default content is the current message: a server error, a custom `validate` message, or the browser's validation message. Several messages render as a list. - With a `ValidityState` key like `match="valueMissing"`, it shows only for that constraint, typically with your own message. - With `match` set to `true`, it always shows, letting an external library control it. It never shows while the field is disabled. Its `data-state` is `open` or `closed`, and it waits for a closing animation before unmounting, keeping its last message meanwhile. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. | | `id` | | `string` | Id of the element. Auto-generated when not provided. | | `match` | | `boolean \| keyof ValidityState` | Restricts when this error renders:
- a `ValidityState` key (e.g. `"valueMissing"`) — renders when that constraint fails.
- `true` — always renders, letting an external library control visibility.
- omitted — renders whenever the field is invalid. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `errors` | `string[]` | The error messages this part displays. | [FieldError.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Field/FieldError.vue) ### Validity Renders no element. Passes the field's `validity`, `errors`, `error`, `value` and `initialValue` to its slot, for displaying something custom based on the field's validity. ```vue

{{ error }}

``` **Slots** | Slot | Payload | Description | | --- | --- | --- | | `validity` | `FieldValidityState` | The field's validity. `valid` is `null` until the field has a validity to report. | | `errors` | `string[]` | All current error messages. | | `error` | `string` | The first error message, or an empty string. | | `value` | `unknown` | The value validity was last computed for. | | `initialValue` | `unknown` | The control's initial value. | [FieldValidity.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Field/FieldValidity.vue) ## Examples ### Custom validation Pass a sync or async `validate` function. It receives the control's value and, inside a `FormRoot`, the values of every named field. Return a message (or array of messages) when invalid, or `null`/`undefined` when valid. An async `validate` doesn't prevent form submission in `onSubmit` mode. ```vue ``` ### Validation timing Use `validation-mode` to control when validation (native constraint checks and the custom `validate` function) runs. Whatever the mode, an empty `required` field isn't reported until the user has changed its value, or the form is submitted: - `onSubmit` (default): when the owning `FormRoot` submits, then on every change after that. - `onBlur`: when the control loses focus. - `onChange`: on every change to the control's value. Use `validation-debounce-time` to wait between `validate` calls. A `FieldRoot` without its own `validation-mode` uses the `FormRoot`'s. ```vue ``` ### Using an existing reka control Place any reka form control inside a `FieldRoot` instead of `FieldControl` — it participates automatically. ```vue ``` Participating controls report focus/dirty/filled state, pass their actual value to `validate`, and enforce `required`: an empty `Select`, an unchecked `Checkbox` or an empty `DateField` makes the field invalid (`match="valueMissing"`). ## Accessibility `FieldLabel` associates with the control via matching `for`/`id` and `aria-labelledby`. `FieldDescription` and any shown `FieldError` are added to the control's `aria-describedby`, and `aria-invalid` is set once the field is known to be invalid. Custom errors are also set on native controls with `setCustomValidity`, so the browser's own validity state agrees with the field. --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Field) - [npm](https://www.npmjs.com/package/akar) # Form > Extends the native form element with server error display and submit-time validation gating. ```vue [index.vue] ``` ```css [styles.css] @scope (.akar-demo-Form) { .FormRoot { display: flex; width: 256px; flex-direction: column; gap: 12px; } .FieldRoot { display: flex; flex-direction: column; gap: 6px; } .FieldLabel { font-size: 14px; font-weight: 500; color: white; } .FieldControl { border-radius: 6px; border: 1px solid #404040; background-color: #171717; padding: 8px 12px; font-size: 14px; color: white; outline: none; } .FieldControl:focus { box-shadow: 0 0 0 2px #10b981; } .FieldControl[data-invalid] { border-color: #ef4444; } .FieldError { font-size: 12px; color: #ef4444; } .SubmitButton { border-radius: 6px; background-color: #047857; padding: 8px 12px; font-size: 14px; font-weight: 500; color: white; border: none; cursor: pointer; } .SubmitButton:hover { background-color: #065f46; } .SuccessMessage { font-size: 12px; color: #10b981; } } ``` ## Features - Runs every Field's validation on submit and focuses the first invalid control instead of submitting. - Displays server-side errors by field name, cleared automatically once the user edits that field. - Hands you the value of every named field through `formSubmit`, or leaves a valid form to submit natively. - Sets a default `validationMode` for every Field inside it. - Native `reset` clears every Field's touched/dirty/error state. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. See the [Field](https://vinicunca.dev/akar/components/field) docs for `FieldRoot` and its parts. ```vue ``` ## API Reference ### Root Extends the native `form` element. Provides context that every descendant `FieldRoot` optionally reads for server errors, submit-time validation, and reset handling. Renders with `novalidate`, so the browser's own validation popups don't pre-empt Field errors. Exposes a `validate(name?)` method through a template ref, which validates every field (or only the named one) and returns whether they're valid. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"form"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `errors` | | `Record` | A map of field `name` to server-side error message(s). Displayed by the
matching `FieldRoot`'s `FieldError` until the user edits that field, or a
new value for that key is provided. | | `validationMode` | `"onSubmit"` | `"onBlur" \| "onChange" \| "onSubmit"` | When fields validate. The `validationMode` of a `FieldRoot` takes precedence over this.
- `onSubmit`: when the form is submitted, then on every change after that.
- `onBlur`: when a control loses focus.
- `onChange`: on every change to a control's value. | **Events** | Event | Payload | Description | | --- | --- | --- | | `formSubmit` | `values: Record, event: SubmitEvent` | Emitted after `submit` with the values of every named field. Listening
to it prevents the native submission. | | `submit` | `event: SubmitEvent` | Emitted with the native submit event once every field has validated
successfully. When any field is invalid, the native submission is
prevented and this isn't emitted. Otherwise the form submits natively
(e.g. to its `action`) unless you call `event.preventDefault()`, or
listen to `formSubmit`. | **Methods** | Method | Type | Description | | --- | --- | --- | | `validate` | `(fieldName?: string \| undefined) => boolean` | Validates every field, or only the field with the given `name`. Returns whether they're all valid. | [FormRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Form/FormRoot.vue) ## Examples ### Server-side errors Pass an `errors` map keyed by field `name`. The matching `FieldRoot`'s `FieldError` displays it until the user edits that field, or a new value for that key is provided. When errors arrive in response to a submit, focus moves to the first field they invalidate. ```vue ``` ### Submit gating On submit, `FormRoot` runs every field's validation. If any field is invalid, it prevents the native submission and focuses the first invalid field's control, in document order. Otherwise it emits `submit` with the native event, then: - With a `formSubmit` listener, it prevents the native submission and emits `formSubmit` with the value of every named field. - Without one, the form submits natively (for example to its `action`), unless you call `event.preventDefault()` in your `submit` handler. Only synchronous results gate the submission. An async `validate` runs, and shows its errors once it resolves, but doesn't hold the submission back in `onSubmit` mode. ```vue ``` ### Validation timing Set `validation-mode` on `FormRoot` to change when every field inside it validates. A `FieldRoot`'s own `validation-mode` takes precedence. ```vue ``` ## Accessibility Renders a native `form` element. Focus moves to the first invalid field's control when a submit is blocked, so keyboard and screen-reader users land directly on the field that needs attention. --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Form) - [npm](https://www.npmjs.com/package/akar) # Hover Card > For sighted users to preview content available behind a link. ## HoverCard ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/mauve.css'; @scope (.akar-demo-HoverCard) { /* reset */ a { all: unset; } .HoverCardContent { border-radius: 6px; padding: 20px; width: 300px; background-color: white; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; animation-duration: 400ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); will-change: transform, opacity; } .HoverCardContent[data-side='top'] { animation-name: slideDownAndFade; } .HoverCardContent[data-side='right'] { animation-name: slideLeftAndFade; } .HoverCardContent[data-side='bottom'] { animation-name: slideUpAndFade; } .HoverCardContent[data-side='left'] { animation-name: slideRightAndFade; } .HoverCardArrow { fill: white; } .ImageTrigger { cursor: pointer; border-radius: 100%; display: inline-block; } .ImageTrigger:focus { box-shadow: 0 0 0 2px white; } .Image { display: block; border-radius: 100%; } .Image.normal { width: 45px; height: 45px; } .Image.large { width: 60px; height: 60px; } .Text { margin: 0; color: var(--mauve-12); font-size: 15px; line-height: 1.5; } .Text.faded { color: var(--mauve-10); } .Text.bold { font-weight: 500; } @keyframes slideUpAndFade { 0% { opacity: 0; transform: translateY(2px); } 100% { opacity: 1; transform: translateY(0); } } @keyframes slideRightAndFade { 0% { opacity: 0; transform: translateX(-2px); } 100% { opacity: 1; transform: translateX(0); } } @keyframes slideDownAndFade { 0% { opacity: 0; transform: translateY(-2px); } 100% { opacity: 1; transform: translateY(0); } } @keyframes slideLeftAndFade { 0% { opacity: 0; transform: translateX(2px); } 100% { opacity: 1; transform: translateX(0); } } } ``` ## Features - Can be controlled or uncontrolled. - Customize side, alignment, offsets, collision handling. - Optionally render a pointing arrow. - Supports custom open and close delays. - Ignored by screen readers. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a hover card. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `closeDelay` | `300` | `number` | The duration from when the mouse leaves the trigger or content until the hover card closes. | | `defaultOpen` | `false` | `boolean` | The open state of the hover card when it is initially rendered. Use when you do not need to control its open state. | | `enableTouch` | `false` | `boolean` | When `true`, tapping the trigger on touch devices toggles the hover card open/closed. By default touch interactions are ignored to match pointer hover semantics. | | `open` | | `boolean` | The controlled open state of the hover card. Can be binded as `v-model:open`. | | `openDelay` | `700` | `number` | The duration from when the mouse enters the trigger until the hover card opens. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `value: boolean` | Event handler called when the open state of the hover card changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | [HoverCardRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/HoverCard/HoverCardRoot.vue) ### Trigger The link that opens the hover card when hovered. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"a"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `reference` | | `ReferenceElement` | The reference (or anchor) element that is being referred to for positioning.

If not provided will use the current component as anchor. | [HoverCardTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/HoverCard/HoverCardTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### Portal When used, portals the content part into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [HoverCardPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/HoverCard/HoverCardPortal.vue) ### Content The component that pops out when the hover card is open. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.
May change when collisions occur. | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the popper content when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.
Will be reversed when collisions occur and avoidCollisions
is enabled. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [HoverCardContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/HoverCard/HoverCardContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | CSS variable | Description | | --- | --- | | `--akar-hover-card-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets | | `--akar-hover-card-content-available-width` | The remaining width between the trigger and the boundary edge | | `--akar-hover-card-content-available-height` | The remaining height between the trigger and the boundary edge | | `--akar-hover-card-trigger-width` | The width of the trigger | | `--akar-hover-card-trigger-height` | The height of the trigger | ### Arrow An optional arrow element to render alongside the hover card. This can be used to help visually link the trigger with the `HoverCardContent`. Must be rendered inside `HoverCardContent`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` | | `width` | `10` | `number` | The width of the arrow in pixels. | [HoverCardArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/HoverCard/HoverCardArrow.vue) ## Examples ### Show instantly Use the `openDelay` prop to control the time it takes for the hover card to open. ```vue ``` ### Constrain the content size You may want to constrain the width of the content so that it matches the trigger width. You may also want to constrain its height to not exceed the viewport. We expose several CSS custom properties such as `--akar-hover-card-trigger-width` and `--akar-hover-card-content-available-height` to support this. Use them to constrain the content dimensions. ```vue // index.vue ``` ```css /* styles.css */ .HoverCardContent { width: var(--akar-hover-card-trigger-width); max-height: var(--akar-hover-card-content-available-height); } ``` ### Origin-aware animations We expose a CSS custom property `--akar-hover-card-content-transform-origin`. Use it to animate the content from its computed origin based on `side`, `sideOffset`, `align`, `alignOffset` and any collisions. ```vue ``` ```css /* styles.css */ .HoverCardContent { transform-origin: var(--akar-hover-card-content-transform-origin); animation: scaleIn 0.5s ease-out; } @keyframes scaleIn { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } } ``` ### Collision-aware animations We expose `data-side` and `data-align` attributes. Their values will change at runtime to reflect collisions. Use them to create collision and direction-aware animations. ```vue ``` ```css /* styles.css */ .HoverCardContent { animation-duration: 0.6s; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); } .HoverCardContent[data-side="top"] { animation-name: slideUp; } .HoverCardContent[data-side="bottom"] { animation-name: slideDown; } @keyframes slideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } ``` ## Accessibility The hover card is intended for sighted users only, the content will be inaccessible to keyboard users. ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | Opens/closes the hover card. | | Enter | Opens the hover card link | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/HoverCard) - [npm](https://www.npmjs.com/package/akar) # Label > Renders an accessible label associated with controls. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @scope (.akar-demo-Label) { /* reset */ input { all: unset; } .LabelRoot { font-size: 15px; font-weight: 500; line-height: 35px; color: white; } .Input { width: 200px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; padding: 0 10px; height: 35px; font-size: 15px; line-height: 1; color: white; background-color: var(--black-a5); box-shadow: 0 0 0 1px var(--black-a9); } .Input:focus { box-shadow: 0 0 0 2px black; } .Input::selection { background-color: var(--black-a9); color: white; } } ``` ## Features - Text selection is prevented when double clicking label. - Supports nested controls. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import the component. ```vue ``` ## API Reference ### Root Contains the content for the label. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"label"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `for` | | `string` | The id of the element the label is associated with. | [Label.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Label/Label.vue) ## Accessibility This component is based on the native `label` element, it will automatically apply the correct labelling when wrapping controls or using the `for` attribute. For your own custom controls to work correctly, ensure they use native elements such as `button` or `input` as a base. --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Label) - [npm](https://www.npmjs.com/package/akar) # Listbox > A control that allows the user to toggle between checked and not checked. ```vue [index.vue] ``` ## Features - Can be controlled or uncontrolled. - Supports items, labels, groups of items. - Focus is fully managed. - Full keyboard navigation. - Supports Right to Left direction. - Different selection behavior. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a listbox. An `input` will also render when used within a `form` to ensure events propagate correctly. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `by` | | `string \| ((a: AcceptableValue, b: AcceptableValue) => boolean)` | Use this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared. | | `defaultValue` | | `AcceptableValue \| AcceptableValue[]` | The value of the listbox when initially rendered. Use when you do not need to control the state of the Listbox | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the listbox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with listbox | | `highlightOnHover` | | `boolean` | When `true`, hover over item will trigger highlight | | `modelValue` | | `AcceptableValue \| AcceptableValue[]` | The controlled value of the listbox. Can be binded with `v-model`. | | `multiple` | | `boolean` | Whether multiple options can be selected or not. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `orientation` | `"vertical"` | `"vertical" \| "horizontal"` | The orientation of the listbox.

Mainly so arrow navigation is done accordingly (left & right vs. up & down) | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `selectionBehavior` | `"toggle"` | `"replace" \| "toggle"` | How multiple selection should behave in the collection. | **Events** | Event | Payload | Description | | --- | --- | --- | | `entryFocus` | `event: CustomEvent` | Event handler called when container is being focused. Can be prevented. | | `highlight` | `payload: { ref: HTMLElement; value: AcceptableValue; }` | Event handler when highlighted element changes. | | `leave` | `event: Event` | Event handler called when the mouse leave the container | | `update:modelValue` | `value: AcceptableValue` | Event handler called when the value changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `T \| T[]` | Current active value | [ListboxRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Listbox/ListboxRoot.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Filter Input element to perform filtering. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `autoFocus` | | `boolean` | Focus on element when mounted. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with item | | `modelValue` | | `string` | The controlled value of the filter. Can be binded with v-model. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `string` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `string` | Current input values | [ListboxFilter.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Listbox/ListboxFilter.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Content Contains all the listbox group and items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ListboxContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Listbox/ListboxContent.vue) ### Item The item component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `value*` | | `T` | The value given as data when submitted with a `name`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: SelectEvent` | Event handler called when the selecting item.

It can be prevented by calling `event.preventDefault`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `selected` | `boolean` | Whether the item is currently selected | [ListboxItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Listbox/ListboxItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### ItemIndicator Renders when the item is selected. You can style this element directly, or you can use it as a wrapper to put an icon into, or both. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [ListboxItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Listbox/ListboxItemIndicator.vue) ### Group Used to group multiple items. use in conjunction with `ListboxGroupLabel` to ensure good accessibility via automatic labelling. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ListboxGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Listbox/ListboxGroup.vue) ### GroupLabel Used to render the label of a group. It won't be focusable using arrow keys. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `for` | | `string` | | [ListboxGroupLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Listbox/ListboxGroupLabel.vue) ### Virtualizer Virtual container to achieve list virtualization. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `estimateSize` | | `number \| ((index: number) => number)` | Estimated size (in px) of each item | | `options*` | | `T` | List of items | | `overscan` | | `number` | Number of items rendered outside the visible area | | `textContent` | | `((option: T) => string)` | Text content for each item to achieve type-ahead feature | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `option` | `T` | | | `virtualizer` | `Virtualizer` | | | `virtualItem` | `VirtualItem` | | [ListboxVirtualizer.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Listbox/ListboxVirtualizer.vue) ## Examples ### Binding objects as values Unlike native HTML form controls which only allow you to provide strings as values, Akar supports binding complex objects as well. ```vue ``` ### Selecting multiple values The `Listbox` component allows you to select multiple values. You can enable this by providing an array of values instead of a single value. ```vue ``` ### Custom filtering ```vue ``` ### Virtual List Rendering a long list of item can slow down the app, thus using virtualization would significantly improve the performance. See the [virtualization guide](https://vinicunca.dev/akar/guides/virtualization.md) for more general info on virtualization. ```vue ``` ## Accessibility Adheres to the [Listbox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/). ### Keyboard Interactions | Key | Description | | --- | --- | | Enter | When highlight on `ListboxItem`, selects the focused item. | | ArrowDown | When focus is on `ListboxItem`, moves focus to the next item. | | ArrowUp | When focus is on `ListboxItem`, moves focus to the previous item. | | Home | Moves focus and highlight to the first item. | | End | Moves focus and highlight to the last item. | | Ctrl/Cmd + A | Select all the items. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/listbox) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Listbox) - [npm](https://www.npmjs.com/package/akar) # Menubar > A visually persistent menu common in desktop applications that provides quick ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Menubar) { /* reset */ button { all: unset; } .MenubarRoot { display: flex; background-color: white; padding: 3px; border-radius: 6px; box-shadow: 0 2px 10px var(--black-a7); } .MenubarTrigger { padding: 8px 12px; outline: none; user-select: none; font-weight: 500; line-height: 1; border-radius: 4px; color: var(--grass-11); font-size: 13px; display: flex; align-items: center; justify-content: space-between; gap: 2px; } .MenubarTrigger[data-highlighted], .MenubarTrigger[data-state='open'] { background-color: var(--grass-4); } .MenubarContent, .MenubarSubContent { min-width: 220px; background-color: white; border-radius: 6px; padding: 5px; box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2); animation-duration: 400ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); will-change: transform, opacity; } .MenubarItem, .MenubarSubTrigger, .MenubarCheckboxItem, .MenubarRadioItem { all: unset; font-size: 13px; line-height: 1; color: var(--grass-11); border-radius: 4px; display: flex; align-items: center; height: 25px; padding: 0 10px; position: relative; user-select: none; } .MenubarItem.inset, .MenubarSubTrigger.inset, .MenubarCheckboxItem.inset, .MenubarRadioItem.inset { padding-left: 20px; } .MenubarItem[data-state='open'], .MenubarSubTrigger[data-state='open'] { background-color: var(--grass-4); color: var(--grass-11); } .MenubarItem[data-highlighted], .MenubarSubTrigger[data-highlighted], .MenubarCheckboxItem[data-highlighted], .MenubarRadioItem[data-highlighted] { background-image: linear-gradient(135deg, var(--grass-9) 0%, var(--grass-10) 100%); color: var(--grass-1); } .MenubarItem[data-disabled], .MenubarSubTrigger[data-disabled], .MenubarCheckboxItem[data-disabled], .MenubarRadioItem[data-disabled] { color: var(--mauve-8); pointer-events: none; } .MenubarItemIndicator { position: absolute; left: 0; width: 20px; display: inline-flex; align-items: center; justify-content: center; } .MenubarSeparator { height: 1px; background-color: var(--grass-6); margin: 5px; } .RightSlot { margin-left: auto; padding-left: 20px; color: var(--mauve-9); } [data-highlighted] > .RightSlot { color: white; } [data-disabled] > .RightSlot { color: var(--mauve-8); } } ``` ## Features - Can be controlled or uncontrolled. - Supports submenus with configurable reading direction. - Supports items, labels, groups of items. - Supports checkable items (single or multiple). - Customize side, alignment, offsets, collision handling. - Optionally render a pointing arrow. - Focus is fully managed. - Full keyboard navigation. - Typeahead support. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a menubar **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defaultValue` | | `string` | The value of the menu that should be open when initially rendered. Use when you do not need to control the value state. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. | | `modelValue` | | `string` | The controlled value of the menu to open. Can be used as `v-model`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `value: boolean` | Event handler called when the value changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `string` | Current input values | [MenubarRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarRoot.vue) ### Menu A top level menu item, contains a trigger with content combination. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `value` | | `string` | A unique value that associates the item with an active value when the navigation menu is controlled.

This prop is managed automatically when uncontrolled. | [MenubarMenu.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarMenu.vue) ### Trigger The button that toggles the content. By default, the `MenubarContent` will position itself against the trigger. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with item | [MenubarTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### Portal When used, portals the content part into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [MenubarPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarPortal.vue) ### Content The component that pops out when a menu is open. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"start"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.
May change when collisions occur. | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.
Will be reversed when collisions occur and avoidCollisions
is enabled. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [MenubarContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | CSS variable | Description | | --- | --- | | `--akar-menubar-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets | | `--akar-menubar-content-available-width` | The remaining width between the trigger and the boundary edge | | `--akar-menubar-content-available-height` | The remaining height between the trigger and the boundary edge | | `--akar-menubar-trigger-width` | The width of the trigger | | `--akar-menubar-trigger-height` | The height of the trigger | ### Arrow An optional arrow element to render alongside a menubar menu. This can be used to help visually link the trigger with the `MenubarContent`. Must be rendered inside `MenubarContent`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` | | `width` | `10` | `number` | The width of the arrow in pixels. | [MenubarArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarArrow.vue) ### Item The component that contains the menubar items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).

Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. | [MenubarItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarItem.vue) | Data attribute | Value | | --- | --- | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### Group Used to group multiple `MenubarItem`s. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [MenubarGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarGroup.vue) ### Label Used to render a label. It won't be focusable using arrow keys. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [MenubarLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarLabel.vue) ### CheckboxItem An item that can be controlled and rendered like a checkbox. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `modelValue` | | `false \| true \| "indeterminate"` | The controlled checked state of the item. Can be used as `v-model`. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).

Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. | | `update:modelValue` | `payload: boolean` | Event handler called when the checked state changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `checked` | `false \| true \| "indeterminate"` | Current checked state | | `modelValue` | `CheckedState` | Current modelValue state | [MenubarCheckboxItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarCheckboxItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### RadioGroup Used to group multiple `MenubarRadioItem`s. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `modelValue` | | `AcceptableValue` | The value of the selected item in the group. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: AcceptableValue` | Event handler called when the value changes. | [MenubarRadioGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarRadioGroup.vue) ### RadioItem An item that can be controlled and rendered like a radio. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | | `value*` | | `AcceptableValue` | The unique value of the item. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).

Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `checked` | `boolean` | Current checked state | [MenubarRadioItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarRadioItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### ItemIndicator Renders when the parent `MenubarCheckboxItem` or `MenubarRadioItem` is checked. You can style this element directly, or you can use it as a wrapper to put an icon into, or both. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [MenubarItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarItemIndicator.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | ### Separator Used to visually separate items in a menubar menu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [MenubarSeparator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarSeparator.vue) ### Sub Contains all the parts of a submenu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defaultOpen` | | `boolean` | The open state of the submenu when it is initially rendered. Use when you do not need to control its open state. | | `open` | | `boolean` | The controlled open state of the menu. Can be used as `v-model:open`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `payload: boolean` | Event handler called when the open state of the submenu changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | [MenubarSub.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarSub.vue) ### SubTrigger An item that opens a submenu. Must be rendered inside `MenubarSub`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `graceDuration` | `300` | `number` | Time in milliseconds to keep a submenu open while the pointer moves from
its trigger to the submenu. | | `textValue` | | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.

Use this when the content is complex, or you have non-textual content inside. | [MenubarSubTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarSubTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### SubContent The component that pops out when a submenu is open. Must be rendered inside `MenubarSub`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `entryFocus` | `event: Event` | | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [MenubarSubContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar/MenubarSubContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | `[data-orientation]` | "vertical" \\| "horizontal" | | CSS variable | Description | | --- | --- | | `--akar-menubar-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets | | `--akar-menubar-content-available-width` | The remaining width between the trigger and the boundary edge | | `--akar-menubar-content-available-height` | The remaining height between the trigger and the boundary edge | | `--akar-menubar-trigger-width` | The width of the trigger | | `--akar-menubar-trigger-height` | The height of the trigger | ## Examples ### With submenus You can create submenus by using `MenubarSub` in combination with its parts. ```vue ``` ### With disabled items You can add special styles to disabled items via the `data-disabled` attribute. ```vue ``` ```css /* styles.css */ .MenubarItem[data-disabled] { color: gainsboro; } ``` ### With separators Use the `Separator` part to add a separator between items. ```vue ``` ### With labels Use the `Label` part to help label a section. ```vue ``` ### With checkbox items Use the `CheckboxItem` part to add an item that can be checked. ```vue ``` ### With radio items Use the `RadioGroup` and `RadioItem` parts to add an item that can be checked amongst others. ```vue ``` ### With complex items You can add extra decorative elements in the `Item` parts, such as images. ```vue ``` ### Constrain the content/sub-content size You may want to constrain the width of the content (or sub-content) so that it matches the trigger (or sub-trigger) width. You may also want to constrain its height to not exceed the viewport. We expose several CSS custom properties such as `--akar-menubar-trigger-width` and `--akar-menubar-content-available-height` to support this. Use them to constrain the content dimensions. ```vue ``` ```css /* styles.css */ .MenubarContent { width: var(--akar-menubar-trigger-width); max-height: var(--akar-menubar-content-available-height); } ``` ### Origin-aware animations We expose a CSS custom property `--akar-menubar-content-transform-origin`. Use it to animate the content from its computed origin based on `side`, `sideOffset`, `align`, `alignOffset` and any collisions. ```vue ``` ```css /* styles.css */ .MenubarContent { transform-origin: var(--akar-menubar-content-transform-origin); animation: scaleIn 0.5s ease-out; } @keyframes scaleIn { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } } ``` ### Collision-aware animations We expose `data-side` and `data-align` attributes. Their values will change at runtime to reflect collisions. Use them to create collision and direction-aware animations. ```vue ``` ```css /* styles.css */ .MenubarContent { animation-duration: 0.6s; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); } .MenubarContent[data-side="top"] { animation-name: slideUp; } .MenubarContent[data-side="bottom"] { animation-name: slideDown; } @keyframes slideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } ``` ## Accessibility Adheres to the [Menu Button WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menubutton) and uses [roving tabindex](https://www.w3.org/WAI/ARIA/apg/patterns/kbd_roving_tabindex) to manage focus movement among menu items. ### Keyboard Interactions | Key | Description | | --- | --- | ```text When focus is on an item, activates the focused item. `, }, { keys: ['Enter'], description: ` When focus is on MenubarTrigger, opens the associated menu.
When focus is on an item, activates the focused item. `, }, { keys: ['ArrowDown'], description: ` When focus is on MenubarTrigger, opens the associated menu.
When focus is on an item, moves focus to the next item. `, }, { keys: ['ArrowUp'], description: `When focus is on an item, moves focus to the previous item.`, }, { keys: ['ArrowRight', 'ArrowLeft'], description: ` When focus is on a MenubarTrigger, moves focus to the next or previous item.
When focus is on a MenubarSubTrigger, opens or closes the submenu depending on reading direction.
When focus is within a MenubarContent, opens the next menu in the menubar `, }, { keys: ['Esc'], description: ` Closes the currently open menu and moves focus to its MenubarTrigger. `, }, ``` ]" /> --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/menu/) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Menubar) - [npm](https://www.npmjs.com/package/akar) # MonthPicker > Presents a calendar view tailored for selecting months. ## Month Picker `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-MonthPicker) { .Icon { width: 1rem; height: 1rem; } .MonthPicker { margin-top: 1.5rem; border-radius: 0.75rem; border: 1px solid #e5e5e5; background-color: #ffffff; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); padding: 1rem; } .MonthPickerHeader { display: flex; justify-content: space-between; align-items: center; } .MonthPickerNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2rem; height: 2rem; color: #000000; background-color: transparent; cursor: pointer; border-radius: 0.375rem; } .MonthPickerNavButton:hover { background-color: #fafaf9; } .MonthPickerNavButton:focus { box-shadow: 0 0 0 2px #000000; } .MonthPickerHeading { font-size: 0.875rem; font-weight: 500; color: #000000; } .MonthPickerWrapper { padding-top: 1rem; } .MonthPickerGrid { width: 100%; user-select: none; } .MonthPickerGridWrapper { display: grid; gap: 0.25rem 0; } .MonthPickerGridRow { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.25rem; } .MonthPickerCell { position: relative; text-align: center; } .MonthPickerCellTrigger { position: relative; display: flex; justify-content: center; align-items: center; width: 3rem; height: 3rem; border-radius: 0.5rem; font-size: 0.875rem; font-weight: 400; color: #000000; background-color: transparent; outline: none; cursor: pointer; border: none; } .MonthPickerCellTrigger:hover { background-color: var(--grass-5); } .MonthPickerCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .MonthPickerCellTrigger[data-disabled] { color: rgba(0, 0, 0, 0.3); pointer-events: none; } .MonthPickerCellTrigger[data-selected] { background-color: var(--grass-10); color: #ffffff; font-weight: 500; } .MonthPickerCellTrigger[data-unavailable] { color: rgba(0, 0, 0, 0.3); text-decoration: line-through; pointer-events: none; } .MonthPickerCellTrigger::before { content: ''; position: absolute; top: 0.25rem; width: 0.25rem; height: 0.25rem; border-radius: 9999px; display: none; } .MonthPickerCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } .MonthPickerCellTrigger[data-selected]::before { background-color: #ffffff; } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Highly composable ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a month picker **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `calendarLabel` | | `string` | The accessible label for the month picker | | `defaultPlaceholder` | | `DateValue` | The default placeholder date | | `defaultValue` | | `DateValue` | The default value for the month picker | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the calendar when applicable. If omitted, inherits globally from `ConfigProvider` or assumes LTR. | | `disabled` | `false` | `boolean` | Whether the month picker is disabled | | `initialFocus` | `false` | `boolean` | If true, the month picker will focus the selected month, today, or the first month of the year on mount | | `isMonthDisabled` | | `Matcher` | A function that returns whether or not a month is disabled | | `isMonthUnavailable` | | `Matcher` | A function that returns whether or not a month is unavailable | | `locale` | | `string` | The locale to use for formatting dates | | `maxValue` | | `DateValue` | The maximum date that can be selected | | `minValue` | | `DateValue` | The minimum date that can be selected | | `modelValue` | | `DateValue \| DateValue[] \| null` | The controlled selected month value of the month picker. Can be bound as `v-model`. | | `multiple` | `false` | `boolean` | Whether multiple months can be selected | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the next page of the month picker. Receives the current placeholder as an argument. | | `placeholder` | | `DateValue` | The placeholder date, which is used to determine what year to display when no date is selected | | `preventDeselect` | `false` | `boolean` | Whether or not to prevent the user from deselecting a date without selecting another date first | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the previous page of the month picker. Receives the current placeholder as an argument. | | `readonly` | `false` | `boolean` | Whether the month picker is readonly | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: DateValue \| DateValue[]` | Event handler called whenever the model value changes | | `update:placeholder` | `date: DateValue` | Event handler called whenever the placeholder value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `date` | `DateValue` | The current date of the placeholder | | `grid` | `Grid` | The grid of months | | `locale` | `string` | The month picker locale | | `modelValue` | `DateValue \| DateValue[]` | The current selected value | [MonthPickerRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker/MonthPickerRoot.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Header Contains the navigation buttons and the heading segments. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [MonthPickerHeader.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker/MonthPickerHeader.vue) ### Prev Button Calendar navigation button. It navigates the calendar one year in the past. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the prev page. Overwrites the `prevPage` function set on the `MonthPickerRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [MonthPickerPrev.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker/MonthPickerPrev.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Next Button Calendar navigation button. It navigates the calendar one year in the future. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the next page. Overwrites the `nextPage` function set on the `MonthPickerRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [MonthPickerNext.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker/MonthPickerNext.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Heading Heading for displaying the current year. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `headingValue` | `string` | Current year heading | [MonthPickerHeading.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker/MonthPickerHeading.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Grid Container for wrapping the month picker grid. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"table"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [MonthPickerGrid.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker/MonthPickerGrid.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | ### Grid Body Container for wrapping the grid body. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tbody"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [MonthPickerGridBody.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker/MonthPickerGridBody.vue) ### Grid Row Container for wrapping the grid row. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tr"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [MonthPickerGridRow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker/MonthPickerGridRow.vue) ### Cell Container for wrapping the month picker cells. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"td"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `date*` | | `DateValue` | The date value for the cell | [MonthPickerCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker/MonthPickerCell.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Cell Trigger Interactable container for displaying the cell months. Clicking it selects the month. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `month*` | | `DateValue` | The date value provided to the cell trigger | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `monthValue` | `string` | Current month value (short name) | | `disabled` | `boolean` | Current disable state | | `selected` | `boolean` | Current selected state | | `today` | `boolean` | Current month/year is today state | | `unavailable` | `boolean` | Current unavailable state | [MonthPickerCellTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker/MonthPickerCellTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-selected]` | Present when selected | | `[data-value]` | The ISO string value of the date. | | `[data-disabled]` | Present when disabled | | `[data-unavailable]` | Present when unavailable | | `[data-today]` | Present when the month is the current month | | `[data-focused]` | Present when focused | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the month picker, focuses the first navigation button. | | Space | When the focus is on either `MonthPickerNext` or `MonthPickerPrev`, it navigates the calendar. Otherwise, it selects the month. | | Enter | When the focus is on either `MonthPickerNext` or `MonthPickerPrev`, it navigates the calendar. Otherwise, it selects the month. | | ArrowLeft / ArrowRight / ArrowUp / ArrowDown | When the focus is on `MonthPickerCellTrigger`, it navigates the months, changing the year if necessary. | | PageUp | When the focus is on `MonthPickerCellTrigger`, it navigates to the same month in the previous year. | | PageDown | When the focus is on `MonthPickerCellTrigger`, it navigates to the same month in the next year. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthPicker) - [npm](https://www.npmjs.com/package/akar) # MonthRangePicker > Presents a calendar view tailored for selecting month ranges. ## Month Range Picker `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-MonthRangePicker) { .Icon { width: 1rem; height: 1rem; } .MonthRangePicker { margin-top: 1.5rem; border-radius: 0.75rem; border: 1px solid #e5e5e5; background-color: #ffffff; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); padding: 1rem; } .MonthRangePickerHeader { display: flex; justify-content: space-between; align-items: center; } .MonthRangePickerNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2rem; height: 2rem; color: #000000; background-color: transparent; cursor: pointer; border-radius: 0.375rem; } .MonthRangePickerNavButton:hover { background-color: #fafaf9; } .MonthRangePickerNavButton:focus { box-shadow: 0 0 0 2px #000000; } .MonthRangePickerHeading { font-size: 0.875rem; font-weight: 500; color: #000000; } .MonthRangePickerWrapper { padding-top: 1rem; } .MonthRangePickerGrid { width: 100%; user-select: none; } .MonthRangePickerGridWrapper { display: grid; gap: 0.25rem 0; } .MonthRangePickerGridRow { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.25rem; } .MonthRangePickerCell { position: relative; text-align: center; } .MonthRangePickerCellTrigger { position: relative; display: flex; justify-content: center; align-items: center; width: 3rem; height: 3rem; border-radius: 0.5rem; font-size: 0.875rem; font-weight: 400; color: #000000; background-color: transparent; outline: none; cursor: pointer; border: none; } .MonthRangePickerCellTrigger:hover { background-color: var(--grass-5); } .MonthRangePickerCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .MonthRangePickerCellTrigger[data-disabled] { color: rgba(0, 0, 0, 0.3); pointer-events: none; } .MonthRangePickerCellTrigger[data-selected] { background-color: var(--grass-10); color: #ffffff; font-weight: 500; } .MonthRangePickerCellTrigger[data-highlighted] { background-color: var(--grass-5); } .MonthRangePickerCellTrigger[data-unavailable] { color: rgba(0, 0, 0, 0.3); text-decoration: line-through; pointer-events: none; } .MonthRangePickerCellTrigger::before { content: ''; position: absolute; top: 0.25rem; width: 0.25rem; height: 0.25rem; border-radius: 9999px; display: none; } .MonthRangePickerCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } .MonthRangePickerCellTrigger[data-selected]::before { background-color: #ffffff; } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Highly composable ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a month range picker **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `allowNonContiguousRanges` | `false` | `boolean` | When combined with `isMonthUnavailable`, determines whether non-contiguous ranges may be selected. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `calendarLabel` | | `string` | The accessible label for the calendar | | `defaultPlaceholder` | | `DateValue` | The default placeholder date | | `defaultValue` | `{ start: undefined, end: undefined }` | `DateRange` | The default value for the calendar | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the calendar when applicable. | | `disabled` | `false` | `boolean` | Whether or not the calendar is disabled | | `fixedDate` | | `"start" \| "end"` | Which part of the range should be fixed | | `initialFocus` | `false` | `boolean` | If true, the calendar will focus the selected month on mount | | `isMonthDisabled` | | `Matcher` | A function that returns whether or not a month is disabled | | `isMonthUnavailable` | | `Matcher` | A function that returns whether or not a month is unavailable | | `locale` | | `string` | The locale to use for formatting dates | | `maximumMonths` | | `number` | The maximum number of months that can be selected in a range | | `maxValue` | | `DateValue` | The maximum date that can be selected | | `minValue` | | `DateValue` | The minimum date that can be selected | | `modelValue` | | `DateRange \| null` | The controlled selected month range of the month range picker. Can be bound as `v-model`. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the next page of the calendar. | | `placeholder` | | `DateValue` | The placeholder date, which is used to determine what year to display when no date is selected. | | `preventDeselect` | `false` | `boolean` | Whether or not to prevent the user from deselecting a date without selecting another date first | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the previous page of the calendar. | | `readonly` | `false` | `boolean` | Whether or not the calendar is readonly | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: DateRange` | Event handler called whenever the model value changes | | `update:placeholder` | `date: DateValue` | Event handler called whenever the placeholder value changes | | `update:startValue` | `date: DateValue` | Event handler called whenever the start value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `date` | `DateValue` | The current date of the placeholder | | `grid` | `Grid` | The grid of months | | `locale` | `string` | The calendar locale | | `modelValue` | `DateRange` | The current date range | [MonthRangePickerRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerRoot.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Header Contains the navigation buttons and the heading segments. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [MonthRangePickerHeader.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerHeader.vue) ### Prev Button Calendar navigation button. It navigates the calendar one year in the past. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the prev page. Overwrites the `prevPage` function set on the Root. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [MonthRangePickerPrev.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerPrev.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Next Button Calendar navigation button. It navigates the calendar one year in the future. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the next page. Overwrites the `nextPage` function set on the Root. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [MonthRangePickerNext.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerNext.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Heading Heading for displaying the current year. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `headingValue` | `string` | Current year heading | [MonthRangePickerHeading.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerHeading.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Grid Container for wrapping the month range picker grid. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"table"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [MonthRangePickerGrid.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerGrid.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | ### Grid Body Container for wrapping the grid body. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tbody"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [MonthRangePickerGridBody.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerGridBody.vue) ### Grid Row Container for wrapping the grid row. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tr"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [MonthRangePickerGridRow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerGridRow.vue) ### Cell Container for wrapping the month range picker cells. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"td"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `date*` | | `DateValue` | The date value for the cell | [MonthRangePickerCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerCell.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Cell Trigger Interactable container for displaying the cell months. Clicking it selects the month. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `month*` | | `DateValue` | The date value provided to the cell trigger | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `monthValue` | `string` | Current month value (short name) | | `disabled` | `boolean` | Current disable state | | `selected` | `boolean` | Current selected state | | `today` | `boolean` | Current month is today's month state | | `unavailable` | `boolean` | Current unavailable state | | `highlighted` | `boolean` | Current highlighted state | | `highlightedStart` | `boolean` | Current highlighted start state | | `highlightedEnd` | `boolean` | Current highlighted end state | | `selectionStart` | `boolean` | Current selection start state | | `selectionEnd` | `boolean` | Current selection end state | [MonthRangePickerCellTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker/MonthRangePickerCellTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-selected]` | Present when selected | | `[data-value]` | The ISO string value of the date. | | `[data-disabled]` | Present when disabled | | `[data-unavailable]` | Present when unavailable | | `[data-today]` | Present when the month is the current month | | `[data-selection-start]` | Present when the month is the start of the selection. | | `[data-selection-end]` | Present when the month is the end of the selection. | | `[data-highlighted]` | Present when the month is highlighted by the user as they select a range. | | `[data-highlighted-start]` | Present when the month is the start of the range that is highlighted by the user. | | `[data-highlighted-end]` | Present when the month is the end of the range that is highlighted by the user. | | `[data-focused]` | Present when focused | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the month range picker, focuses the first navigation button. | | Space | When the focus is on either `MonthRangePickerNext` or `MonthRangePickerPrev`, it navigates the calendar. Otherwise, it selects the month. | | Enter | When the focus is on either `MonthRangePickerNext` or `MonthRangePickerPrev`, it navigates the calendar. Otherwise, it selects the month. | | ArrowLeft / ArrowRight / ArrowUp / ArrowDown | When the focus is on `MonthRangePickerCellTrigger`, it navigates the months, changing the year if necessary. | | PageUp | When the focus is on `MonthRangePickerCellTrigger`, it navigates to the same month in the previous year. | | PageDown | When the focus is on `MonthRangePickerCellTrigger`, it navigates to the same month in the next year. | | Escape | Cancels the current range selection and restores the previous valid range. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/MonthRangePicker) - [npm](https://www.npmjs.com/package/akar) # Navigation Menu > A collection of links for navigating websites. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/indigo.css'; @import '../_colors/mauve.css'; @import '../_colors/green.css'; @import '../_colors/grass.css'; @scope (.akar-demo-NavigationMenu) { /* reset */ button, p { all: unset; } .NavigationMenuRoot { position: relative; display: flex; justify-content: center; width: 100vw; z-index: 1; } .NavigationMenuList { display: flex; justify-content: center; background-color: white; padding: 4px; border-radius: 6px; list-style: none; box-shadow: 0 2px 10px var(--black-a7); margin: 0; } .NavigationMenuTrigger, .NavigationMenuLink { padding: 8px 12px; outline: none; user-select: none; font-weight: 500; line-height: 1; border-radius: 4px; font-size: 15px; color: var(--grass-11); } .NavigationMenuTrigger:focus, .NavigationMenuLink:focus { box-shadow: 0 0 0 2px var(--grass-7); } .NavigationMenuTrigger:hover, .NavigationMenuLink:hover { background-color: var(--grass-3); } .NavigationMenuTrigger { display: flex; align-items: center; justify-content: space-between; gap: 2px; } .NavigationMenuLink { display: block; text-decoration: none; font-size: 15px; line-height: 1; } .NavigationMenuContent { position: absolute; top: 0; left: 0; width: 100%; animation-duration: 250ms; animation-timing-function: ease; } .NavigationMenuContent[data-motion='from-start'] { animation-name: enterFromLeft; } .NavigationMenuContent[data-motion='from-end'] { animation-name: enterFromRight; } .NavigationMenuContent[data-motion='to-start'] { animation-name: exitToLeft; } .NavigationMenuContent[data-motion='to-end'] { animation-name: exitToRight; } @media only screen and (min-width: 600px) { .NavigationMenuContent { width: auto; } } .NavigationMenuIndicator { display: flex; align-items: flex-end; justify-content: center; height: 10px; top: 100%; overflow: hidden; z-index: 1; transition: width, transform 250ms ease; } .NavigationMenuIndicator[data-state='visible'] { animation: fadeIn 200ms ease; } .NavigationMenuIndicator[data-state='hidden'] { animation: fadeOut 200ms ease; } .NavigationMenuViewport { position: relative; transform-origin: top center; margin-top: 10px; width: 100%; background-color: white; border-radius: 6px; overflow: hidden; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; height: var(--akar-navigation-menu-viewport-height); transition: width, height, 300ms ease; } .NavigationMenuViewport[data-state='open'] { animation: scaleIn 200ms ease; } .NavigationMenuViewport[data-state='closed'] { animation: scaleOut 200ms ease; } @media only screen and (min-width: 600px) { .NavigationMenuViewport { width: var(--akar-navigation-menu-viewport-width); } } .List { display: grid; padding: 22px; margin: 0; column-gap: 10px; list-style: none; } @media only screen and (min-width: 600px) { .List.one { width: 500px; grid-template-columns: 0.75fr 1fr; } .List.two { width: 600px; grid-auto-flow: column; grid-template-rows: repeat(3, 1fr); } } .ListItemLink { display: block; outline: none; text-decoration: none; user-select: none; padding: 12px; border-radius: 6px; font-size: 15px; line-height: 1; } .ListItemLink:focus { box-shadow: 0 0 0 2px var(--grass-7); } .ListItemLink:hover { background-color: var(--mauve-3); } .ListItemHeading { font-weight: 500; line-height: 1.2; margin-bottom: 5px; color: var(--grass-12); } .ListItemText { color: var(--mauve-11); line-height: 1.4; font-weight: initial; } .Callout { display: flex; justify-content: flex-end; flex-direction: column; width: 100%; height: 100%; background: linear-gradient(135deg, var(--green-9) 0%, var(--indigo-9) 100%); border-radius: 6px; padding: 25px; text-decoration: none; outline: none; user-select: none; } .Callout:focus { box-shadow: 0 0 0 2px var(--grass-7); } .CalloutHeading { color: white; font-size: 18px; font-weight: 500; line-height: 1.2; margin-top: 16px; margin-bottom: 7px; } .CalloutText { color: var(--mauve-4); font-size: 14px; line-height: 1.3; } .ViewportPosition { position: absolute; display: flex; justify-content: center; width: 100%; top: 100%; left: 0; perspective: 2000px; } .CaretDown { position: relative; color: var(--grass-10); top: 1px; transition: transform 250ms ease; } [data-state='open'] > .CaretDown { transform: rotate(-180deg); } .Arrow { position: relative; top: 70%; background-color: white; width: 10px; height: 10px; transform: rotate(45deg); border-top-left-radius: 2px; } @keyframes enterFromRight { from { opacity: 0; transform: translateX(200px); } to { opacity: 1; transform: translateX(0); } } @keyframes enterFromLeft { from { opacity: 0; transform: translateX(-200px); } to { opacity: 1; transform: translateX(0); } } @keyframes exitToRight { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(200px); } } @keyframes exitToLeft { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(-200px); } } @keyframes scaleIn { from { opacity: 0; transform: rotateX(-30deg) scale(0.9); } to { opacity: 1; transform: rotateX(0deg) scale(1); } } @keyframes scaleOut { from { opacity: 1; transform: rotateX(0deg) scale(1); } to { opacity: 0; transform: rotateX(-10deg) scale(0.95); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } } ``` ## Features - Can be controlled or uncontrolled. - Flexible layout structure with managed tab focus. - Supports submenus. - Optional active item indicator. - Full keyboard navigation. - Exposes CSS variables for advanced animation. - Supports custom timings. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a navigation menu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"nav"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `string` | The value of the menu item that should be active when initially rendered.

Use when you do not need to control the value state. | | `delayDuration` | `200` | `number` | The duration from when the pointer enters the trigger until the tooltip gets opened. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disableClickTrigger` | `false` | `boolean` | If `true`, menu cannot be open by click on trigger | | `disableHoverTrigger` | `false` | `boolean` | If `true`, menu cannot be open by hover on trigger | | `disablePointerLeaveClose` | `false` | `boolean` | If `true`, menu will not close during pointer leave event | | `modelValue` | | `string` | The controlled value of the menu item to activate. Can be used as `v-model`. | | `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation of the menu. | | `skipDelayDuration` | `300` | `number` | How much time a user has to enter another trigger without incurring a delay again. | | `unmountOnHide` | `true` | `boolean` | When `true`, the element will be unmounted on closed state. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `value: string` | Event handler called when the value changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `string` | Current input values | [NavigationMenuRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NavigationMenu/NavigationMenuRoot.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Sub Signifies a submenu. Use it in place of the root part when nested to create a submenu. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `string` | The value of the menu item that should be active when initially rendered.

Use when you do not need to control the value state. | | `modelValue` | | `string` | The controlled value of the sub menu item to activate. Can be used as `v-model`. | | `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation of the menu. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `value: string` | Event handler called when the value changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `string` | Current input values | [NavigationMenuSub.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NavigationMenu/NavigationMenuSub.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ### List Contains the top level menu items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"ul"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [NavigationMenuList.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NavigationMenu/NavigationMenuList.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Item A top level menu item, contains a link or trigger with content combination. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"li"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `value` | | `string` | A unique value that associates the item with an active value when the navigation menu is controlled.

This prop is managed automatically when uncontrolled. | [NavigationMenuItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NavigationMenu/NavigationMenuItem.vue) ### Trigger The button that toggles the content. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with item | [NavigationMenuTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NavigationMenu/NavigationMenuTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | ### Content Contains the content associated with each trigger. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disableOutsidePointerEvents` | | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside
the `DismissableLayer`. Users will need to click twice on outside elements to
interact with them: once to close the `DismissableLayer`, and again to trigger the element. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | **Events** | Event | Payload | Description | | --- | --- | --- | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [NavigationMenuContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NavigationMenu/NavigationMenuContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-motion]` | "to-start" \\| "to-end" \\| "from-start" \\| "from-end" | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Link A navigational link. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `active` | | `boolean` | Used to identify the link as the currently active page. | | `as` | `"a"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `payload: CustomEvent<{ originalEvent: Event; }>` | Event handler called when the user selects a link (via mouse or keyboard).

Calling `event.preventDefault` in this handler will prevent the navigation menu from closing when selecting that link. | [NavigationMenuLink.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NavigationMenu/NavigationMenuLink.vue) | Data attribute | Value | | --- | --- | | `[data-active]` | Present when active | ### Indicator An optional indicator element that renders below the list, is used to highlight the currently active trigger. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [NavigationMenuIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NavigationMenu/NavigationMenuIndicator.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "visible" \\| "hidden" | | `[data-orientation]` | "vertical" \\| "horizontal" | | CSS variable | Description | | --- | --- | | `--akar-navigation-menu-indicator-size` | The size of the indicator. | | `--akar-navigation-menu-indicator-position` | The position of the indicator | ### Viewport An optional viewport element that is used to render active content outside of the list. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"center"` | `"start" \| "center" \| "end"` | Placement of the viewport for css variables `(--akar-navigation-menu-viewport-left, --akar-navigation-menu-viewport-top)`. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [NavigationMenuViewport.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NavigationMenu/NavigationMenuViewport.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "visible" \\| "hidden" | | `[data-orientation]` | "vertical" \\| "horizontal" | | CSS variable | Description | | --- | --- | | `--akar-navigation-menu-viewport-width` | The width of the viewport when visible/hidden, computed from the active content | | `--akar-navigation-menu-viewport-height` | The height of the viewport when visible/hidden, computed from the active content | ## Examples ### Vertical You can create a vertical menu by using the `orientation` prop. ```vue ``` ### Flexible layouts Use the `Viewport` part when you need extra control over where `Content` is rendered. This can be helpful when your design requires an adjusted DOM structure or if you need flexibility to achieve [advanced animation](https://vinicunca.dev/akar/components/navigation-menu#advanced-animation). Tab focus will be maintained automatically. ```vue ``` ### With indicator You can use the optional `Indicator` part to highlight the currently active `Trigger`, this is useful when you want to provide an animated visual cue such as an arrow or highlight to accompany the `Viewport`. ```vue ``` ```css /* styles.css */ .NavigationMenuIndicator { background-color: grey; position: absolute; transition: width, transform, 250ms ease; } .NavigationMenuIndicator[data-orientation='horizontal'] { left: 0; height: 3px; transform: translateX(var(--akar-navigation-menu-indicator-position)); width: var(--akar-navigation-menu-indicator-size); } ``` ### With submenus Create a submenu by nesting your `NavigationMenu` and using the `Sub` part in place of its `Root`. Submenus work differently to `Root` navigation menus and are similar to [`Tabs`](https://vinicunca.dev/akar/components/tabs) in that one item should always be active, so be sure to assign and set a `defaultValue`. ```vue ``` ### With client side routing If you need to use the `RouterLink` component provided by your routing package then we recommend adding `asChild="true"` to `NavigationMenuLink`, or setting `as="RouterLink"`. This will ensure accessibility and consistent keyboard control is maintained: ```vue ``` ### Advanced animation We expose `--akar-navigation-menu-viewport-[width|height]` and `data-motion['from-start'|'to-start'|'from-end'|'to-end']` attributes to allow you to animate `Viewport` size and `Content` position based on the enter/exit direction. Combining these with `position: absolute;` allows you to create smooth overlapping animation effects when moving between items. ```vue ``` ```css /* styles.css */ .NavigationMenuContent { position: absolute; top: 0; left: 0; animation-duration: 250ms; animation-timing-function: ease; } .NavigationMenuContent[data-motion="from-start"] { animation-name: enterFromLeft; } .NavigationMenuContent[data-motion="from-end"] { animation-name: enterFromRight; } .NavigationMenuContent[data-motion="to-start"] { animation-name: exitToLeft; } .NavigationMenuContent[data-motion="to-end"] { animation-name: exitToRight; } .NavigationMenuViewport { position: relative; width: var(--akar-navigation-menu-viewport-width); height: var(--akar-navigation-menu-viewport-height); transition: width, height, 250ms ease; } @keyframes enterFromRight { from { opacity: 0; transform: translateX(200px); } to { opacity: 1; transform: translateX(0); } } @keyframes enterFromLeft { from { opacity: 0; transform: translateX(-200px); } to { opacity: 1; transform: translateX(0); } } @keyframes exitToRight { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(200px); } } @keyframes exitToLeft { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(-200px); } } ``` ## Accessibility Adheres to the [`navigation` role requirements](https://www.w3.org/TR/wai-aria-1.2/#navigation). ### Differences to menubar `NavigationMenu` should not be confused with `menubar`, although this primitive shares the name `menu` in the colloquial sense to refer to a set of navigation links, it does not use the WAI-ARIA `menu` role. This is because `menu` and `menubars` behave like native operating system menus most commonly found in desktop application windows, as such they feature complex functionality like composite focus management and first-character navigation. These features are often considered [unnecessary for website navigation](https://github.com/w3c/aria-practices/issues/353) and at worst can confuse users who are familiar with established website patterns. See the W3C [Disclosure Navigation Menu](https://w3c.github.io/aria-practices/examples/disclosure/disclosure-navigation.html) example for more information. ### Link usage and aria-current It's important to use `NavigationMenuLink` for all navigational links within a menu, this not only applies to the main list but also within any content rendered via `NavigationMenuContent`. This will ensure consistent keyboard interactions and accessibility while also giving access to the `active` prop for setting `aria-current` and the active styles. See [this example](https://vinicunca.dev/akar/components/navigation-menu#with-client-side-routing) for more information on usage with third party routing components. ### Keyboard Interactions | Key | Description | | --- | --- | ```text Moves focus to the next NavigationMenuTrigger or NavigationMenuLink. `, }, { keys: ['ArrowUp'], description: ` Moves focus to the previous NavigationMenuTrigger or NavigationMenuLink. `, }, { keys: ['ArrowRight', 'ArrowLeft'], description: ` When vertical and focus is on an open NavigationMenuTrigger, moves focus into its NavigationMenuContent.
Moves focus to the next / previous NavigationMenuTrigger or NavigationMenuLink. `, }, { keys: ['Home', 'End'], description: ` Moves focus to the first/last NavigationMenu.Trigger or NavigationMenu.Link. `, }, { keys: ['Esc'], description: ` Closes open NavigationMenu.Content and moves focus to its NavigationMenu.Trigger. `, }, ``` ]" /> --- - [ARIA](https://www.w3.org/TR/wai-aria/#navigation) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NavigationMenu) - [npm](https://www.npmjs.com/package/akar) # Number Field > A number field allows a user to enter a number and increment or decrement the value using stepper buttons. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-NumberField) { /* reset */ button { all: unset; } .CheckboxRoot { background-color: white; width: 25px; height: 25px; border-radius: 4px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 10px var(--black-a7); } .CheckboxRoot:hover { background-color: var(--grass-3); } .CheckboxRoot:focus { box-shadow: 0 0 0 2px black; } .CheckboxIndicator { color: var(--grass-11); } } ``` ## Features - Full keyboard navigation. - Can be controlled or uncontrolled. - Support button hold and wheel event. - Support numbering systems in different locale. - Customizable formatting. ## Installation Install the number package. ```bash [pnpm] pnpm add @internationalized/number ``` ```bash [yarn] yarn add @internationalized/number ``` ```bash [npm] npm install @internationalized/number ``` ```bash [bun] bun add @internationalized/number ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a number field. An `input` will also render when used within a `form` to ensure events propagate correctly. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `number` | | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the Number Field. | | `disableWheelChange` | | `boolean` | When `true`, prevents the value from changing on wheel scroll. | | `focusOnChange` | `true` | `boolean` | When `true`, the input will be focused when the value changes. | | `formatOptions` | | `Intl.NumberFormatOptions` | Formatting options for the value displayed in the number field. This also affects what characters are allowed to be typed by the user. | | `id` | | `string` | Id of the element | | `invertWheelChange` | | `boolean` | When `true`, inverts the direction of the wheel change. | | `locale` | | `string` | The locale to use for formatting and currencies | | `max` | | `number` | The largest value allowed for the input. | | `min` | | `number` | The smallest value allowed for the input. | | `modelValue` | | `number \| null` | | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `readonly` | | `boolean` | When `true`, the Number Field is read-only. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | `1` | `number` | The amount that the input value changes with each increment or decrement "tick". | | `stepSnapping` | `true` | `boolean` | When `false`, prevents the value from snapping to the nearest increment of the step value | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `val: number` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `number` | | | `textValue` | `string` | | | `readonly` | `boolean` | | [NumberFieldRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NumberField/NumberFieldRoot.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Input Input The input component that renders the text value based on value and format options. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [NumberFieldInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NumberField/NumberFieldInput.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Increment The button that increases the value. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | | [NumberFieldIncrement.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NumberField/NumberFieldIncrement.vue) | Data attribute | Value | | --- | --- | | `[data-pressed]` | Present when pressed | | `[data-disabled]` | Present when disabled | ### Decrement The button that decreases the value. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | | [NumberFieldDecrement.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NumberField/NumberFieldDecrement.vue) | Data attribute | Value | | --- | --- | | `[data-pressed]` | Present when pressed | | `[data-disabled]` | Present when disabled | ## Example ### Decimal All options supported by `Intl.NumberFormat` are supported, including configuration of minimum and maximum fraction digits, sign display, grouping separators, etc. ```vue ``` ### Percentage You can set `formatOptions.style` to `percent` to treat the value as a percentage. You need to set the step to 0.01 manually to allow an appropriate step size in this mode. ```vue ``` ### Currency You can set `formatOptions.style` to `currency` to treat the value as a currency value. The currency option must also be passed to set the currency code (e.g., USD). If you need to allow the user to change the currency, you should include a separate dropdown next to the number field. The number field itself will not determine the currency from the user input. ```vue ``` ## Accessibility Adheres to the [Spinbutton WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton). ### Keyboard Interactions | Key | Description | | --- | --- | | Arrow Up | Increase the value | | Arrow Down | Decrease the value | | Page Up | Increase the value by scale of 10 | | Page Down | Decrease the value by scale of 10 | | Home | Set value to minimum (if `min` is provided) | | End | Set value to maximum (if `max` is provided) | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/NumberField) - [npm](https://www.npmjs.com/package/akar) # Pagination > Displays data in paged format and provides navigation between pages. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Pagination) { /* reset */ button { all: unset; } .Button{ text-align: center; font-size: 15px; line-height: 1; align-items: center; justify-content: center; height: 2.25rem; width: 2.25rem; border-radius: 0.25rem; transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1); cursor: pointer; } .Button:disabled { opacity: .5 } .Button:hover{ background-color: rgb(255 255 255 / 0.1) } .Button[data-selected]{ background-color: rgb(255 255 255); color: var(--black-a11) } .PaginationEllipsis{ display: flex; height: 2.25rem; width: 2.25rem; align-items: center; justify-content: center } .PaginationList{ display: flex; align-items: center; gap: 0.25rem; color: rgb(255 255 255) } } ``` ## Features - Enable quick access to first, or last page - Enable to show edges constantly, or not ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ### Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all of the paginations parts. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"nav"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultPage` | `1` | `number` | The value of the page that should be active when initially rendered.

Use when you do not need to control the value state. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with item | | `itemsPerPage*` | | `number` | Number of items per page | | `page` | | `number` | The controlled value of the current page. Can be binded as `v-model:page`. | | `showEdges` | `false` | `boolean` | When `true`, always show first page, last page, and ellipsis | | `siblingCount` | `2` | `number` | Number of sibling should be shown around the current page | | `total` | `0` | `number` | Number of items in your list | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:page` | `value: number` | Event handler called when the page value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `page` | `number` | Current page state | | `pageCount` | `number` | Number of pages | [PaginationRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Pagination/PaginationRoot.vue) ### List Used to show the list of pages. It also makes pagination accessible to assistive technologies. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `items` | `{ type: "ellipsis"; } \| { type: "page"; value: number; }` | Pages item | [PaginationList.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Pagination/PaginationList.vue) ### Item Used to render the button that changes the current page. Reka's docs called this part `PaginationItem`; in Akar v2.0.20 the export is `PaginationListItem`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `value*` | | `number` | Value for the page | [PaginationListItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Pagination/PaginationListItem.vue) | Data attribute | Value | | --- | --- | | `[data-selected]` | "true" \\| "" | | `[data-type]` | "page" | ### Ellipsis Placeholder element when the list is long, and only a small amount of `siblingCount` was set and `showEdges` was set to `true`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [PaginationEllipsis.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Pagination/PaginationEllipsis.vue) | Data attribute | Value | | --- | --- | | `[data-type]` | "ellipsis" | ### First Triggers that set the page value to 1 **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [PaginationFirst.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Pagination/PaginationFirst.vue) ### Prev Triggers that set the page value to the previous page **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [PaginationPrev.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Pagination/PaginationPrev.vue) ### Next Triggers that set the page value to the next page **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [PaginationNext.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Pagination/PaginationNext.vue) ### Last Triggers that set the page value to the last page **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [PaginationLast.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Pagination/PaginationLast.vue) ## Examples ### With ellipsis You can add `PaginationEllipsis` as a visual cue for more previous and after items. ```vue ``` ### With first/last button You can add `PaginationFirst` to allow user to navigate to first page, or `PaginationLast` to navigate to last page. ```vue ``` ### Control page programmatically You can control the current page by passing it a reactive value. ```vue ``` ## Keyboard Interactions | Key | Description | | --- | --- | | Tab | Moves focus to the next focusable element. | | Space | When focus is on a any trigger, trigger selected page or arrow navigation | | Enter | When focus is on a any trigger, trigger selected page or arrow navigation | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Pagination) - [npm](https://www.npmjs.com/package/akar) # Pin Input > A sequence of one-character alphanumeric inputs. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-PinInput) { /* reset */ input { all: unset; } .Text { color: white } .PinInputInput{ text-align: center; font-size: 15px; line-height: 1; align-items: center; justify-content: center; height: 2.25rem; width: 2.25rem; border-radius: 0.25rem; transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1); cursor: pointer; } .PinInputInput:disabled { opacity: .5 } .PinInputRoot{ display: flex; align-items: center; gap: 0.25rem; margin-top: 0.25rem; color: rgb(255 255 255) } } ``` ## Features - Full keyboard navigation. - Can be controlled or uncontrolled. - Supports pasting from clipboard - Emit event when inputs were filled. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a pin. An `input` will also render when used within a `form` to ensure events propagate correctly. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `PinInputValue` | The default value of the pin inputs when it is initially rendered. Use when you do not need to control its checked state. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the pin input | | `id` | | `string` | Id of the element | | `mask` | | `boolean` | When `true`, pin inputs will be treated as password. | | `modelValue` | | `PinInputValue \| null` | The controlled checked state of the pin input. Can be binded as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `otp` | | `boolean` | When `true`, mobile devices will autodetect the OTP from messages or clipboard, and enable the autocomplete field. | | `placeholder` | `""` | `string` | The placeholder character to use for empty pin-inputs. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `type` | `"text" as any` | `Type` | Input type for the inputs. | **Events** | Event | Payload | Description | | --- | --- | --- | | `complete` | `value: PinInputValue` | | | `update:modelValue` | `value: PinInputValue` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `PinInputValue` | Current input values | [PinInputRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/PinInput/PinInputRoot.vue) | Data attribute | Value | | --- | --- | | `[data-complete]` | Present when completed | | `[data-disabled]` | Present when disabled | ### Input Input field for Pin Input. You can add as many input as you like. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the pin input | | `index*` | | `number` | Position of the value this input binds to. | [PinInputInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/PinInput/PinInputInput.vue) | Data attribute | Value | | --- | --- | | `[data-complete]` | Present when completed | | `[data-disabled]` | Present when disabled | ## Examples ### OTP mode You can set the pin input to `otp` mode by setting otp to `true`. ```vue ``` ### Numeric mode You can set the pin input to only accept `number` type by setting type to `number`. ```vue ``` ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | ArrowLeft | Focus on previous input. | | ArrowRight | Focus on next input. | | Home | Focus on the first input. | | End | Focus on the last input. | | Backspace | Deletes the value of the current input. If the input is empty, moves to the previous input and deletes that value as well. | | Delete | Deletes the value of the current input. | | Ctrl + V | Pastes the contents of the clipboard into the pin input. If the number of characters in the clipboard equals exceeds the number of inputs, the contents are pasted from the first input. Otherwise, the contents are pasted from the current input onwards. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/PinInput) - [npm](https://www.npmjs.com/package/akar) # Popover > Displays rich content in a portal, triggered by a button. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Popover) { /* reset */ button, fieldset, input { all: unset; } .PopoverContent { border-radius: 4px; padding: 20px; width: 260px; background-color: white; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; animation-duration: 400ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); will-change: transform, opacity; } .PopoverContent:focus { box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px, 0 0 0 2px var(--grass-7); } .PopoverContent[data-state='open'][data-side='top'] { animation-name: slideDownAndFade; } .PopoverContent[data-state='open'][data-side='right'] { animation-name: slideLeftAndFade; } .PopoverContent[data-state='open'][data-side='bottom'] { animation-name: slideUpAndFade; } .PopoverContent[data-state='open'][data-side='left'] { animation-name: slideRightAndFade; } .PopoverArrow { fill: white; } .PopoverClose { font-family: inherit; border-radius: 100%; height: 25px; width: 25px; display: inline-flex; align-items: center; justify-content: center; color: var(--grass-11); position: absolute; top: 5px; right: 5px; } .PopoverClose:hover { background-color: var(--grass-4); } .PopoverClose:focus { box-shadow: 0 0 0 2px var(--grass-7); } .IconButton { font-family: inherit; border-radius: 100%; height: 35px; width: 35px; display: inline-flex; align-items: center; justify-content: center; color: var(--grass-11); background-color: white; box-shadow: 0 2px 10px var(--black-a7); } .IconButton:hover { background-color: var(--grass-3); } .IconButton:focus { box-shadow: 0 0 0 2px black; } .Fieldset { display: flex; gap: 20px; align-items: center; } .Label { font-size: 13px; color: var(--grass-11); width: 75px; } .Input { width: 100%; display: inline-flex; align-items: center; justify-content: center; flex: 1; border-radius: 4px; padding: 0 10px; font-size: 13px; line-height: 1; color: var(--grass-11); box-shadow: 0 0 0 1px var(--grass-7); height: 25px; } .Input:focus { box-shadow: 0 0 0 2px var(--grass-8); } .Text { margin: 0; color: var(--mauve-12); font-size: 15px; line-height: 19px; font-weight: 500; } @keyframes slideUpAndFade { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideRightAndFade { from { opacity: 0; transform: translateX(-2px); } to { opacity: 1; transform: translateX(0); } } @keyframes slideDownAndFade { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideLeftAndFade { from { opacity: 0; transform: translateX(2px); } to { opacity: 1; transform: translateX(0); } } } ``` ## Features - Can be controlled or uncontrolled. - Customize side, alignment, offsets, collision handling. - Optionally render a pointing arrow. - Focus is fully managed and customizable. - Supports modal and non-modal modes. - Dismissing and layering behavior is highly customizable. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a popover. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defaultOpen` | `false` | `boolean` | The open state of the popover when it is initially rendered. Use when you do not need to control its open state. | | `modal` | `false` | `boolean` | The modality of the popover. When set to true, interaction with outside elements will be disabled and only popover content will be visible to screen readers. | | `open` | | `boolean` | The controlled open state of the popover. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `value: boolean` | Event handler called when the open state of the popover changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | | `close` | `(): void` | Close the popover | [PopoverRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Popover/PopoverRoot.vue) ### Trigger The button that toggles the popover. By default, the `PopoverContent` will position itself against the trigger. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [PopoverTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Popover/PopoverTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | ### Anchor An optional element to position the `PopoverContent` against. If this part is not used, the content will position alongside the `PopoverTrigger`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `reference` | | `ReferenceElement` | The reference (or anchor) element that is being referred to for positioning.

If not provided will use the current component as anchor. | [PopoverAnchor.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Popover/PopoverAnchor.vue) ### Portal When used, portals the content part into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [PopoverPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Popover/PopoverPortal.vue) ### Content The component that pops out when the popover is open. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.
May change when collisions occur. | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the popper content when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disableOutsidePointerEvents` | | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside
the `DismissableLayer`. Users will need to click twice on outside elements to
interact with them: once to close the `DismissableLayer`, and again to trigger the element. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.
Will be reversed when collisions occur and avoidCollisions
is enabled. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.
Can be prevented. | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.
Can be prevented. | | `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.
Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
Can be prevented. | | `openAutoFocus` | `event: Event` | Event handler called when auto-focusing on open.
Can be prevented. | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [PopoverContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Popover/PopoverContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | CSS variable | Description | | --- | --- | | `--akar-popover-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets | | `--akar-popover-content-available-width` | The remaining width between the trigger and the boundary edge | | `--akar-popover-content-available-height` | The remaining height between the trigger and the boundary edge | | `--akar-popover-trigger-width` | The width of the trigger | | `--akar-popover-trigger-height` | The height of the trigger | ### Arrow An optional arrow element to render alongside the popover. This can be used to help visually link the anchor with the `PopoverContent`. Must be rendered inside `PopoverContent`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` | | `width` | `10` | `number` | The width of the arrow in pixels. | [PopoverArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Popover/PopoverArrow.vue) ### Close The button that closes an open popover. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [PopoverClose.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Popover/PopoverClose.vue) ## Examples ### Constrain the content size You may want to constrain the width of the content so that it matches the trigger width. You may also want to constrain its height to not exceed the viewport. We expose several CSS custom properties such as `--akar-popover-trigger-width` and `--akar-popover-content-available-height` to support this. Use them to constrain the content dimensions. ```vue ``` ```css /* styles.css */ .PopoverContent { width: var(--akar-popover-trigger-width); max-height: var(--akar-popover-content-available-height); } ``` ### Origin-aware animations We expose a CSS custom property `--akar-popover-content-transform-origin`. Use it to animate the content from its computed origin based on `side`, `sideOffset`, `align`, `alignOffset` and any collisions. ```vue ``` ```css /* styles.css */ .PopoverContent { transform-origin: var(--akar-popover-content-transform-origin); animation: scaleIn 0.5s ease-out; } @keyframes scaleIn { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } } ``` ### Collision-aware animations We expose `data-side` and `data-align` attributes. Their values will change at runtime to reflect collisions. Use them to create collision and direction-aware animations. ```vue ``` ```css /* styles.css */ .PopoverContent { animation-duration: 0.6s; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); } .PopoverContent[data-side="top"] { animation-name: slideUp; } .PopoverContent[data-side="bottom"] { animation-name: slideDown; } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } ``` ### With custom anchor You can anchor the content to another element if you do not want to use the trigger as the anchor. ```vue ``` ```css /* styles.css */ .Row { background-color: gainsboro; padding: 20px; } ``` ### Close using slot props Alternatively, you can use the `close` method provided by the `PopoverRoot` slot props to programmatically close the popover. ```vue ``` ## Accessibility Adheres to the [Dialog WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/). ### Keyboard Interactions | Key | Description | | --- | --- | | Space | Opens/closes the popover. | | Enter | Opens/closes the popover. | | Tab | Moves focus to the next focusable element | | Shift + Tab | Moves focus to the previous focusable element | | Esc | Closes the popover and moves focus to `PopoverTrigger`. | ## Custom APIs Create your own API by abstracting the primitive parts into your own component. #### Abstract the arrow and set default configuration This example abstracts the `PopoverArrow` part and sets a default `sideOffset` configuration. #### Usage ```vue ``` #### Implementation ```ts export { PopoverRoot as Popover, PopoverTrigger } from 'akar'; // your-popover.ts export { default as PopoverContent } from 'PopoverContent.vue'; ``` ```vue ``` --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Popover) - [npm](https://www.npmjs.com/package/akar) # Progress > Displays an indicator showing the completion progress of a task, typically displayed as a progress bar. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @scope (.akar-demo-Progress) { .ProgressRoot { position: relative; overflow: hidden; background: var(--black-a9); border-radius: 99999px; width: 300px; height: 25px; /* Fix overflow clipping in Safari */ /* https://gist.github.com/domske/b66047671c780a238b51c51ffde8d3a0 */ transform: translateZ(0); } .ProgressIndicator { background-color: white; width: 100%; height: 100%; transition: transform 660ms cubic-bezier(0.65, 0, 0.35, 1); } } ``` ## Features - Provides context for assistive technology to read the progress of a task. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ### Anatomy Import all parts and piece them together. ```vue ``` ## Accessibility Adheres to the [`progressbar` role requirements](https://www.w3.org/WAI/ARIA/apg/patterns/meter). ## API Reference ### Root Contains all of the progress parts. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `getValueLabel` | `isNumber(value) ? `${Math.round((value / max) * DEFAULT_MAX)}%` : undefined` | `((value: number \| null, max: number) => string)` | A function to get the accessible label text in a human-readable format.

If not provided, the value label will be read as the numeric value as a percentage of the max value. | | `getValueText` | | `((value: number \| null, max: number) => string)` | A function to get the accessible value text representing the current value in a human-readable format. | | `max` | `DEFAULT_MAX` | `number` | The maximum progress value. | | `modelValue` | | `number \| null` | The progress value. Can be bind as `v-model`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:max` | `value: number` | Event handler called when the max value changes | | `update:modelValue` | `value: string[]` | Event handler called when the progress value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `number \| null` | Current input values | [ProgressRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Progress/ProgressRoot.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "complete" \\| "indeterminate" \\| "loading" | | `[data-value]` | The current value | | `[data-max]` | The max value | ### Indicator Used to show the progress visually. It also makes progress accessible to assistive technologies. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ProgressIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Progress/ProgressIndicator.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "complete" \\| "indeterminate" \\| "loading" | | `[data-value]` | The current value | | `[data-max]` | The max value | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/meter) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Progress) - [npm](https://www.npmjs.com/package/akar) # Radio Group > A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time. ## RadioGroup ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-RadioGroup) { /* reset */ button { all: unset; } .RadioGroupRoot { display: flex; flex-direction: column; gap: 10px; } .RadioGroupItem { background-color: white; width: 25px; height: 25px; border-radius: 100%; box-shadow: 0 2px 10px var(--black-a7); } .RadioGroupItem:hover { background-color: var(--grass-3); } .RadioGroupItem:focus { box-shadow: 0 0 0 2px black; } .RadioGroupIndicator { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; position: relative; } .RadioGroupIndicator::after { content: ''; display: block; width: 11px; height: 11px; border-radius: 50%; background-color: var(--grass-11); } .Label { color: white; font-size: 15px; line-height: 1; padding-left: 15px; } } ``` ## Features - Full keyboard navigation. - Supports horizontal/vertical orientation. - Can be controlled or uncontrolled. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a radio group. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `AcceptableValue` | The value of the radio item that should be checked when initially rendered.

Use when you do not need to control the state of the radio items. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with radio items. | | `loop` | `true` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. | | `modelValue` | | `AcceptableValue` | The controlled value of the radio item to check. Can be binded as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `orientation` | | `"vertical" \| "horizontal"` | The orientation of the component. | | `required` | `false` | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: AcceptableValue` | Event handler called when the radio group value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `null \| string \| number \| bigint \| Record` | Current input values | [RadioGroupRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RadioGroup/RadioGroupRoot.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Item An item in the group that can be checked. An `input` will also render when used within a `form` to ensure events propagate correctly. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the radio item. | | `id` | | `string` | | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `value` | | `AcceptableValue` | The value given as data when submitted with a `name`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: SelectEvent` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `checked` | `boolean` | Current checked state | | `required` | `boolean` | Required state | | `disabled` | `boolean` | Disabled state | [RadioGroupItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RadioGroup/RadioGroupItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-disabled]` | Present when disabled | ### Indicator Renders when the radio item is in a checked state. You can style this element directly, or you can use it as a wrapper to put an icon into, or both. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [RadioGroupIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RadioGroup/RadioGroupIndicator.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-disabled]` | Present when disabled | ## Accessibility Adheres to the [Radio Group WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/radiobutton) and uses [roving tabindex](https://www.w3.org/TR/wai-aria-practices-1.2/examples/radio/radio.html) to manage focus movement among radio items. ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | Moves focus to either the checked radio item or the first radio item in the group. | | Space | When focus is on an unchecked radio item, checks it. | | ArrowDown | Moves focus and checks the next radio item in the group. | | ArrowRight | Moves focus and checks the next radio item in the group. | | ArrowUp | Moves focus to the previous radio item in the group. | | ArrowLeft | Moves focus to the previous radio item in the group. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/radiobutton) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RadioGroup) - [npm](https://www.npmjs.com/package/akar) # RangeCalendar > Presents a calendar view tailored for selecting date ranges. ## Range Calendar `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-RangeCalendar) { .Calendar { margin-top: 1.5rem; border-width: 1px; border-color: #000000; background-color: #ffffff; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); padding: 22px; } .CalendarHeader { display: flex; justify-content: space-between; align-items: center; } .CalendarNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2.5rem; height: 2.5rem; color: #000000; background-color: transparent; cursor: pointer; } .CalendarNavButton:hover { color: #ffffff; background-color: #000000; } .CalendarHeading { font-weight: 500; color: #000000; color: 15px; } .CalendarWrapper { display: flex; padding-top: 1rem; margin-top: 1rem; flex-direction: column; } @media (min-width: 640px) { .CalendarWrapper { margin-left: 1rem; margin-top: 0; flex-direction: row; } } .CalendarGrid { margin-top: 0.25rem; width: 100%; user-select: none; border-collapse: collapse; } .CalendarGridRow { display: grid; margin-bottom: 0.25rem; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; } .CalendarGridRow[data-reka-calendar-month-view] { grid-template-columns: repeat(7, minmax(0, 1fr)); } .CalendarHeadCell { border-radius: 0.375rem; font-size: 0.75rem; line-height: 1rem; color: #000000; font-weight: 400; } .CalendarCell { position: relative; font-size: 0.875rem; line-height: 1.25rem; text-align: center; padding: 0 !important; } .CalendarCellTrigger { display: flex; position: relative; padding: 0.5rem; justify-content: center; align-items: center; border-width: 1px; border-color: transparent; outline-style: none; font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; color: #000000; white-space: nowrap; background-color: transparent; } .CalendarCellTrigger:hover { border-color: #000000; } .CalendarCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .CalendarCellTrigger[data-disabled] { cursor: none; color: rgba(0,0,0,0.3); } .CalendarCellTrigger[data-selected] { background-color: #000000; color: #ffffff; font-weight: 500; } .CalendarCellTrigger[data-selected]::before { background-color: #FFFFFF; } .CalendarCellTrigger[data-unavailable] { color: rgba(0,0,0,0.3); text-decoration: line-through; } .CalendarCellTrigger::before { content: ''; position: absolute; top: 5px; left: 0; width: 0.25rem; height: 0.25rem; border-radius: 9999px; background-color: #FFFFFF; } .CalendarCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } .CalendarCellTrigger[data-selected:not(data-selection-start):not(data-selection-end)] { background-color: rgba(0, 0, 0, 0.3); } .CalendarCellTrigger[data-highlighted] { background-color: var(--grass-9); color: var(--grass-1); border-radius:0; } .CalendarCellTrigger[data-selection-start] { background-color: #000000; border-radius: 0; border-top-left-radius: 9px; border-bottom-left-radius: 9px; } .CalendarCellTrigger[data-selection-end] { background-color: #000000; border-radius: 0; border-top-right-radius: 9px; border-bottom-right-radius: 9px; } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Highly composable ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a calendar **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `allowNonContiguousRanges` | `false` | `boolean` | When combined with `isDateUnavailable`, determines whether non-contiguous ranges, i.e. ranges containing unavailable dates, may be selected. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `calendarLabel` | | `string` | The accessible label for the calendar | | `defaultPlaceholder` | | `DateValue` | The default placeholder date | | `defaultValue` | `{ start: undefined, end: undefined }` | `DateRange` | The default value for the calendar | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the calendar when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | Whether or not the calendar is disabled | | `disableDaysOutsideCurrentView` | `false` | `boolean` | Whether or not to disable days outside the current view. | | `fixedDate` | | `"start" \| "end"` | Which part of the range should be fixed | | `fixedWeeks` | `false` | `boolean` | Whether or not to always display 6 weeks in the calendar | | `initialFocus` | `false` | `boolean` | If true, the calendar will focus the selected day, today, or the first day of the month depending on what is visible when the calendar is mounted | | `isDateDisabled` | | `Matcher` | A function that returns whether or not a date is disabled | | `isDateHighlightable` | | `Matcher` | A function that returns whether or not a date is hightable | | `isDateUnavailable` | | `Matcher` | A function that returns whether or not a date is unavailable | | `locale` | | `string` | The locale to use for formatting dates | | `maximumDays` | | `number` | The maximum number of days that can be selected in a range | | `maxValue` | | `DateValue` | The maximum date that can be selected | | `minValue` | | `DateValue` | The minimum date that can be selected | | `modelValue` | | `DateRange \| null` | The controlled selected date range of the calendar. Can be bound as `v-model`. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the next page of the calendar. It receives the current placeholder as an argument inside the component. | | `numberOfMonths` | `1` | `number` | The number of months to display at once | | `pagedNavigation` | `false` | `boolean` | This property causes the previous and next buttons to navigate by the number of months displayed at once, rather than one month | | `placeholder` | | `DateValue` | The placeholder date, which is used to determine what month to display when no date is selected. This updates as the user navigates the calendar and can be used to programmatically control the calendar view | | `preventDeselect` | `false` | `boolean` | Whether or not to prevent the user from deselecting a date without selecting another date first | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the previous page of the calendar. It receives the current placeholder as an argument inside the component. | | `readonly` | `false` | `boolean` | Whether or not the calendar is readonly | | `weekdayFormat` | `"narrow"` | `"narrow" \| "short" \| "long"` | The format to use for the weekday strings provided via the weekdays slot prop | | `weekStartsOn` | | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | The day of the week to start the calendar on | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: DateRange` | Event handler called whenever the model value changes | | `update:placeholder` | `date: DateValue` | Event handler called whenever the placeholder value changes | | `update:startValue` | `date: DateValue` | Event handler called whenever the start value changes | | `update:validModelValue` | `date: DateRange` | Event handler called whenever there is a new validModel | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `date` | `DateValue` | The current date of the placeholder | | `grid` | `Grid[]` | The grid of dates | | `weekDays` | `string[]` | The days of the week | | `weekStartsOn` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | The start of the week | | `locale` | `string` | The calendar locale | | `fixedWeeks` | `boolean` | Whether or not to always display 6 weeks in the calendar | | `modelValue` | `DateRange` | The current date range | [RangeCalendarRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarRoot.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Header Contains the navigation buttons and the heading segments. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [RangeCalendarHeader.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarHeader.vue) ### Prev Button Calendar navigation button. It navigates the calendar one month/year/decade in the past based on the current calendar view. | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the prev page. Overwrites the `prevPage` function set on the `RangeCalendarRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [RangeCalendarPrev.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarPrev.vue) ### Next Button Calendar navigation button. It navigates the calendar one month/year/decade in the future based on the current calendar view. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the next page. Overwrites the `nextPage` function set on the `RangeCalendarRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [RangeCalendarNext.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarNext.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Heading Heading for displaying the current month and year. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `headingValue` | `string` | Current month and year | [RangeCalendarHeading.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarHeading.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Grid Container for wrapping the calendar grid. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"table"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [RangeCalendarGrid.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarGrid.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | ### Grid Head Container for wrapping the grid head. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"thead"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [RangeCalendarGridHead.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarGridHead.vue) ### Grid Body Container for wrapping the grid body. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tbody"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [RangeCalendarGridBody.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarGridBody.vue) ### Grid Row Container for wrapping the grid row. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tr"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [RangeCalendarGridRow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarGridRow.vue) ### Head Cell Container for wrapping the head cell. Used for displaying the week days. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"th"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [RangeCalendarHeadCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarHeadCell.vue) ### Cell Container for wrapping the calendar cells. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"td"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `date*` | | `DateValue` | | [RangeCalendarCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarCell.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Cell Trigger Interactable container for displaying the cell dates. Clicking it selects the date. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `day*` | | `DateValue` | | | `month*` | | `DateValue` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `dayValue` | `string` | Current day | | `disabled` | `boolean` | Current disable state | | `selected` | `boolean` | Current selected state | | `today` | `boolean` | Current today state | | `outsideView` | `boolean` | Current outside view state | | `outsideVisibleView` | `boolean` | Current outside visible view state | | `unavailable` | `boolean` | Current unavailable state | | `highlighted` | `boolean` | Current highlighted state | | `highlightedStart` | `boolean` | Current highlighted start state | | `highlightedEnd` | `boolean` | Current highlighted end state | | `selectionStart` | `boolean` | Current selection start state | | `selectionEnd` | `boolean` | Current selection end state | [RangeCalendarCellTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar/RangeCalendarCellTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-selected]` | Present when selected | | `[data-value]` | The ISO string value of the date. | | `[data-disabled]` | Present when disabled | | `[data-unavailable]` | Present when unavailable | | `[data-today]` | Present when today | | `[data-outside-view]` | Present when the date is outside the current month it is displayed in. | | `[data-outside-visible-view]` | Present when the date is outside the months that are visible on the calendar. | | `[data-selection-start]` | Present when the date is the start of the selection. | | `[data-selection-end]` | Present when the date is the end of the selection. | | `[data-highlighted]` | Present when the date is highlighted by the user as they select a range. | | `[data-highlighted-start]` | Present when the date is the start of the range that is highlighted by the user. | | `[data-highlighted-end]` | Present when the date is the end of the range that is highlighted by the user. | | `[data-focused]` | Present when focused | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the calendar, focuses the first navigation button. | | Space | When the focus is on either `RangeCalendarNext` or `RangeCalendarPrev`, it navigates the calendar. Otherwise, it selects the date. | | Enter | When the focus is on either `RangeCalendarNext` or `RangeCalendarPrev`, it navigates the calendar. Otherwise, it selects the date. | | ArrowLeft / ArrowRight / ArrowUp / ArrowDown | When the focus is on `RangeCalendarCellTrigger`, it navigates the dates, changing the month/year/decade if necessary. | | Home | When the focus is on `RangeCalendarCellTrigger`, it moves focus to the first day of the current week. | | End | When the focus is on `RangeCalendarCellTrigger`, it moves focus to the last day of the current week. | | PageUp | When the focus is on `RangeCalendarCellTrigger`, it moves to the previous month while preserving the day of the month when possible, or clamps to the last day of the month. | | PageDown | When the focus is on `RangeCalendarCellTrigger`, it moves to the next month while preserving the day of the month when possible, or clamps to the last day of the month. | | Shift+PageUp | When the focus is on `RangeCalendarCellTrigger`, it moves to the previous year while preserving the month and day when possible, or clamps to the last day of the month. | | Shift+PageDown | When the focus is on `RangeCalendarCellTrigger`, it moves to the next year while preserving the month and day when possible, or clamps to the last day of the month. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RangeCalendar) - [npm](https://www.npmjs.com/package/akar) # Rating > A star-rating input where the user selects a score, with support for fractional values. ```vue [index.vue] ``` ```css [styles.css] @scope (.akar-demo-Rating) { .RatingRoot { display: flex; gap: 4px; } .RatingItem { position: relative; width: 32px; height: 32px; cursor: pointer; transition: transform 150ms ease-out; } .RatingItem:hover { transform: scale(1.1); } .RatingItemIndicator { position: absolute; overflow: hidden; border-radius: 4px; color: #e7e5e4; transition: color 150ms; width: var(--akar-rating-item-step-width); opacity: var(--akar-rating-item-step-opacity); z-index: var(--akar-rating-item-step-z-index); } .RatingItemIndicator[data-state="active"] { color: hsl(142.1 70.6% 45.3%); filter: drop-shadow(0 1px 4px hsl(142.1 70.6% 45.3% / 0.5)); } .RatingItemIndicator:focus-visible { outline: 2px solid hsl(142.1 70.6% 45.3%); outline-offset: 2px; } .RatingStar { width: 32px; height: 32px; } } ``` ## Features - Can be controlled or uncontrolled. - Supports fractional ratings (half, quarter, etc.) via the step prop. - Previews the value under the pointer on hover. - Can be cleared by clicking the active value again. - Built on top of Radio Group — full keyboard navigation and form support. - Supports Right to Left direction. - Exposes CSS variables for rendering partial steps. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. `RatingRoot` exposes the list of `items`, and each `RatingItem` exposes the `steps` it is made of, so you render an indicator per step. ```vue ``` ## API Reference ### Root Contains all the parts of a rating and provides the rating state. Renders a [Radio Group](https://vinicunca.dev/akar/components/radio-group) under the hood, so it supports form submission and keyboard navigation. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `clearable` | | `boolean` | When `true`, clicking the currently selected rating resets the value to `0`. | | `defaultValue` | | `number` | The rating value when initially rendered. Use when you do not need to control the state of the rating. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with radio items. | | `hoverable` | | `boolean` | When `true`, the rating previews the value under the pointer on hover. | | `length` | `5` | `number` | The number of rating items to render. | | `loop` | | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. | | `modelValue` | | `number` | The controlled rating value. Can be bound with `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation of the component. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | `1` | `1 \| 0.5 \| 0.25 \| 0.1` | The granularity each rating item is divided into. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: number` | Event handler called when the value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `number` | | | `items` | `number[]` | | [RatingRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Rating/RatingRoot.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Item Wraps a single rating value (e.g. a single star). It computes the list of `steps` that compose this item based on the root's `step` prop, exposed via the default slot. Renders a `label` by default. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"label"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `item*` | | `number` | The 1-based index of this item within the rating (e.g. the 3rd star). | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `steps` | `number[]` | | [RatingItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Rating/RatingItem.vue) ### ItemIndicator The interactive indicator rendered for each step of an item. It reflects whether the step is active based on the current (or hovered) value. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `step*` | | `number` | The step value this indicator represents. | [RatingItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Rating/RatingItemIndicator.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "active" | | `[data-disabled]` | Present when disabled | To render partial steps (for `step` values below `1`), `RatingItemIndicator` exposes the following CSS variables: | CSS Variable | Description | | --- | --- | | `--akar-rating-item-step-width` | The width this step should occupy within the item, e.g. `50%` for a half step. | | `--akar-rating-item-step-opacity` | `1` when the step should be visible, `0` otherwise (used to stack overlapping steps). | | `--akar-rating-item-step-z-index` | The stacking order of the step so smaller steps render above larger ones. | A typical fractional indicator clips its width and stacks steps using these variables: ```vue ``` ## Examples ### Fractional rating Use the `step` prop to allow values smaller than `1`. Each `RatingItem` is then split into multiple `steps`, and each step renders its own indicator clipped with the exposed CSS variables. ```vue ``` ### Clearable Use the `clearable` prop to let users reset the rating to `0` by clicking the currently selected value again. ```vue ``` ### Hover preview Use the `hoverable` prop to preview the value under the pointer before committing to it. The `RatingItemIndicator` exposes `data-state="active"` for every step at or below the hovered value. ```vue ``` ### Custom length Use the `length` prop to change how many items are rendered. It defaults to `5`. ```vue ``` ### Read-only / disabled Use the `disabled` prop to prevent interaction, for example when displaying an average rating. ```vue ``` ## Accessibility Built on top of the [Radio Group](https://vinicunca.dev/akar/components/radio-group) primitive and adheres to the [Radio Group WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/radio). Provide an accessible label for each step via `aria-label` so screen reader users understand the value each indicator represents. ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | Moves focus to either the checked item or the first item in the rating. | | Space | When focus is on an unchecked item, selects that value. | | ArrowDown | Moves focus and selection to the next item. | | ArrowRight | Moves focus and selection to the next item. | | ArrowUp | Moves focus and selection to the previous item. | | ArrowLeft | Moves focus and selection to the previous item. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/radio) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Rating) - [npm](https://www.npmjs.com/package/akar) # Scroll Area > Augments native scroll functionality for custom, cross-browser styling. ## ScrollArea ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-ScrollArea) { .ScrollAreaRoot { width: 200px; height: 225px; border-radius: 4px; overflow: hidden; box-shadow: 0 2px 10px var(--black-a7); background-color: white; --scrollbar-size: 10px; } .ScrollAreaViewport { width: 100%; height: 100%; border-radius: inherit; } .ScrollAreaScrollbar { display: flex; /* ensures no selection */ user-select: none; /* disable browser handling of all panning and zooming gestures on touch devices */ touch-action: none; padding: 2px; background: var(--black-a6); transition: background 160ms ease-out; } .ScrollAreaScrollbar:hover { background: var(--black-a8); } .ScrollAreaScrollbar[data-orientation='vertical'] { width: var(--scrollbar-size); } .ScrollAreaScrollbar[data-orientation='horizontal'] { flex-direction: column; height: var(--scrollbar-size); } .ScrollAreaThumb { flex: 1; background: var(--mauve-10); border-radius: var(--scrollbar-size); position: relative; } /* increase target size for touch devices https://www.w3.org/WAI/WCAG21/Understanding/target-size.html */ .ScrollAreaThumb::before { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 100%; height: 100%; min-width: 44px; min-height: 44px; } .ScrollAreaCorner { background: var(--black-a8); } .Text { color: var(--grass-11); font-size: 15px; line-height: 18px; font-weight: 500; } .Tag { color: var(--mauve-12); font-size: 13px; line-height: 18px; margin-top: 10px; border-top: 1px solid var(--mauve-6); padding-top: 10px; } } ``` ## Features - Scrollbar sits on top of the scrollable content, taking up no space. - Scrolling is native; no underlying position movements via CSS transformations. - Shims pointer behaviors only when interacting with the controls, so keyboard controls are unaffected. - Supports Right to Left direction. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a scroll area. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `scrollHideDelay` | `600` | `number` | If type is set to either `scroll` or `hover`, this prop determines the length of time, in milliseconds,

before the scrollbars are hidden after the user stops interacting with scrollbars. | | `type` | `"hover"` | `"scroll" \| "always" \| "hover" \| "auto" \| "glimpse"` | Describes the nature of scrollbar visibility, similar to how the scrollbar preferences in MacOS control visibility of native scrollbars.

`auto` - means that scrollbars are visible when content is overflowing on the corresponding orientation.

`always` - means that scrollbars are always visible regardless of whether the content is overflowing.

`scroll` - means that scrollbars are visible when the user is scrolling along its corresponding orientation.

`hover` - when the user is scrolling along its corresponding orientation and when the user is hovering over the scroll area.

`glimpse` - a hybrid approach that briefly shows scrollbars when the user enters the scroll area, then hides them until further interaction. | **Methods** | Method | Type | Description | | --- | --- | --- | | `scrollTop` | `() => void` | Scroll viewport to top | | `scrollTopLeft` | `() => void` | Scroll viewport to top-left | [ScrollAreaRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ScrollArea/ScrollAreaRoot.vue) ### Viewport The viewport area of the scroll area. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `nonce` | | `string` | Will add `nonce` attribute to the style tag which can be used by Content Security Policy.

If omitted, inherits globally from `ConfigProvider`. | [ScrollAreaViewport.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ScrollArea/ScrollAreaViewport.vue) ### Scrollbar The vertical scrollbar. Add a second `Scrollbar` with an `orientation` prop to enable horizontal scrolling. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `orientation` | `"vertical"` | `"vertical" \| "horizontal"` | The orientation of the scrollbar | [ScrollAreaScrollbar.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ScrollArea/ScrollAreaScrollbar.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "visible" \\| "hidden" | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Thumb The thumb to be used in `ScrollAreaScrollbar`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ScrollAreaThumb.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ScrollArea/ScrollAreaThumb.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "visible" \\| "hidden" | ### Corner The corner where both vertical and horizontal scrollbars meet. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ScrollAreaCorner.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ScrollArea/ScrollAreaCorner.vue) ## Examples ### Custom Scroll Use the exposed `viewport` to modify / or set the scroll position outside default methods ```vue ``` ## Accessibility In most cases, it's best to rely on native scrolling and work with the customization options available in CSS. When that isn't enough, `ScrollArea` provides additional customizability while maintaining the browser's native scroll behavior (as well as accessibility features, like keyboard scrolling). ### Keyboard Interactions Scrolling via keyboard is supported by default because the component relies on native scrolling. Specific keyboard interactions may differ between platforms, so we do not specify them here or add specific event listeners to handle scrolling via key events. --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ScrollArea) - [npm](https://www.npmjs.com/package/akar) # Select > Displays a list of options for the user to pick from—triggered by a button. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Select) { /* reset */ button { all: unset; } .SelectTrigger { display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; padding: 0 15px; font-size: 13px; line-height: 1; height: 35px; gap: 5px; background-color: white; color: var(--grass-11); box-shadow: 0 2px 10px var(--black-a7); } .SelectTrigger:hover { background-color: var(--mauve-3); } .SelectTrigger:focus { box-shadow: 0 0 0 2px black; } .SelectTrigger[data-placeholder] { color: var(--grass-9); } .SelectIcon { color: Var(--grass-11); } .SelectContent { overflow: hidden; background-color: white; border-radius: 6px; box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2); } .SelectViewport { padding: 5px; } .SelectItem { font-size: 13px; line-height: 1; color: var(--grass-11); border-radius: 3px; display: flex; align-items: center; height: 25px; padding: 0 35px 0 25px; position: relative; user-select: none; } .SelectItem[data-disabled] { color: var(--mauve-8); pointer-events: none; } .SelectItem[data-highlighted] { outline: none; background-color: var(--grass-9); color: var(--grass-1); } .SelectLabel { padding: 0 25px; font-size: 12px; line-height: 25px; color: var(--mauve-11); } .SelectSeparator { height: 1px; background-color: var(--grass-6); margin: 5px; } .SelectItemIndicator { position: absolute; left: 0; width: 25px; display: inline-flex; align-items: center; justify-content: center; } .SelectScrollButton { display: flex; align-items: center; justify-content: center; height: 25px; background-color: white; color: var(--grass-11); cursor: default; } } ``` ## Features - Can be controlled or uncontrolled. - Offers 2 positioning modes. - Supports items, labels, groups of items. - Focus is fully managed. - Full keyboard navigation. - Supports custom placeholder. - Typeahead support. - Supports Right to Left direction. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a Select **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `autocomplete` | | `string` | Native html input `autocomplete` attribute. | | `by` | | `string \| ((a: T, b: T) => boolean)` | Use this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared. | | `defaultOpen` | | `boolean` | The open state of the select when it is initially rendered. Use when you do not need to control its open state. | | `defaultValue` | | `T \| T[]` | The value of the select when initially rendered. Use when you do not need to control the state of the Select | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with Select | | `modelValue` | | `T \| T[]` | The controlled value of the Select. Can be bind as `v-model`. | | `multiple` | | `boolean` | Whether multiple options can be selected or not. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `nullableValue` | `""` | `string` | The value of the hidden native select option when the model value is nullish. | | `open` | | `boolean` | The controlled open state of the Select. Can be bind as `v-model:open`. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `value: T` | Event handler called when the value changes. | | `update:open` | `value: boolean` | Event handler called when the open state of the context menu changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `T \| T[]` | Current input values | | `open` | `boolean` | Current open state | [SelectRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectRoot.vue) ### Trigger The button that toggles the Select The `SelectContent` will position itself by aligning over the trigger. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | | | `reference` | | `ReferenceElement` | The reference (or anchor) element that is being referred to for positioning.

If not provided will use the current component as anchor. | [SelectTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-disabled]` | Present when disabled | | `[data-placeholder]` | Present when has placeholder | ### Value The part that reflects the selected value. By default the selected item's text will be rendered. if you require more control, you can instead control the select and pass your own `children`. It should not be styled to ensure correct positioning. An optional `placeholder` prop is also available for when the select has no value. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `placeholder` | `""` | `string` | The content that will be rendered inside the `SelectValue` when no `value` or `defaultValue` is set. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `selectedLabel` | `string[]` | | | `modelValue` | `AcceptableValue \| AcceptableValue[]` | | [SelectValue.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectValue.vue) ### Icon A small icon often displayed next to the value as a visual affordance for the fact it can be open. By default renders ▼ but you can use your own icon via `asChild` or use `children`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `textValue` | | `string` | Optional text used for typeahead purposes.

By default the typeahead behavior will use the `.textContent` of the `SelectItemText` part.

Use this when the content is complex, or you have non-textual content inside. | | `value*` | | `AcceptableValue` | The value given as data when submitted with a `name`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: SelectEvent` | Event handler called when the selecting item.

It can be prevented by calling `event.preventDefault`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `selected` | `boolean` | Whether the item is currently selected | [SelectItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectItem.vue) ### Portal When used, portals the content part into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [SelectPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectPortal.vue) ### Content The component that pops out when the select is open. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.
May change when collisions occur. | | `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `bodyLock` | `true` | `boolean` | The document.body will be lock, and scrolling will be disabled. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the popper content when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disableOutsidePointerEvents` | | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside
the `DismissableLayer`. Users will need to click twice on outside elements to
interact with them: once to close the `DismissableLayer`, and again to trigger the element. | | `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered
to the reference element. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `memoDependencies` | | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. | | `position` | | `"popper" \| "item-aligned"` | The positioning mode to use

`item-aligned (default)` - behaves similarly to a native MacOS menu by positioning content relative to the active item.

`popper` - positions content in the same way as our other primitives, for example `Popover` or `DropdownMenu`. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.

Might overlap the reference element, which may not be desired. | | `reference` | | `ReferenceElement` | The custom element or virtual element that will be set as the reference
to position the floating element.

If provided, it will replace the default anchor element. | | `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.
Will be reversed when collisions occur and avoidCollisions
is enabled. | | `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `closeAutoFocus` | `event: Event` | | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.
Can be prevented. | | `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
Can be prevented. | [SelectContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | CSS variable | Description | | --- | --- | | `--akar-select-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets. Only present when `position="popper"`. | | `--akar-select-content-available-width` | The remaining width between the trigger and the boundary edge. Only present when `position="popper"`. | | `--akar-select-content-available-height` | The remaining height between the trigger and the boundary edge. Only present when `position="popper"`. | | `--akar-select-trigger-width` | The width of the trigger. Only present when `position="popper"`. | | `--akar-select-trigger-height` | The height of the trigger. Only present when `position="popper"`. | ### Viewport The scrolling viewport that contains all of the items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `nonce` | | `string` | Will add `nonce` attribute to the style tag which can be used by Content Security Policy.

If omitted, inherits globally from `ConfigProvider`. | [SelectViewport.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectViewport.vue) ### Item The component that contains the select items. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `textValue` | | `string` | Optional text used for typeahead purposes.

By default the typeahead behavior will use the `.textContent` of the `SelectItemText` part.

Use this when the content is complex, or you have non-textual content inside. | | `value*` | | `AcceptableValue` | The value given as data when submitted with a `name`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: SelectEvent` | Event handler called when the selecting item.

It can be prevented by calling `event.preventDefault`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `selected` | `boolean` | Whether the item is currently selected | [SelectItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-highlighted]` | Present when highlighted | | `[data-disabled]` | Present when disabled | ### ItemText The textual part of the item. It should only contain the text you want to see in the trigger when that item is selected. It should not be styled to ensure correct positioning. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [SelectItemText.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectItemText.vue) ### ItemIndicator Renders when the item is selected. You can style this element directly, or you can use it as a wrapper to put an icon into, or both. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | [SelectItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectItemIndicator.vue) ### ScrollUpButton An optional button used as an affordance to show the viewport overflow as well as functionally enable scrolling upwards. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [SelectScrollUpButton.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectScrollUpButton.vue) ### ScrollDownButton An optional button used as an affordance to show the viewport overflow as well as functionally enable scrolling downwards. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [SelectScrollDownButton.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectScrollDownButton.vue) ### Group Used to group multiple items. use in conjunction with `SelectLabel` to ensure good accessibility via automatic labelling. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [SelectGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectGroup.vue) ### Label Used to render the label of a group. It won't be focusable using arrow keys. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `for` | | `string` | | [SelectLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectLabel.vue) ### Separator Used to visually separate items in the Select **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [SelectSeparator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectSeparator.vue) ### Arrow An optional arrow element to render alongside the content. This can be used to help visually link the trigger with the `SelectContent`. Must be rendered inside `SelectContent`. Only available when `position` is set to `popper`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` | | `width` | `10` | `number` | The width of the arrow in pixels. | [SelectArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select/SelectArrow.vue) ## Examples ### Change the positioning mode By default, `Select` will behave similarly to a native MacOS menu by positioning `SelectContent` relative to the active item. If you would prefer an alternative positioning approach similar to `Popover` or `DropdownMenu` then you can set `position` to `popper` and make use of additional alignment options such as `side`, `sideOffset` and more. ```vue // index.vue ``` ### Constrain the content size When using `position="popper"` on `SelectContent`, you may want to constrain the width of the content so that it matches the trigger width. You may also want to constrain its height to not exceed the viewport. We expose several CSS custom properties such as `--akar-select-trigger-width` and `--akar-select-content-available-height` to support this. Use them to constrain the content dimensions. ```vue // index.vue ``` ```css /* styles.css */ .SelectContent { width: var(--akar-select-trigger-width); max-height: var(--akar-select-content-available-height); } ``` ### With disabled items You can add special styles to disabled items via the `data-disabled` attribute. ```vue // index.vue ``` ```css /* styles.css */ .SelectItem[data-disabled] { color: "gainsboro"; } ``` ### With a placeholder You can use the `placeholder` prop on `Value` for when the select has no value. There's also a `data-placeholder` attribute on `Trigger` to help with styling. ```vue // index.vue ``` ```css /* styles.css */ .SelectTrigger[data-placeholder] { color: "gainsboro"; } ``` ### With separators Use the `Separator` part to add a separator between items. ```vue ``` ### With grouped items Use the `Group` and `Label` parts to group items in a section. ```vue ``` ### With complex items You can use custom content in your items. ```vue ``` ### Controlling the value displayed in the trigger By default the trigger display the selected item's text (no longer automatically render `ItemText`'s content like in v1). If you need to render other than plain text, you can control the component using `v-model` props (or accessing `SelectValue`'s slotProps) and passing `slot` to `SelectValue`. Remember to make sure what you put in there is accessible. ```vue ``` ### With custom scrollbar The native scrollbar is hidden by default as we recommend using the `ScrollUpButton` and `ScrollDownButton` parts for the best UX. If you do not want to use these parts, compose your select with our [Scroll Area](scroll-area) primitive. ```vue // index.vue ``` ```css /* styles.css */ .ScrollAreaRoot { width: 100%; height: 100%; } .ScrollAreaViewport { width: 100%; height: 100%; } .ScrollAreaScrollbar { width: 4px; padding: 5px 2px; } .ScrollAreaThumb { background: rgba(0, 0, 0, 0.3); borderradius: 3px; } ``` ## Accessibility Adheres to the [ListBox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox). See the W3C [Select-Only Combobox](https://www.w3.org/TR/wai-aria-practices/examples/combobox/combobox-select-only.html) example for more information. ### Keyboard Interactions | Key | Description | | --- | --- | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/listbox) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Select) - [npm](https://www.npmjs.com/package/akar) # Separator > Visually or semantically separates content. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/grass.css'; @scope (.akar-demo-Separator) { .SeparatorRoot { background-color: var(--grass-6); } .SeparatorRoot[data-orientation='horizontal'] { height: 1px; width: 100%; } .SeparatorRoot[data-orientation='vertical'] { height: 100%; width: 1px; } .Text { color: white; font-size: 15px; line-height: 20px; } } ``` ## Features - Supports horizontal and vertical orientations. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root The separator. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `decorative` | | `boolean` | Whether or not the component is purely decorative.

When `true`, accessibility-related attributes
are updated so that that the rendered element is removed from the accessibility tree. | | `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | Orientation of the component.

Either `vertical` or `horizontal`. Defaults to `horizontal`. | [Separator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Separator/Separator.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ## Accessibility Adheres to the [`separator` role requirements](https://www.w3.org/TR/wai-aria-1.2/#separator). --- - [ARIA](https://www.w3.org/TR/wai-aria-1.2/#separator) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Separator) - [npm](https://www.npmjs.com/package/akar) # Slider > An input where the user selects a value from within a given range. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Slider) { .SliderRoot { position: relative; display: flex; align-items: center; user-select: none; touch-action: none; width: 200px; height: 20px; } .SliderTrack { background-color: var(--black-a10); position: relative; flex-grow: 1; border-radius: 9999px; height: 3px; } .SliderRange { position: absolute; background-color: white; border-radius: 9999px; height: 100%; } .SliderThumb { display: block; width: 20px; height: 20px; background-color: white; box-shadow: 0 2px 10px var(--black-a7); border-radius: 10px; } .SliderThumb:hover { background-color: var(--grass-3); } .SliderThumb:focus { outline: none; box-shadow: 0 0 0 5px var(--black-a8); } } ``` ## Features - Can be controlled or uncontrolled. - Supports multiple thumbs. - Supports a minimum value between thumbs. - Supports touch or click on track to update value. - Supports Right to Left direction. - Full keyboard navigation. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a slider. It will render an `input` for each thumb when used within a `form` to ensure events propagate correctly. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | `[0]` | `number[]` | The value of the slider when initially rendered. Use when you do not need to control the state of the slider. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the slider. | | `inverted` | `false` | `boolean` | Whether the slider is visually inverted. | | `max` | `100` | `number` | The maximum value for the range. | | `min` | `0` | `number` | The minimum value for the range. | | `minStepsBetweenThumbs` | `0` | `number` | The minimum permitted steps between multiple thumbs. | | `modelValue` | | `number[] \| null` | The controlled value of the slider. Can be bind as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation of the slider. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | `1` | `number` | The stepping interval. | | `thumbAlignment` | `"contain"` | `"contain" \| "overflow"` | The alignment of the slider thumb.
- `contain`: thumbs will be contained within the bounds of the track.
- `overflow`: thumbs will not be bound by the track. No extra offset will be added. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: number[]` | Event handler called when the slider value changes | | `valueCommit` | `payload: number[]` | Event handler called when the value changes at the end of an interaction.

Useful when you only need to capture a final value e.g. to update a backend service. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `number[] \| null` | Current slider values | [SliderRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Slider/SliderRoot.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Track The track that contains the `SliderRange`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [SliderTrack.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Slider/SliderTrack.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Range The range part. Must live inside `SliderTrack`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [SliderRange.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Slider/SliderRange.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Thumb A draggable thumb. You can render multiple thumbs. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [SliderThumb.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Slider/SliderThumb.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ## Examples ### Vertical orientation Use the `orientation` prop to create a vertical slider. ```vue // index.vue ``` ```css /* styles.css */ .SliderRoot { position: relative; display: flex; align-items: center; } .SliderRoot[data-orientation="vertical"] { flex-direction: column; width: 20px; height: 100px; } .SliderTrack { position: relative; flex-grow: 1; background-color: grey; } .SliderTrack[data-orientation="vertical"] { width: 3px; } .SliderRange { position: absolute; background-color: black; } .SliderRange[data-orientation="vertical"] { width: 100%; } .SliderThumb { display: block; width: 20px; height: 20px; background-color: black; } ``` ### Create a range Add multiple thumbs and values to create a range slider. ```vue // index.vue ``` ### Define step size Use the `step` prop to increase the stepping interval. ```vue // index.vue ``` ### Prevent thumb overlap Use `minStepsBetweenThumbs` to avoid thumbs with equal values. ```vue // index.vue ``` ## Accessibility Adheres to the [Slider WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/slidertwothumb). ### Keyboard Interactions | Key | Description | | --- | --- | | ArrowRight | Increases the value by the `step` amount. | | ArrowLeft | Decreases the value by the `step` amount. | | ArrowUp | Increases the value by the `step` amount. | | ArrowDown | Decreases the value by the `step` amount. | | PageUp | Increases the value by a larger `step`. | | PageDown | Decreases the value by a larger `step`. | | Shift + ArrowUp | Increases the value by a larger `step`. | | Shift + ArrowDown | Decreases the value by a larger `step`. | | Home | Sets the value to its minimum. | | End | Sets the value to its maximum. | #### Inverted sliders When the slider is `inverted`, some controls are inverted as well, depending on the `orientation`. - When the slider is `horizontal` (the default), `→`, `←`, `Home`, and `End` are inverted. - When the slider is `vertical`, `↑`, `↓`, `PageUp`, `PageDown`, `Shift + ArrowUp`, and `Shift + ArrowDown` are inverted. ## Custom APIs Create your own API by abstracting the primitive parts into your own component. ### Abstract all parts This example abstracts all of the `Slider` parts so it can be used as a self closing element. #### Usage ```vue ``` #### Implementation ```ts // your-slider.ts export { default as Slider } from 'Slider.vue'; ``` ```vue ``` ## Caveats ### Mouse events are not fired Because of [a limitation](https://github.com/unovue/reka-ui/blob/v2/packages/core/src/Slider/SliderImpl.vue#L48-L49) we faced during implementation, the following example won't work as expected and the `@mousedown` and `@mousedown` event handlers won't be fired: ```vue … ``` We recommend using pointer events instead (eg. `@pointerdown`, `@pointerup`). Regardless of the above limitation, these events are better suited for cross-platform/device handling as they are fired for all pointer input types (mouse, touch, pen, etc.). --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/slidertwothumb) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Slider) - [npm](https://www.npmjs.com/package/akar) # Splitter > A component that divides your layout into resizable sections. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @scope (.akar-demo-Splitter) { /* reset */ button { all: unset; } .SplitterPanel { background-color: #ffffff; border-radius: 1.5rem; display: flex; align-items: center; justify-content: center; } .SplitterResizeHandle[data-orientation="horizontal"] { width: 0.5rem } .SplitterResizeHandle[data-orientation="vertical"] { height: 0.5rem } } ``` ## Features - Supports keyboard interaction. - Supports horizontal/vertical layout. - Supports nested layout. - Supports Right to Left direction. - Can resize across another panel. - Can be mounted conditionally. - Supports percent and pixel sizing. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Group Contains all the parts of a Splitter. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `autoSaveId` | `null` | `string \| null` | Unique id used to auto-save group arrangement via `localStorage`. | | `direction*` | | `"vertical" \| "horizontal"` | The group orientation of splitter. | | `id` | | `string \| null` | Group id; falls back to `useId` when not provided. | | `keyboardResizeBy` | `10` | `number \| null` | Step size when arrow key was pressed. | | `storage` | `defaultStorage` | `PanelGroupStorage` | Custom storage API; defaults to localStorage | **Events** | Event | Payload | Description | | --- | --- | --- | | `layout` | `val: number[]` | Event handler called when group layout changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `layout` | `number[]` | Current size of layout | [SplitterGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Splitter/SplitterGroup.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | | `[data-state]` | "collapsed" \\| "expanded" \\| "Present when collapsbile" | ### Panel A collapsible section. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `collapsedSize` | | `number` | The size of panel when it is collapsed; interpreted using `sizeUnit`. | | `collapsible` | | `boolean` | Should panel collapse when resized beyond its `minSize`. When `true`, it will be collapsed to `collapsedSize`. | | `defaultSize` | | `number` | Initial size of panel, interpreted using `sizeUnit` (percent by default). | | `id` | | `string` | Panel id (unique within group); falls back to `useId` when not provided | | `maxSize` | | `number` | The maximum allowable size of panel, interpreted using `sizeUnit`; defaults to `100` (percent). | | `minSize` | | `number` | The minimum allowable size of panel, interpreted using `sizeUnit`; defaults to `10` (percent). | | `order` | | `number` | The order of panel within group; required for groups with conditionally rendered panels | | `sizeUnit` | | `"%" \| "px"` | Unit used for sizing values; `%` by default, or `px` for fixed sizing. | **Events** | Event | Payload | Description | | --- | --- | --- | | `collapse` | | Event handler called when panel is collapsed. | | `expand` | | Event handler called when panel is expanded. | | `resize` | `size: number, prevSize: number` | Event handler called when panel is resized; size parameter is a numeric value between 1-100. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `isCollapsed` | `boolean` | Is the panel collapsed | | `isExpanded` | `boolean` | Is the panel expanded | | `collapse` | `(): void` | If panel is `collapsible`, collapse it fully. | | `expand` | `(): void` | If panel is currently collapsed, expand it to its most recent size. | | `resize` | `(size: number): void` | Resize panel to the specified percentage (1 - 100). | **Methods** | Method | Type | Description | | --- | --- | --- | | `collapse` | `() => void` | If panel is `collapsible`, collapse it fully. | | `expand` | `() => void` | If panel is currently collapsed, expand it to its most recent size. | | `getSize` | `() => number` | Gets the current size of the panel (in the panel's sizeUnit: percentage for '%', pixels for 'px'). | | `resize` | `(size: number) => void` | Resize panel to the specified size (in the panel's sizeUnit: percentage for '%', pixels for 'px'). | [SplitterPanel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Splitter/SplitterPanel.vue) ### Resize Handle Handle that use for resizing. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | Disable drag handle | | `hitAreaMargins` | | `PointerHitAreaMargins` | Allow this much margin when determining resizable handle hit detection | | `id` | | `string` | Resize handle id (unique within group); falls back to `useId` when not provided | | `nonce` | | `string` | Will add `nonce` attribute to the style tag which can be used by Content Security Policy.

If omitted, inherits globally from `ConfigProvider`. | | `tabindex` | `0` | `number` | Tabindex for the handle | **Events** | Event | Payload | Description | | --- | --- | --- | | `dragging` | `isDragging: boolean` | Event handler called when dragging the handler. | [SplitterResizeHandle.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Splitter/SplitterResizeHandle.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "drag" \\| "hover" \\| "inactive" | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ## Examples ### Collapsible Use the `collapsible` prop to allow the panel to collapse into `collapsedSize` when `minSize` is reached. (`collapsedSize` and `minSize` props are required.) ```vue ``` ### Persist in localStorage Use the `autoSaveId` prop to save the layout data into `localStorage`. ```vue ``` ### Persist layout with SSR By default, Splitter uses `localStorage` to persist layouts. With server rendering, this can cause a flicker when the default layout (rendered on the server) is replaced with the persisted layout (in `localStorage`). The way to avoid this flicker is to also persist the layout with a cookie like so: ```vue ``` ### Collapse/Expand programmatically Sometimes panels need to resize or collapse/expand in response to user actions. `SplitterPanel` exposes the `collapse` and `expand` methods to achieve this. ```vue ``` ### Pixel sizing Use `sizeUnit="px"` when you need a panel to stay a fixed pixel width (great for sidebars) even if the parent container resizes. All sizing props (`defaultSize`, `minSize`, `maxSize`, `collapsedSize`) are interpreted using the chosen unit. ```vue ``` Pixel-sized panels also work with persistence (`autoSaveId`) and collapse/expand APIs; sizes are restored using the correct unit. ### Custom handle Customize the handle by passing any element as the slot. ```vueline=6-8 ``` ### SSR Splitter component heavily relies on unique `id`, however for Vue<3.4 we don't have a reliable way of generating [SSR-friendly `id`](https://github.com/vuejs/rfcs/discussions/557). Thus, if you are using Nuxt or other SSR framework, you are required to manually add the `id` for all Splitter components. Alternatively, you can wrap the component with ``. ```vue ``` ## Accessibility Adheres to the [Window Splitter WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter). ### Keyboard Interactions | Key | Description | | --- | --- | | Enter | If the primary pane is not collapsed, collapses the pane. If the pane is collapsed, restores the splitter to its previous position. | | ArrowDown | Moves a horizontal splitter down. | | ArrowUp | Moves a horizontal splitter up. | | ArrowRight | Moves a vertical splitter to the right. | | ArrowLeft | Moves a vertical splitter to the left. | | Home | Moves splitter to the position that gives the primary pane its smallest allowed size. | | End | Moves splitter to the position that gives the primary pane its largest allowed size. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Splitter) - [npm](https://www.npmjs.com/package/akar) # Stepper > A set of steps that are used to indicate progress through a multi-step process. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/grass.css'; @import '../_colors/mauve.css'; @import '../_colors/green.css'; @scope (.akar-demo-Stepper) { .StepperList { display: flex; gap: 1rem; } .StepperItem { display: flex; gap: 1rem; align-items: center; cursor: pointer; } .StepperItem[data-disabled] { pointer-events: none; } .StepperTrigger { display: flex; flex-direction: column; gap: 0.5rem; align-items: center; } .StepperIndicator { display: inline-flex; align-items: center; justify-content: center; border-radius: 9999px; width: 1.5rem; height: 1.5rem; color: var(--grass11); box-shadow: 0 0 0 2px #000; } .StepperItem[data-disabled] .StepperIndicator { color: #9ca3af; } .StepperItem[data-state="active"] .StepperIndicator { background-color: #000; color: #fff; box-shadow: 0 0 0 2px #000; } .StepperItem[data-state="completed"] .StepperIndicator { background-color: var(--green9); color: #fff; box-shadow: 0 0 0 2px var(--green9); } .StepperIcon { width: 1.5rem; height: 1.5rem; } .StepperTitle { font-size: 0.875rem; font-weight: 500; color: #000; } .StepperDescription { font-size: 0.75rem; color: #000; } .StepperSeparator { width: 20px; height: 1px; flex-shrink: 0; background-color: var(--green5); } .StepperItem[data-state="active"] .StepperSeparator { background-color: #000; } .StepperItem[data-state="completed"] .StepperSeparator { background-color: var(--green9); } .StepperItem[data-disabled] { background-color: #d1d5db; } } ``` ## Features - Can be controlled or uncontrolled. - Supports horizontal/vertical orientation. - Supports linear/non-linear activation. - Full keyboard navigation. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the stepper component parts. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | `1` | `number` | The value of the step that should be active when initially rendered. Use when you do not need to control the state of the steps. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `linear` | `true` | `boolean` | Whether or not the steps must be completed in order. | | `modelValue` | | `number` | The controlled value of the step to activate. Can be bound as `v-model`. | | `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation the steps are laid out.
Mainly so arrow navigation is done accordingly (left & right vs. up & down). | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: number` | Event handler called when the value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `number` | Current step | | `totalSteps` | `number` | Total number of steps | | `isNextDisabled` | `boolean` | Whether or not the next step is disabled | | `isPrevDisabled` | `boolean` | Whether or not the previous step is disabled | | `isFirstStep` | `boolean` | Whether or not the first step is active | | `isLastStep` | `boolean` | Whether or not the last step is active | | `goToStep` | `(step: number): void` | Go to a specific step | | `nextStep` | `(): void` | Go to the next step | | `prevStep` | `(): void` | Go to the previous step | | `hasNext` | `(): boolean` | Whether or not there is a next step | | `hasPrev` | `(): boolean` | Whether or not there is a previous step | **Methods** | Method | Type | Description | | --- | --- | --- | | `goToStep` | `(step: number) => void` | | | `nextStep` | `() => void` | | | `prevStep` | `() => void` | | | `hasNext` | `() => boolean` | | | `hasPrev` | `() => boolean` | | [StepperRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperRoot.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | | `[data-linear]` | Present when linear | ### Item The step item component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `completed` | `false` | `boolean` | Shows whether the step is completed. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the step. | | `step*` | | `number` | A unique value that associates the stepper item with an index | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `state` | `"active" \| "completed" \| "inactive"` | The current state of the stepper item | [StepperItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "active" \\| "inactive" \\| "completed" | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Trigger The trigger that toggles the step. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [StepperTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "active" \\| "inactive" \\| "completed" | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Indicator The indicator for the step. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `step` | `number` | Current step | [StepperIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperIndicator.vue) ### Title An accessible title to be announced when the stepper trigger is focused. If you want to hide the title, wrap it inside our Visually Hidden utility like this ``. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"h4"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [StepperTitle.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperTitle.vue) ### Description An optional accessible description to be announced when the stepper trigger is focused. If you want to hide the description, wrap it inside our Visually Hidden utility like this ``. If you want to remove the description entirely, remove this part and pass `aria-describedby="undefined"` to `StepperTrigger`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `completed` | `false` | `boolean` | Shows whether the step is completed. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the step. | | `step*` | | `number` | A unique value that associates the stepper item with an index | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `state` | `"active" \| "completed" \| "inactive"` | The current state of the stepper item | [StepperItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperItem.vue) ## Examples ### Vertical You can create vertical steps by using the `orientation` prop. ```vue ``` ### With controls You can add additional controls for the stepper using buttons and access the typed component instance using `useTemplateRef`. ```vue ``` ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the steps, focuses the first step . | | ArrowDown | Moves focus to the next step depending on `orientation`. | | ArrowRight | Moves focus to the next step depending on `orientation` . | | ArrowUp | Moves focus to the previous step depending on `orientation` . | | ArrowLeft | Moves focus to the previous step depending on `orientation` . | | Enter / Space | Selects the focused step. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper) - [npm](https://www.npmjs.com/package/akar) # Switch > A control that allows the user to toggle between checked and not checked. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @scope (.akar-demo-Switch) { /* reset */ button { all: unset; } .SwitchRoot { width: 42px; height: 25px; background-color: var(--black-a9); border-radius: 9999px; position: relative; box-shadow: 0 2px 10px var(--black-a7); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } .SwitchRoot:focus { box-shadow: 0 0 0 2px black; } .SwitchRoot[data-state='checked'] { background-color: black; } .SwitchThumb { display: block; width: 21px; height: 21px; background-color: white; border-radius: 9999px; box-shadow: 0 2px 2px var(--black-a7); transition: transform 100ms; transform: translateX(2px); will-change: transform; } .SwitchThumb[data-state='checked'] { transform: translateX(19px); } .Label { color: white; font-size: 15px; line-height: 1; } } ``` ## Features - Full keyboard navigation. - Can be controlled or uncontrolled. - Supports custom true/false values. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a switch. An `input` will also render when used within a `form` to ensure events propagate correctly. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `T` | The state of the switch when it is initially rendered. Use when you do not need to control its state. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the switch. | | `falseValue` | `(() => false) as unknown as undefined` | `T` | The value used when the switch is off. Defaults to `false`. | | `id` | | `string` | | | `modelValue` | | `null \| T` | The controlled state of the switch. Can be bind as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `trueValue` | `(() => true) as unknown as undefined` | `T` | The value used when the switch is on. Defaults to `true`. | | `value` | `"on"` | `string` | The value given as data when submitted with a `name`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: T` | Event handler called when the value of the switch changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `T` | Current value | | `checked` | `boolean` | Whether the switch is checked | [SwitchRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Switch/SwitchRoot.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-disabled]` | Present when disabled | ### Thumb The thumb that is used to visually indicate whether the switch is on or off. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [SwitchThumb.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Switch/SwitchThumb.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-disabled]` | Present when disabled | ## Examples ### Custom Values Use the `trueValue` and `falseValue` props to specify custom values for the on and off states instead of the default `true`/`false`. ```vue ``` ## Accessibility Adheres to the [`switch` role requirements](https://www.w3.org/WAI/ARIA/apg/patterns/switch). ### Keyboard Interactions | Key | Description | | --- | --- | | Space | Toggles the component's state. | | Enter | Toggles the component's state. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/switch) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Switch) - [npm](https://www.npmjs.com/package/akar) # Tabs > A set of layered sections of content—known as tab panels—that are displayed one at a time. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/green.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Tabs) { /* reset */ button, fieldset, input { all: unset; } .TabsRoot { display: flex; flex-direction: column; width: 300px; box-shadow: 0 2px 10px var(--black-a4); } .TabsList { flex-shrink: 0; display: flex; border-bottom: 1px solid var(--mauve-6); position: relative; } .TabsIndicator { position: absolute; padding-left: 2rem; left: 0; height: 2px; bottom: 0; width: var(--akar-tabs-indicator-size); transform: translateX(var(--akar-tabs-indicator-position)); border-radius: 9999px; /* rounded-full equivalent */ transition-property: width, transform; transition-duration: 300ms; } .TabsIndicatorContent { background-color: var(--grass-8); height: 100%; width: 100%; } .TabsTrigger { font-family: inherit; background-color: white; padding: 0 20px; height: 45px; flex: 1; display: flex; align-items: center; justify-content: center; font-size: 15px; line-height: 1; color: var(--mauve-11); user-select: none; } .TabsTrigger:first-child { border-top-left-radius: 6px; } .TabsTrigger:last-child { border-top-right-radius: 6px; } .TabsTrigger:hover { color: var(--grass-11); } .TabsTrigger[data-state='active'] { color: var(--grass-11); box-shadow: inset 0 -1px 0 0 currentColor, 0 1px 0 0 currentColor; } .TabsTrigger:focus { position: relative; box-shadow: 0 0 0 2px black; } .TabsContent { flex-grow: 1; padding: 20px; background-color: white; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; outline: none; } .TabsContent:focus { box-shadow: 0 0 0 2px black; } .Text { margin-top: 0; margin-bottom: 20px; color: var(--mauve-11); font-size: 15px; line-height: 1.5; } .Fieldset { margin-bottom: 15px; width: 100%; display: flex; flex-direction: column; justify-content: flex-start; } .Label { font-size: 13px; line-height: 1; margin-bottom: 10px; color: var(--grass-12); display: block; } .Input { flex: 1 0 auto; border-radius: 4px; padding: 0 10px; font-size: 15px; line-height: 1; color: var(--grass-11); box-shadow: 0 0 0 1px var(--grass-7); height: 35px; } .Input:focus { box-shadow: 0 0 0 2px var(--grass-8); } .Button { display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; padding: 0 15px; font-size: 15px; line-height: 1; font-weight: 500; height: 35px; } .Button.green { background-color: var(--green-4); color: var(--green-11); } .Button.green:hover { background-color: var(--green-5); } .Button.green:focus { box-shadow: 0 0 0 2px var(--green-7); } } ``` ## Features - Can be controlled or uncontrolled. - Supports horizontal/vertical orientation. - Supports automatic/manual activation. - Full keyboard navigation. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the tabs component parts. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `activationMode` | `"automatic"` | `"automatic" \| "manual"` | Whether a tab is activated automatically (on focus) or manually (on click). | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `T` | The value of the tab that should be active when initially rendered. Use when you do not need to control the state of the tabs | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `modelValue` | | `T` | The controlled value of the tab to activate. Can be bind as `v-model`. | | `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation the tabs are laid out.
Mainly so arrow navigation is done accordingly (left & right vs. up & down) | | `unmountOnHide` | `true` | `boolean` | When `true`, the element will be unmounted on closed state. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: T` | Event handler called when the value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `T` | Current input values | [TabsRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tabs/TabsRoot.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ### List Contains the triggers that are aligned along the edge of the active content. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `loop` | `true` | `boolean` | When `true`, keyboard navigation will loop from last tab to first, and vice versa. | [TabsList.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tabs/TabsList.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Trigger The button that activates its associated content. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the tab. | | `value*` | | `string \| number` | A unique value that associates the trigger with a content. | [TabsTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tabs/TabsTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "active" \\| "inactive" | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Indicator The indicator that highlights the current active tab. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | **Methods** | Method | Type | Description | | --- | --- | --- | | `updateIndicatorStyle` | `() => void` | | [TabsIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tabs/TabsIndicator.vue) | CSS variable | Description | | --- | --- | | `--akar-tabs-indicator-size` | The size of the indicator. | | `--akar-tabs-indicator-thickness` | The thickness of the indicator. | | `--akar-tabs-indicator-position` | The position of the indicator | ### Content Contains the content associated with each trigger. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `value*` | | `string \| number` | A unique value that associates the content with a trigger. | [TabsContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tabs/TabsContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "active" \\| "inactive" | | `[data-orientation]` | "vertical" \\| "horizontal" | ## Examples ### Vertical You can create vertical tabs by using the `orientation` prop. ```vue ``` ## Accessibility Adheres to the [Tabs WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel). ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the tabs, focuses the active trigger. When a trigger is focused, moves focus to the active content. | | ArrowDown | Moves focus to the next trigger depending on `orientation` and activates its associated content. | | ArrowRight | Moves focus to the next trigger depending on `orientation` and activates its associated content. | | ArrowUp | Moves focus to the previous trigger depending on `orientation` and activates its associated content. | | ArrowLeft | Moves focus to the previous trigger depending on `orientation` and activates its associated content. | | Home | Moves focus to the first trigger and activates its associated content. | | End | Moves focus to the last trigger and activates its associated content. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tabs) - [npm](https://www.npmjs.com/package/akar) # Tag Group > A focusable list of tags that can be navigated, selected and removed with the keyboard. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-TagGroup) { /* reset */ button { all: unset; } } ``` ## Features - Full keyboard navigation, including typeahead. - Supports no, single or multiple selection. - Removable with the keyboard or a delete button. - Keeps focus on a neighbouring tag after removal. - Can be controlled or uncontrolled. - Labelled and described by an ancestor Field. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the tags. Renders a `grid`, or a `group` when there are no tags. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `by` | | `string \| ((a: T, b: T) => boolean)` | Use this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared. | | `defaultValue` | | `T \| T[]` | The value of the selected tag(s) when initially rendered. Use when you do not need to control the selection. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the tag group when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the tag group and all its tags. | | `disallowEmptySelection` | | `boolean` | When `true`, the user cannot deselect the last selected tag. | | `escapeKeyBehavior` | `"clearSelection"` | `"none" \| "clearSelection"` | Whether pressing Escape clears the selection. | | `loop` | `true` | `boolean` | When `true`, keyboard navigation will loop from last tag to first, and vice versa. | | `modelValue` | | `T \| T[]` | The controlled value of the selected tag(s). Can be binded with `v-model`. An array when `selectionMode` is `multiple`. | | `selectionMode` | `"none"` | `"single" \| "multiple" \| "none"` | The type of selection that is allowed. Tags are not selectable when `none`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `remove` | `values: T[]` | Event handler called when the user removes tags, with the values to remove.
Tags are only removable when this event has a listener; remove the values from your own list to remove the tags. | | `update:modelValue` | `value: T \| T[]` | Event handler called when the selection changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `T \| T[]` | Current selected value(s) | [TagGroupRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagGroup/TagGroupRoot.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-empty]` | Present when there are no tags | ### Item A tag. Pressing `Delete` or `Backspace` on it removes it. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the tag. | | `textValue` | | `string` | A string representation of the tag's contents, used for typeahead and as the tag's accessible name. Defaults to the text of `TagGroupItemText`. | | `value*` | | `T` | The unique value of the tag. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `selected` | `boolean` | Whether the tag is selected | | `disabled` | `boolean` | Whether the tag is disabled | [TagGroupItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagGroup/TagGroupItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "checked" \\| "unchecked" | | `[data-disabled]` | Present when disabled | ### ItemText The text of the tag. Used for typeahead unless the item has a `textValue`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [TagGroupItemText.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagGroup/TagGroupItemText.vue) ### ItemDelete The button that removes its tag. It is labelled "Remove" followed by the tag's name; pass an `aria-label` to translate it. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the delete button. | [TagGroupItemDelete.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagGroup/TagGroupItemDelete.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ## Examples ### Removing tags Tags are removable when you listen to the `remove` event. It receives the values to remove, which you remove from your own list. Removing a selected tag with the keyboard removes every selected tag. ```vue ``` ### Selection Set `selectionMode` to `single` or `multiple` to make tags selectable with a click, `Space` or `Enter`. `v-model` holds the selected value, or an array of values when `multiple`. ```vue ``` ### Empty state When there are no tags, the root renders as a focusable `group` with a `data-empty` attribute. Render any empty content inside it. ```vue ``` ### With a label and description Place the root in a `FieldRoot` to label and describe it. ```vue ``` ## Accessibility Adheres to the [Grid WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/), with each tag a `row`. When using `asChild` on `TagGroupItem`, wrap the tag's content in an element with `role="gridcell"`. ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | Moves focus into the tag group, to the focused tag's delete button, then out of the tag group. | | ArrowRight / ArrowDown | Moves focus to the next tag. | | ArrowLeft / ArrowUp | Moves focus to the previous tag. | | Home / End | Moves focus to the first or last tag. | | Space / Enter | When selectable, toggles the focused tag's selection. | | Delete / Backspace | Removes the focused tag, or every selected tag when the focused tag is selected. | | Escape | Clears the selection. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagGroup) - [npm](https://www.npmjs.com/package/akar) # Tags Input > Tags input render tags inside an input, followed by an actual text input. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/green.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-TagsInput) { /* reset */ button, fieldset, input { all: unset; } } ``` ## Features - Can be controlled or uncontrolled. - Full keyboard navigation. - Limit the number of tags. - Accept value from clipboard. - Clear button to reset all tags values. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the tags input component parts. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `addOnBlur` | | `boolean` | When `true` allow adding tags blur input | | `addOnPaste` | | `boolean` | When `true`, allow adding tags on paste. Work in conjunction with delimiter prop. | | `addOnTab` | | `boolean` | When `true` allow adding tags on tab keydown | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `convertValue` | | `((value: string) => T)` | Convert the input value to the desired type. Mandatory when using objects as values and using `TagsInputInput` | | `defaultValue` | `[]` | `T[]` | The value of the tags that should be added. Use when you do not need to control the state of the tags input | | `delimiter` | `","` | `string \| RegExp` | The character or regular expression to trigger the addition of a new tag. Also used to split tags for `@paste` event | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the tags input. | | `displayValue` | `value.toString()` | `((value: T) => string)` | Display the value of the tag. Useful when you want to apply modifications to the value like adding a suffix or when using object as values | | `duplicate` | | `boolean` | When `true`, allow duplicated tags. | | `id` | | `string` | | | `max` | `0` | `number` | Maximum number of tags. | | `modelValue` | | `T[] \| null` | The controlled value of the tags input. Can be bind as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | **Events** | Event | Payload | Description | | --- | --- | --- | | `addTag` | `payload: T` | Event handler called when tag is added | | `invalid` | `payload: T` | Event handler called when the value is invalid | | `removeTag` | `payload: T` | Event handler called when tag is removed | | `update:modelValue` | `payload: T[]` | Event handler called when the value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `string \| number \| bigint \| Record` | Current input values | [TagsInputRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagsInput/TagsInputRoot.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-focused]` | Present when focus on input | | `[data-invalid]` | Present when input value is invalid | ### Item The component that contains the tag. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the tags input. | | `value*` | | `string \| number \| bigint \| Record` | Value associated with the tags | [TagsInputItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagsInput/TagsInputItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "active" \\| "inactive" | | `[data-disabled]` | Present when disabled | ### ItemText The textual part of the tag. Important for accessibility. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [TagsInputItemText.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagsInput/TagsInputItemText.vue) ### ItemDelete The button that delete the associate tag. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [TagsInputItemDelete.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagsInput/TagsInputItemDelete.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "active" \\| "inactive" | | `[data-disabled]` | Present when disabled | ### Input The input element for the tags input. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `autoFocus` | | `boolean` | Focus on element when mounted. | | `maxLength` | | `number` | Maximum number of character allowed. | | `placeholder` | | `string` | The placeholder character to use for empty tags input. | [TagsInputInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagsInput/TagsInputInput.vue) | Data attribute | Value | | --- | --- | | `[data-invalid]` | Present when input value is invalid | ### Clear The button that remove all tags. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [TagsInputClear.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagsInput/TagsInputClear.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ## Examples ### Paste behavior You can automatically add tags on paste by passing the `add-on-paste` prop. ```vue ``` ### Multiple delimiters You can pass `RegExp` as `delimiter` to allow multiple characters to trigger addition of a new tag. When `add-on-paste` is passed it will be also used to split tags for `@paste` event. ```vue ``` ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Delete | When tag is active, remove it and set the tag on right active. | | Backspace | When tag is active, remove it and set the tag on left active. If there are no tags to the left, either the next tags gets focus, or the input. | | ArrowRight | Set the next tag active. | | ArrowLeft | Set the previous tag active. | | Home | Set the first tag active | | End | Set the last tag active | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TagsInput) - [npm](https://www.npmjs.com/package/akar) # Time Field > Enables users to input specific times within a designated field. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-TimeField) { .TimeFieldWrapper { display: flex; flex-direction: column; gap: 0.5rem; } .TimeFieldLabel { font-size: 0.875rem; line-height: 1.25rem; color: var(--gray-9); } .TimeField { display: flex; padding: 0.5rem; align-items: center; border-radius: 0.25rem; border-width: 1px; text-align: center; background-color: #ffffff; user-select: none; color: var(--green-10); border: 1px solid var(--gray-9); } .TimeField::placeholder { color: var(--mauve-5); } .TimeField[data-invalid] { border: 1px solid var(--red-500); } .TimeFieldLiteral { padding: 0.25rem; } .TimeFieldSegment { padding: 0.25rem; } .TimeFieldSegment:hover { background-color: var(--grass-4); } .TimeFieldSegment:focus { background-color: var(--grass-2); } .TimeFieldSegment:[aria-valuetext='Empty'] { color: var(--grass-6); } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Highly composable - Accessible by default ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a time field **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `defaultPlaceholder` | | `TimeValue` | The default placeholder date | | `defaultValue` | | `TimeValue` | The default value for the calendar | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the time field when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | Whether or not the time field is disabled | | `granularity` | | `"hour" \| "minute" \| "second"` | The granularity to use for formatting times. Defaults to minute if a Time is provided, otherwise defaults to minute. The field will render segments for each part of the date up to and including the specified granularity | | `hideTimeZone` | | `boolean` | Whether or not to hide the time zone segment of the field | | `hourCycle` | | `12 \| 24` | The hour cycle used for formatting times. Defaults to the local preference | | `id` | | `string` | Id of the element | | `locale` | | `string` | The locale to use for formatting dates | | `maxValue` | | `TimeValue` | The maximum date that can be selected | | `minValue` | | `TimeValue` | The minimum date that can be selected | | `modelValue` | | `TimeValue \| null` | The controlled checked state of the field. Can be bound as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `placeholder` | | `TimeValue` | The placeholder date, which is used to determine what time to display when no time is selected. This updates as the user navigates the field | | `readonly` | `false` | `boolean` | Whether or not the time field is readonly | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | | `DateStep` | The stepping interval for the time fields. Defaults to `1`. | | `stepSnapping` | `false` | `boolean` | Whether to enforce snapping the value to the nearest step increment after input. Defaults to `false`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: TimeValue` | Event handler called whenever the model value changes | | `update:placeholder` | `date: TimeValue` | Event handler called whenever the placeholder value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `TimeValue` | The current time of the field | | `segments` | `{ part: SegmentPart; value: string; }[]` | The time field segment contents | | `isInvalid` | `boolean` | Value if the input is invalid | **Methods** | Method | Type | Description | | --- | --- | --- | | `setFocusedElement` | `(el: HTMLElement) => void` | Helper to set the focused element inside the DateField | [TimeFieldRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TimeField/TimeFieldRoot.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Input Contains the time field segments **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `part*` | | `"day" \| "month" \| "year" \| "hour" \| "minute" \| "second" \| "dayPeriod" \| "literal" \| "timeZoneName"` | The part of the date to render | [TimeFieldInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TimeField/TimeFieldInput.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-placeholder]` | Present when no value is set | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the time field, focuses the first segment. | | ArrowLeft / ArrowRight | Navigates between the time field segments. | | ArrowUp / ArrowDown | Increments/changes the value of the segment. | | 0-9 | When the focus is on a numeric `TimeFieldInput`, it types in the number and focuses the next segment if the next input would result in an invalid value. | | Backspace | Deletes a digit from the focused numeric segments. | | A / P | When the focus is on the day period, it sets it to AM or PM. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TimeField) - [npm](https://www.npmjs.com/package/akar) # Time Range Field > Allows users to input a range of times within a designated field. `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-TimeRangeField) { .TimeFieldWrapper { display: flex; flex-direction: column; gap: 0.5rem; } .TimeFieldLabel { font-size: 0.875rem; line-height: 1.25rem; color: var(--gray-9); } .TimeField { display: flex; padding: 0.5rem; align-items: center; border-radius: 0.25rem; text-align: center; background-color: #fff; user-select: none; color: var(--green-10); border: 1px solid var(--gray-9); } .TimeField::placeholder { color: var(--mauve-5); } .TimeField[data-invalid] { border: 1px solid var(--red-500); } .TimeFieldLiteral { padding: 0.25rem; } .TimeFieldSegment { padding: 0.25rem; } .TimeFieldSegment:hover{ background-color: var(--grass-4); } .TimeFieldSegment:focus { background-color: var(--grass-2); } .TimeFieldSegment[aria-valuetext='Empty'] { color: var(--grass-6); } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Highly composable - Accessible by default - Supports various time formats - Time range validation - Configurable granularity ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the time-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a time range field. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `defaultPlaceholder` | | `TimeValue` | The default placeholder time | | `defaultValue` | | `TimeRange` | The default value for the field | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the time field when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | Whether or not the time field is disabled | | `granularity` | | `"hour" \| "minute" \| "second"` | The granularity to use for formatting times. Defaults to minute. The field will render segments for each part of the time up to and including the specified granularity | | `hideTimeZone` | | `boolean` | Whether or not to hide the time zone segment of the field | | `hourCycle` | | `12 \| 24` | The hour cycle used for formatting times. Defaults to the local preference | | `id` | | `string` | Id of the element | | `isTimeUnavailable` | | `Matcher` | A function that returns whether or not a time is unavailable | | `locale` | | `string` | The locale to use for formatting times | | `maxValue` | | `TimeValue` | The maximum time that can be selected | | `minValue` | | `TimeValue` | The minimum time that can be selected | | `modelValue` | | `TimeRange \| null` | The controlled checked state of the field. Can be bound as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `placeholder` | | `TimeValue` | The placeholder time, which is used to determine what time to display when no time is selected. This updates as the user navigates the field | | `readonly` | `false` | `boolean` | Whether or not the time field is readonly | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `step` | | `DateStep` | The stepping interval for the time fields. Defaults to `1`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: TimeRange` | Event handler called whenever the model value changes | | `update:placeholder` | `date: TimeValue` | Event handler called whenever the placeholder value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `TimeRange` | The current time of the field | | `segments` | `{ start: { part: SegmentPart; value: string; }[]; end: { part: SegmentPart; value: string; }[]; }` | The time field segment contents | | `isInvalid` | `boolean` | Value if the input is invalid | **Methods** | Method | Type | Description | | --- | --- | --- | | `setFocusedElement` | `(el: HTMLElement) => void` | Helper to set the focused element inside the TimeRangeField | [TimeRangeFieldRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Input Contains the time field segments. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `part*` | | `"day" \| "month" \| "year" \| "hour" \| "minute" \| "second" \| "dayPeriod" \| "literal" \| "timeZoneName"` | The part of the date to render | | `type*` | | `"start" \| "end"` | The type of field to render (start or end) | [TimeRangeFieldInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TimeRangeField/TimeRangeFieldInput.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-placeholder]` | Present when no value is set | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the time field, focuses the first segment. | | ArrowLeft / ArrowRight | Navigates between the time field segments. | | ArrowUp / ArrowDown | Increments/changes the value of the segment. | | 0-9 | When the focus is on a numeric `TimeRangeFieldInput`, it types in the number and focuses the next segment if the next input would result in an invalid value. | | Backspace | Deletes a digit from the focused numeric segments. | | A / P | When the focus is on the day period, it sets it to AM or PM. | ## Usage Examples ### Basic Usage ```vue ``` ### Controlled Component ```vue ``` ### With Validation ```vue ``` ### With Different Granularity ```vue ``` ### With Locale and Hour Cycle ```vue ``` ### With Min and Max Values ```vue ``` ### With Step Increment ```vue ``` ### Disabled State ```vue ``` ### Read-only State ```vue ``` ### Advanced Keyboard Navigation The TimeRangeField provides intuitive keyboard navigation for efficient time input. Users can seamlessly move between time segments, increment or decrement values, and type numbers directly. ```vue ``` ### Form Integration Integrate TimeRangeField with HTML forms to handle submissions and validation. ```vue ``` ### Custom Styling Customize the appearance of the TimeRangeField using CSS classes or Tailwind utilities. ```vue ``` ### Advanced Validation Implement complex validation rules, such as ensuring the end time is after the start time and within business hours. ```vue ``` ### Accessibility Features The TimeRangeField is built with accessibility in mind. Enhance it further with ARIA labels and descriptions for screen readers. ```vue ``` ### Real-world Use Cases Use TimeRangeField in practical scenarios like scheduling appointments or booking resources. ```vue ``` --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/TimeRangeField) - [npm](https://www.npmjs.com/package/akar) # Toast > A succinct message that is displayed temporarily. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/green.css'; @import '../_colors/mauve.css'; @import '../_colors/slate.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Toast) { /* reset */ button { all: unset; } .ToastViewport { --viewport-padding: 25px; position: fixed; bottom: 0; right: 0; display: flex; flex-direction: column; padding: var(--viewport-padding); gap: 10px; width: 390px; max-width: 100vw; margin: 0; list-style: none; z-index: 2147483647; outline: none; } .ToastRoot { background-color: white; border-radius: 6px; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; padding: 15px; display: grid; grid-template-areas: 'title action' 'description action'; grid-template-columns: auto max-content; column-gap: 15px; align-items: center; } .ToastRoot[data-state='open'] { animation: slideIn 150ms cubic-bezier(0.16, 1, 0.3, 1); } .ToastRoot[data-state='closed'] { animation: hide 100ms ease-in; } .ToastRoot[data-swipe='move'] { transform: translateX(var(--akar-toast-swipe-move-x)); } .ToastRoot[data-swipe='cancel'] { transform: translateX(0); transition: transform 200ms ease-out; } .ToastRoot[data-swipe='end'] { animation: swipeOut 100ms ease-out; } @keyframes hide { from { opacity: 1; } to { opacity: 0; } } @keyframes slideIn { from { transform: translateX(calc(100% + var(--viewport-padding))); } to { transform: translateX(0); } } @keyframes swipeOut { from { transform: translateX(var(--akar-toast-swipe-end-x)); } to { transform: translateX(calc(100% + var(--viewport-padding))); } } .ToastTitle { grid-area: title; margin-bottom: 5px; font-weight: 500; color: var(--slate-12); font-size: 15px; } .ToastDescription { grid-area: description; margin: 0; color: var(--slate-11); font-size: 13px; line-height: 1.3; } .ToastAction { grid-area: action; } .Button { display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; font-weight: 500; } .Button.small { font-size: 12px; padding: 0 10px; line-height: 25px; height: 25px; } .Button.large { font-size: 15px; padding: 0 15px; line-height: 35px; height: 35px; } .Button.grass { background-color: white; color: var(--grass-11); box-shadow: 0 2px 10px var(--black-a7); } .Button.grass:hover { background-color: var(--mauve-3); } .Button.grass:focus { box-shadow: 0 0 0 2px black; } .Button.green { background-color: var(--green-2); color: var(--green-11); box-shadow: inset 0 0 0 1px var(--green-7); } .Button.green:hover { box-shadow: inset 0 0 0 1px var(--green-8); } .Button.green:focus { box-shadow: 0 0 0 2px var(--green-8); } } ``` - Automatically closes. - Pauses closing on hover, focus and window blur. - Supports hotkey to jump to toast viewport. - Supports closing via swipe gesture. - Exposes CSS variables for swipe gesture animations. - Can be controlled or uncontrolled. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import the component. ```vue ``` ## API Reference ### Provider The provider that wraps your toasts and toast viewport. It usually wraps the application. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `disableSwipe` | `false` | `boolean` | Whether to disable the ability to swipe to close the toast. | | `duration` | `5000` | `number` | Time in milliseconds that each toast should remain visible for. | | `label` | `"Notification"` | `string` | An author-localized label for each toast. Used to help screen reader users
associate the interruption with a toast. | | `swipeDirection` | `"right"` | `"right" \| "left" \| "down" \| "up"` | Direction of pointer swipe that should close the toast. | | `swipeThreshold` | `50` | `number` | Distance in pixels that the swipe must pass before a close is triggered. | [ToastProvider.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toast/ToastProvider.vue) ### Viewport The fixed area where toasts appear. Users can jump to the viewport by pressing a hotkey. It is up to you to ensure the discoverability of the hotkey for keyboard users. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"ol"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `hotkey` | `["F8"]` | `string[]` | The keys to use as the keyboard shortcut that will move focus to the toast viewport. | | `label` | `"Notifications ({hotkey})"` | `string \| ((hotkey: string) => string)` | An author-localized label for the toast viewport to provide context for screen reader users
when navigating page landmarks. The available `{hotkey}` placeholder will be replaced for you.
Alternatively, you can pass in a custom function to generate the label. | [ToastViewport.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toast/ToastViewport.vue) ### Root The toast that automatically closes. It should not be held open to [acquire a user response](https://vinicunca.dev/akar/components/toast#action). > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"li"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultOpen` | `true` | `boolean` | The open state of the dialog when it is initially rendered. Use when you do not need to control its open state. | | `duration` | | `number` | Time in milliseconds that toast should remain visible for. Overrides value
given to `ToastProvider`. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `open` | | `boolean` | The controlled open state of the dialog. Can be bind as `v-model:open`. | | `type` | `"foreground"` | `"foreground" \| "background"` | Control the sensitivity of the toast for accessibility purposes.

For toasts that are the result of a user action, choose `foreground`. Toasts generated from background tasks should use `background`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. | | `pause` | | Event handler called when the dismiss timer is paused. This occurs when the pointer is moved over the viewport, the viewport is focused or when the window is blurred. | | `resume` | | Event handler called when the dismiss timer is resumed. This occurs when the pointer is moved away from the viewport, the viewport is blurred or when the window is focused. | | `swipeCancel` | `event: SwipeEvent` | Event handler called when swipe interaction is cancelled. It can be prevented by calling `event.preventDefault`. | | `swipeEnd` | `event: SwipeEvent` | Event handler called at the end of a swipe interaction. It can be prevented by calling `event.preventDefault`. | | `swipeMove` | `event: SwipeEvent` | Event handler called during a swipe interaction. It can be prevented by calling `event.preventDefault`. | | `swipeStart` | `event: SwipeEvent` | Event handler called when starting a swipe interaction. It can be prevented by calling `event.preventDefault`. | | `update:open` | `value: boolean` | Event handler called when the open state changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | | `remaining` | `number` | Remaining time (in ms) | | `duration` | `number` | Total time the toast will remain visible for (in ms) | [ToastRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toast/ToastRoot.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "open" \\| "closed" | | `[data-swipe]` | "start" \\| "move" \\| "cancel" \\| "end" | | `[data-swipe-direction]` | "up" \\| "down" \\| "left" \\| "right" | | CSS variable | Description | | --- | --- | | `--akar-toast-swipe-move-x` | The offset position of the toast when horizontally swiping | | `--akar-toast-swipe-move-y` | The offset position of the toast when vertically swiping | | `--akar-toast-swipe-end-x` | The offset end position of the toast after horizontally swiping | | `--akar-toast-swipe-end-y` | The offset end position of the toast after vertically swiping | ### Portal When used, portals the content part into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [ToastPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toast/ToastPortal.vue) ### Title An optional title for the toast **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ToastTitle.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toast/ToastTitle.vue) ### Description The toast message. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ToastDescription.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toast/ToastDescription.vue) ### Action An action that is safe to ignore to ensure users are not expected to complete tasks with unexpected side effects as a result of a [time limit](https://www.w3.org/TR/UNDERSTANDING-WCAG20/time-limits-required-behaviors.html). When obtaining a user response is necessary, portal an ["AlertDialog"](https://vinicunca.dev/akar/components/alert-dialog) styled as a toast into the viewport instead. By default, clicking `ToastAction` dismisses the toast. Set `closeOnClick` to `false` when the action should run while keeping the toast visible. ```vue ``` **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `altText*` | | `string` | A short description for an alternate way to carry out the action. For screen reader users
who will not be able to navigate to the button easily/quickly. | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `closeOnClick` | `true` | `boolean` | Whether the action should close the toast when clicked. | [ToastAction.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toast/ToastAction.vue) ### Close A button that allows users to dismiss the toast before its duration has elapsed. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ToastClose.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toast/ToastClose.vue) ## Examples ### Custom hotkey Override the default hotkey using the `event.code` value for each key from [keycode.info](https://keycode.info/). ```vue ``` ### Custom duration Customise the duration of a toast to override the provider value. ```vue ``` ### Duplicate toasts When a toast must appear every time a user clicks a button, use state to render multiple instances of the same toast (see below). Alternatively, you can abstract the parts to create your own [imperative API](https://vinicunca.dev/akar/components/toast#imperative-api). ```vue ``` ### Animating swipe gesture Combine `--akar-toast-swipe-move-[x|y]` and `--akar-toast-swipe-end-[x|y]` CSS variables with `data-swipe="[start|move|cancel|end]"` attributes to animate a swipe to close gesture. Here's an example: ```vue ``` ```css /* styles.css */ .ToastRoot[data-swipe='move'] { transform: translateX(var(--akar-toast-swipe-move-x)); } .ToastRoot[data-swipe='cancel'] { transform: translateX(0); transition: transform 200ms ease-out; } .ToastRoot[data-swipe='end'] { animation: slideRight 100ms ease-out; } @keyframes slideRight { from { transform: translateX(var(--akar-toast-swipe-end-x)); } to { transform: translateX(100%); } } ``` ## Accessibility Adheres to the [`aria-live` requirements](https://www.w3.org/TR/wai-aria/#aria-live). ### Sensitivity Control the sensitivity of the toast for screen readers using the `type` prop. For toasts that are the result of a user action, choose `foreground`. Toasts generated from background tasks should use `background`. #### Foreground Foreground toasts are announced immediately. Assistive technologies may choose to clear previously queued messages when a foreground toast appears. Try to avoid stacking distinct foreground toasts at the same time. #### Background Background toasts are announced at the next graceful opportunity, for example, when the screen reader has finished reading its current sentence. They do not clear queued messages so overusing them can be perceived as a laggy user experience for screen reader users when used in response to a user interaction. ```vue ``` ### Alternative action Use the `altText` prop on the `Action` to instruct an alternative way of actioning the toast to screen reader users. You can direct the user to a permanent place in your application where they can action it or implement your own custom hotkey logic. If implementing the latter, use `foreground` type to announce immediately and increase the duration to give the user ample time. ```vue ``` ### Close icon button When providing an icon (or font icon), remember to label it correctly for screen reader users. ```vue ``` ### Keyboard Interactions | Key | Description | | --- | --- | | F8 | Focuses toasts viewport. | | Tab | Moves focus to the next focusable element. | | Shift + Tab | Moves focus to the previous focusable element. | | Space | When focus is on a `ToastAction`, closes the toast when `closeOnClick` is `true`. When focus is on `ToastClose`, closes the toast. | | Enter | When focus is on a `ToastAction`, closes the toast when `closeOnClick` is `true`. When focus is on `ToastClose`, closes the toast. | | Esc | When focus is on a `Toast`, closes the toast | ## Custom APIs ### Abstract parts Create your own API by abstracting the primitive parts into your own component. #### Usage ```vue ``` #### Implementation ```vue // your-toast.vue ``` ### Imperative API Create your own imperative API to allow [toast duplication](https://vinicunca.dev/akar/components/toast#duplicate-toasts) if preferred. #### Usage ```vue ``` #### Implementation ```vue // your-toast.vue ``` --- - [ARIA](https://www.w3.org/TR/wai-aria/#aria-live) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toast) - [npm](https://www.npmjs.com/package/akar) # Toggle > A two-state button that can be either on or off. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Toggle) { /* reset */ button { all: unset; } .Toggle { background-color: white; color: var(--mauve-11); height: 35px; width: 35px; border-radius: 4px; display: flex; font-size: 15px; line-height: 1; align-items: center; justify-content: center; box-shadow: 0 2px 10px var(--black-a7); } .Toggle:hover { background-color: var(--grass-3); } .Toggle[data-state='on'] { background-color: var(--grass-6); color: var(--grass-12); } .Toggle:focus { box-shadow: 0 0 0 2px black; } } ``` ## Features - Full keyboard navigation. - Can be controlled or uncontrolled. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import the component. ```vue ``` ## API Reference ### Root The toggle. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `boolean` | The pressed state of the toggle when it is initially rendered. Use when you do not need to control its open state. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the toggle. | | `modelValue` | | `boolean \| null` | The controlled pressed state of the toggle. Can be bind as `v-model`. | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `value: boolean` | Event handler called when the value of the toggle changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `boolean` | Current value | | `state` | `"on" \| "off"` | Current state | | `pressed` | `boolean` | Current pressed state | | `disabled` | `boolean` | Current disabled state | [Toggle.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toggle/Toggle.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "on" \\| "off" | | `[data-disabled]` | Present when disabled | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Space | Activates/deactivates the toggle. | | Enter | Activates/deactivates the toggle. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/button) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toggle) - [npm](https://www.npmjs.com/package/akar) # Toggle Group > A set of two-state buttons that can be toggled on or off. ## ToggleGroup ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-ToggleGroup) { /* reset */ button { all: unset; } .ToggleGroup { display: inline-flex; background-color: var(--mauve-6); border-radius: 4px; box-shadow: 0 2px 10px var(--black-a7); } .ToggleGroupItem { background-color: white; color: var(--mauve-11); height: 35px; width: 35px; display: flex; font-size: 15px; line-height: 1; align-items: center; justify-content: center; margin-left: 1px; } .ToggleGroupItem:first-child { margin-left: 0; border-top-left-radius: 4px; border-bottom-left-radius: 4px; } .ToggleGroupItem:last-child { border-top-right-radius: 4px; border-bottom-right-radius: 4px; } .ToggleGroupItem:hover { background-color: var(--grass-3); } .ToggleGroupItem[data-state='on'] { background-color: var(--grass-5); color: var(--grass-11); } .ToggleGroupItem:focus { position: relative; box-shadow: 0 0 0 2px black; } } ``` ## Features - Full keyboard navigation. - Supports horizontal/vertical orientation. - Support single and multiple pressed buttons. - Can be controlled or uncontrolled. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import the component. ```vue ``` ## API Reference ### Root Contains all the parts of a toggle group. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `AcceptableValue \| AcceptableValue[]` | The default active value of the item(s).

Use when you do not need to control the state of the item(s). | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | `false` | `boolean` | When `true`, prevents the user from interacting with the toggle group and all its items. | | `loop` | `true` | `boolean` | When `loop` and `rovingFocus` is `true`, keyboard navigation will loop from last item to first, and vice versa. | | `modelValue` | | `AcceptableValue \| AcceptableValue[]` | The controlled value of the active item(s).

Use this when you need to control the state of the items. Can be binded with `v-model` | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `orientation` | | `"vertical" \| "horizontal"` | The orientation of the component, which determines how focus moves: `horizontal` for left/right arrows and `vertical` for up/down arrows. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `rovingFocus` | `true` | `boolean` | When `false`, navigating through the items using arrow keys will be disabled. | | `type` | | `"single" \| "multiple"` | Determines whether a "single" or "multiple" items can be selected at a time.

This prop will overwrite the inferred type from `modelValue` and `defaultValue`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: AcceptableValue \| AcceptableValue[]` | Event handler called when the value changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `AcceptableValue \| AcceptableValue[]` | Current toggle values | [ToggleGroupRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ToggleGroup/ToggleGroupRoot.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Item An item in the group. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the toggle. | | `value*` | | `AcceptableValue` | A string value for the toggle group item. All items within a toggle group should use a unique value. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `modelValue` | `boolean` | Current value | | `state` | `"on" \| "off"` | Current state | | `pressed` | `boolean` | Current pressed state | | `disabled` | `boolean` | Current disabled state | [ToggleGroupItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ToggleGroup/ToggleGroupItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "on" \\| "off" | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ## Examples ### Ensuring there is always a value You can control the component to ensure a value. ```vue ``` ## Accessibility Uses [roving tabindex](https://www.w3.org/TR/wai-aria-practices-1.2/examples/radio/radio.html) to manage focus movement among items. ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | Moves focus to either the pressed item or the first item in the group. | | Space | Activates/deactivates the item. | | Enter | Activates/deactivates the item. | | ArrowDown | Moves focus to the next item in the group. | | ArrowRight | Moves focus to the next item in the group. | | ArrowUp | Moves focus to the previous item in the group. | | ArrowLeft | Moves focus to the previous item in the group. | | Home | Moves focus to the first item. | | End | Moves focus to the last item. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/button) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ToggleGroup) - [npm](https://www.npmjs.com/package/akar) # Toolbar > A container for grouping a set of controls, such as buttons, toggle groups or dropdown menus. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Toolbar) { /* reset */ a, button { all: unset; } .ToolbarRoot { display: flex; padding: 10px; width: 100%; min-width: max-content; border-radius: 6px; background-color: white; box-shadow: 0 2px 10px var(--black-a7); } .ToolbarToggleItem, .ToolbarLink, .ToolbarButton { flex: 0 0 auto; color: var(--mauve-11); height: 25px; padding: 0 5px; border-radius: 4px; display: inline-flex; font-size: 13px; line-height: 1; align-items: center; justify-content: center; } .ToolbarToggleItem:hover, .ToolbarLink:hover, .ToolbarButton:hover { background-color: var(--grass-3); color: var(--grass-11); } .ToolbarToggleItem:focus, .ToolbarLink:focus, .ToolbarButton:focus { position: relative; box-shadow: 0 0 0 2px var(--grass-7); } .ToolbarToggleItem { background-color: white; margin-left: 2px; } .ToolbarToggleItem:first-child { margin-left: 0; } .ToolbarToggleItem[data-state='on'] { background-color: var(--grass-5); color: var(--grass-11); } .ToolbarSeparator { width: 1px; background-color: var(--mauve-6); margin: 0 10px; } .ToolbarLink { background-color: transparent; color: var(--mauve-11); display: none; justify-content: center; align-items: center; } .ToolbarLink:hover { background-color: transparent; cursor: pointer; } @media (min-width: 520px) { .ToolbarLink { display: inline-flex; } } .ToolbarButton { padding-left: 10px; padding-right: 10px; color: white; background-color: var(--grass-9); } .ToolbarButton:hover { background-color: var(--grass-10); color: white; } } ``` ## Features - Full keyboard navigation. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import the component. ```vue ``` ## API Reference ### Root Contains all the toolbar component parts. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `loop` | | `boolean` | When `true`, keyboard navigation will loop from last tab to first, and vice versa. | | `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation of the toolbar | [ToolbarRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toolbar/ToolbarRoot.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Button A button item. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | | [ToolbarButton.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toolbar/ToolbarButton.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Link A link item. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"a"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ToolbarLink.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toolbar/ToolbarLink.vue) ### ToggleGroup A set of two-state buttons that can be toggled on or off. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `defaultValue` | | `AcceptableValue \| AcceptableValue[]` | The default active value of the item(s).

Use when you do not need to control the state of the item(s). | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the toggle group and all its items. | | `loop` | | `boolean` | When `loop` and `rovingFocus` is `true`, keyboard navigation will loop from last item to first, and vice versa. | | `modelValue` | | `AcceptableValue \| AcceptableValue[]` | The controlled value of the active item(s).

Use this when you need to control the state of the items. Can be binded with `v-model` | | `name` | | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. | | `orientation` | | `"vertical" \| "horizontal"` | The orientation of the component, which determines how focus moves: `horizontal` for left/right arrows and `vertical` for up/down arrows. | | `required` | | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. | | `rovingFocus` | | `boolean` | When `false`, navigating through the items using arrow keys will be disabled. | | `type` | | `"single" \| "multiple"` | Determines whether a "single" or "multiple" items can be selected at a time.

This prop will overwrite the inferred type from `modelValue` and `defaultValue`. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `payload: AcceptableValue \| AcceptableValue[]` | Event handler called when the value changes. | [ToolbarToggleGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toolbar/ToolbarToggleGroup.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ### ToggleItem An item in the group. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the toggle. | | `value*` | | `AcceptableValue` | A string value for the toggle group item. All items within a toggle group should use a unique value. | [ToolbarToggleItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toolbar/ToolbarToggleItem.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "on" \\| "off" | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | "vertical" \\| "horizontal" | ### Separator Used to visually separate items in the toolbar **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | [ToolbarSeparator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toolbar/ToolbarSeparator.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" | ## Examples ### Use with other primitives All our primitives which expose a `Trigger` part, such as `Dialog`, `AlertDialog`, `Popover`, `DropdownMenu` can be composed within a toolbar by using the [`asChild` prop](https://vinicunca.dev/akar/guides/composition). Here is an example using our `DropdownMenu` primitive. ```vue ``` ## Accessibility Uses [roving tabindex](https://www.w3.org/TR/wai-aria-practices-1.2/examples/radio/radio.html) to manage focus movement among items. ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | Moves focus to the first item in the group. | | Space | Activates/deactivates the item. | | Enter | Activates/deactivates the item. | | ArrowDown | Moves focus to the next item depending on `orientation`. | | ArrowRight | Moves focus to the next item depending on `orientation`. | | ArrowUp | Moves focus to the previous item depending on `orientation` . | | ArrowLeft | Moves focus to the previous item depending on `orientation` . | | Home | Moves focus to the first item. | | End | Moves focus to the last item. | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Toolbar) - [npm](https://www.npmjs.com/package/akar) # Tooltip > A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Tooltip) { /* reset */ button { all: unset; } .TooltipContent { border-radius: 4px; padding: 10px 15px; font-size: 15px; line-height: 1; color: var(--grass-11); background-color: white; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; user-select: none; animation-duration: 400ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); will-change: transform, opacity; } .TooltipContent[data-state='delayed-open'][data-side='top'] { animation-name: slideDownAndFade; } .TooltipContent[data-state='delayed-open'][data-side='right'] { animation-name: slideLeftAndFade; } .TooltipContent[data-state='delayed-open'][data-side='bottom'] { animation-name: slideUpAndFade; } .TooltipContent[data-state='delayed-open'][data-side='left'] { animation-name: slideRightAndFade; } .TooltipArrow { fill: white; } .IconButton { font-family: inherit; border-radius: 100%; height: 35px; width: 35px; display: inline-flex; align-items: center; justify-content: center; color: var(--grass-11); background-color: white; box-shadow: 0 2px 10px var(--black-a7); } .IconButton:hover { background-color: var(--grass-3); } .IconButton:focus { box-shadow: 0 0 0 2px black; } @keyframes slideUpAndFade { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideRightAndFade { from { opacity: 0; transform: translateX(-2px); } to { opacity: 1; transform: translateX(0); } } @keyframes slideDownAndFade { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideLeftAndFade { from { opacity: 0; transform: translateX(2px); } to { opacity: 1; transform: translateX(0); } } } ``` ## Features - Provider to control display delay globally. - Opens when the trigger is focused or hovered. - Closes when the trigger is activated or when pressing escape. - Supports custom timings. ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Provider Wraps your app to provide global functionality to your tooltips. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `content` | | `TooltipContentProps` | Default settings that will be used by all tooltip components. | | `delayDuration` | `700` | `number` | The duration from when the pointer enters the trigger until the tooltip gets opened. | | `disableClosingTrigger` | `false` | `boolean` | When `true`, clicking on trigger will not close the content. | | `disabled` | `false` | `boolean` | When `true`, disable tooltip | | `disableHoverableContent` | `false` | `boolean` | When `true`, trying to hover the content will result in the tooltip closing as the pointer leaves the trigger. | | `ignoreNonKeyboardFocus` | `false` | `boolean` | Prevent the tooltip from opening if the focus did not come from
the keyboard by matching against the `:focus-visible` selector.
This is useful if you want to avoid opening it when switching
browser tabs or closing a dialog. | | `skipDelayDuration` | `300` | `number` | How much time a user has to enter another trigger without incurring a delay again. | [TooltipProvider.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tooltip/TooltipProvider.vue) ### Root Contains all the parts of a tooltip. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defaultOpen` | `false` | `boolean` | The open state of the tooltip when it is initially rendered.
Use when you do not need to control its open state. | | `delayDuration` | `700` | `number` | Override the duration given to the `Provider` to customise
the open delay for a specific tooltip. | | `disableClosingTrigger` | `false` | `boolean` | When `true`, clicking on trigger will not close the content. | | `disabled` | `false` | `boolean` | When `true`, disable tooltip | | `disableHoverableContent` | | `boolean` | Prevents Tooltip.Content from remaining open when hovering.
Disabling this has accessibility consequences. Inherits
from Tooltip.Provider. | | `ignoreNonKeyboardFocus` | `false` | `boolean` | Prevent the tooltip from opening if the focus did not come from
the keyboard by matching against the `:focus-visible` selector.
This is useful if you want to avoid opening it when switching
browser tabs or closing a dialog. | | `open` | | `boolean` | The controlled open state of the tooltip. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:open` | `value: boolean` | Event handler called when the open state of the tooltip changes. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `open` | `boolean` | Current open state | [TooltipRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tooltip/TooltipRoot.vue) ### Trigger The button that toggles the tooltip. By default, the `TooltipContent` will position itself against the trigger. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `reference` | | `ReferenceElement` | The reference (or anchor) element that is being referred to for positioning.

If not provided will use the current component as anchor. | [TooltipTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tooltip/TooltipTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "closed" \\| "delayed-open" \\| "instant-open" | ### Portal When used, portals the content part into the `body`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `defer` | | `boolean` | Defer the resolving of a Teleport target until other parts of the
application have mounted (requires Vue 3.5.0+)

[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) | | `disabled` | | `boolean` | Disable teleport and render the component inline

[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `to` | | `string \| HTMLElement` | Vue native teleport component prop `:to`

[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) | [TooltipPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tooltip/TooltipPortal.vue) ### Content The component that pops out when the tooltip is open. > [!NOTE] > > Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.
May change when collisions occur. | | `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. | | `ariaLabel` | `String` | `string` | By default, screenreaders will announce the content inside
the component. If this is not descriptive enough, or you have
content that cannot be announced, use aria-label as a more
descriptive label. | | `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.
If your content has border-radius, this will prevent it from
overflowing the corners. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences
to prevent collisions with boundary edges. | | `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default
this is the viewport, though you can provide additional
element(s) to be included in this check. | | `collisionPadding` | `0` | `number \| Partial>` | The distance in pixels from the boundary edges where collision
detection should occur. Accepts a number (same for all sides),
or a partial padding object, for example: { top: 20, left: 20 }. | | `forceMount` | | `boolean` | Used to force mounting when more control is needed. Useful when
controlling animation with Vue animation libraries. | | `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. | | `positionStrategy` | | `"fixed" \| "absolute"` | The type of CSS position property to use. | | `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.
Will be reversed when collisions occur and avoidCollisions
is enabled. | | `sideOffset` | `0` | `number` | The distance in pixels from the trigger. | | `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the
content in the boundary as long as the trigger is at least partially
in the boundary whilst "always" will keep the content in the boundary
regardless. | | `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. | **Events** | Event | Payload | Description | | --- | --- | --- | | `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when focus moves to the destructive action after opening. It can be prevented by calling `event.preventDefault` | | `pointerDownOutside` | `event: Event` | Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | [TooltipContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tooltip/TooltipContent.vue) | Data attribute | Value | | --- | --- | | `[data-state]` | "closed" \\| "delayed-open" \\| "instant-open" | | `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" | | `[data-align]` | "start" \\| "end" \\| "center" | | CSS variable | Description | | --- | --- | | `--akar-tooltip-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets | | `--akar-tooltip-content-available-width` | The remaining width between the trigger and the boundary edge | | `--akar-tooltip-content-available-height` | The remaining height between the trigger and the boundary edge | | `--akar-tooltip-trigger-width` | The width of the trigger | | `--akar-tooltip-trigger-height` | The height of the trigger | ### Arrow An optional arrow element to render alongside the tooltip. This can be used to help visually link the trigger with the `TooltipContent`. Must be rendered inside `TooltipContent`. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `height` | `5` | `number` | The height of the arrow in pixels. | | `width` | `10` | `number` | The width of the arrow in pixels. | [TooltipArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tooltip/TooltipArrow.vue) ## Examples ### Configure globally Use the `Provider` to control `delayDuration` and `skipDelayDuration` globally. ```vue ``` ### Show instantly Use the `delayDuration` prop to control the time it takes for the tooltip to open. ```vue ``` ### Displaying a tooltip from a disabled button Since disabled buttons don't fire events, you need to: - Render the `Trigger` as `span`. - Ensure the `button` has no `pointerEvents`. ```vue ``` ### Constrain the content size You may want to constrain the width of the content so that it matches the trigger width. You may also want to constrain its height to not exceed the viewport. We expose several CSS custom properties such as `--akar-tooltip-trigger-width` and `--akar-tooltip-content-available-height` to support this. Use them to constrain the content dimensions. ```vue ``` ```css /* styles.css */ .TooltipContent { width: var(--akar-tooltip-trigger-width); max-height: var(--akar-tooltip-content-available-height); } ``` ### Origin-aware animations We expose a CSS custom property `--akar-tooltip-content-transform-origin`. Use it to animate the content from its computed origin based on `side`, `sideOffset`, `align`, `alignOffset` and any collisions. ```vue ``` ```css /* styles.css */ .TooltipContent { transform-origin: var(--akar-tooltip-content-transform-origin); animation: scaleIn 0.5s ease-out; } @keyframes scaleIn { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } } ``` ### Collision-aware animations We expose `data-side` and `data-align` attributes. Their values will change at runtime to reflect collisions. Use them to create collision and direction-aware animations. ```vue ``` ```css /* styles.css */ .TooltipContent { animation-duration: 0.6s; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); } .TooltipContent[data-side="top"] { animation-name: slideUp; } .TooltipContent[data-side="bottom"] { animation-name: slideDown; } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } ``` ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | Opens/closes the tooltip without delay. | | Space | If open, closes the tooltip without delay. | | Enter | If open, closes the tooltip without delay. | | Escape | If open, closes the tooltip without delay. | ## Custom APIs Create your own API by abstracting the primitive parts into your own component. ### Abstract parts and introduce a content prop This example abstracts all of the `Tooltip` parts and introduces a new `content` prop. #### Usage ```vue ``` #### Implementation Use the [`asChild` prop](https://vinicunca.dev/akar/guides/composition) to convert the trigger part into a slottable area. It will replace the trigger with the child that gets passed to it. ```vue ``` --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tooltip) - [npm](https://www.npmjs.com/package/akar) # Tree > A tree view widget displays a hierarchical list of items that can be expanded or collapsed to show or hide their child items, such as in a file system navigator. `````vue [index.vue] ``` ## Features - Can be controlled or uncontrolled. - Focus is fully managed. - Full keyboard navigation. - Supports Right to Left direction. - Supports multiple selection. - Different selection behavior. ## Installation Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a tree. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"ul"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `bubbleSelect` | | `boolean` | When `true`, selecting children will update the parent state. Requires `multiple` to be `true`. | | `defaultExpanded` | | `string[]` | The value of the expanded tree when initially rendered. Use when you do not need to control the state of the expanded tree | | `defaultValue` | | `(M extends true ? U[] : U)` | The value of the tree when initially rendered. Use when you do not need to control the state of the tree | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the listbox when applicable.

If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with tree | | `expanded` | | `string[]` | The controlled value of the expanded item. Can be binded with `v-model`. | | `getChildren` | `val.children` | `((val: T) => T[])` | This function is passed the index of each item and should return a list of children for that item | | `getKey*` | | `(val: T): string` | This function is passed the index of each item and should return a unique key for that item | | `items` | | `T[]` | List of items | | `modelValue` | | `(M extends true ? U[] : U)` | The controlled value of the tree. Can be binded with `v-model`. | | `multiple` | | `boolean \| M` | Whether multiple options can be selected or not. | | `propagateSelect` | | `boolean` | When `true`, selecting parent will select the descendants. Requires `multiple` to be `true`. | | `selectionBehavior` | `"toggle"` | `"replace" \| "toggle"` | How multiple selection should behave in the collection. | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:expanded` | `val: string[]` | | | `update:modelValue` | `val: M extends true ? U[] : U` | | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `flattenItems` | `FlattenedItem[]` | | | `modelValue` | `M extends true ? U[] : U` | | | `expanded` | `string[]` | | [TreeRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tree/TreeRoot.vue) ### Item The item component. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"li"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `disabled` | | `boolean` | When `true`, prevents the user from interacting with the item. | | `level*` | | `number` | Level of depth | | `value*` | | `T` | Value given to this item | **Events** | Event | Payload | Description | | --- | --- | --- | | `select` | `event: SelectEvent` | Event handler called when the selecting item.

It can be prevented by calling `event.preventDefault`. | | `toggle` | `event: ToggleEvent` | Event handler called when the selecting item.

It can be prevented by calling `event.preventDefault`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `isExpanded` | `boolean` | | | `isSelected` | `boolean` | | | `isIndeterminate` | `boolean` | | | `isDisabled` | `boolean` | | | `handleToggle` | `(): void` | | | `handleSelect` | `(): void` | | [TreeItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tree/TreeItem.vue) | Data attribute | Value | | --- | --- | | `[data-indent]` | Number | | `[data-expanded]` | Present when expanded | | `[data-selected]` | Present when selected | ### Virtualizer Virtual container to achieve list virtualization. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `estimateSize` | | `number \| ((index: number) => number)` | Estimated size (in px) of each item | | `overscan` | | `number` | Number of items rendered outside the visible area | | `textContent` | | `((item: Record) => string)` | Text content for each item to achieve type-ahead feature | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `item` | `FlattenedItem>` | | | `virtualizer` | `Virtualizer` | | | `virtualItem` | `VirtualItem` | | [TreeVirtualizer.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tree/TreeVirtualizer.vue) ## Examples ### Selecting multiple items The `Tree` component allows you to select multiple items. You can enable this by providing an array of values instead of a single value and set `multiple="true"`. ```vue ``` ### Virtual List Rendering a long list of item can slow down the app, thus using virtualization would significantly improve the performance. See the [virtualization guide](https://vinicunca.dev/akar/guides/virtualization.md) for more general info on virtualization. ```vue ``` ### With Checkbox Some `Tree` component might want to show `toggled/indeterminate` checkbox. We can change the behavior of the `Tree` component by using a few props and `preventDefault` event. We set `propagateSelect` to `true` because we want the parent checkbox to select/deselect it's descendants. Then, we add a checkbox that triggers `select` event. ```vue ``` ### Nested Tree Node The default example shows flatten tree items and nodes, this enables [Virtualization](https://vinicunca.dev/akar/components/tree.html#virtual-list) and custom feature such as Drag & Drop easier. However, you can also build it to have nested DOM node. In `Tree.vue`, ```vue ``` In `CustomTree.vue` ```vue ``` ### Custom children schema By default, `` expects you to provide the list of node's children by passing a list of `children` for every node. You can override that by providing the `getChildren` prop. > [!NOTE] > > If the node doesn't have any children, `getChildren` should return `undefined` instead of an empty array. ```vue ``` ### Draggable/Sortable Tree For more complex draggable `Tree` component, in this example we will be using [pragmatic-drag-and-drop](https://github.com/atlassian/pragmatic-drag-and-drop), as the core package for handling dnd. [Stackblitz Demo](https://stackblitz.com/edit/github-8f3fzs?file=src%2FTreeDND.vue) ## Accessibility Adheres to the [Tree WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/). ### Keyboard Interactions | Key | Description | | --- | --- | | Enter / Space | When highlight on `TreeItem`, selects the focused item. | | ArrowDown | When focus is on `TreeItem`, moves focus to the next item. | | ArrowUp | When focus is on `TreeItem`, moves focus to the previous item. | | ArrowRight | When focus is on a closed `TreeItem` (node), it opens the node without moving focus. When on an open node, it moves focus to the first child node. When on an end node, it does nothing. | | ArrowLeft | When focus is on an open `TreeItem` (node), closes the node. When focus is on a child node that is also either an end node or a closed node, moves focus to its parent node. When focus is on a root node that is also either an end node or a closed node, does nothing. | | Home / PageUp | Moves focus first `TreeItem` | | End / PageDown | Moves focus last `TreeItem` | --- - [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/) - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Tree) - [npm](https://www.npmjs.com/package/akar) # YearPicker > Presents a calendar view tailored for selecting years. ## Year Picker `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-YearPicker) { .Icon { width: 1rem; height: 1rem; } .YearPicker { margin-top: 1.5rem; border-radius: 0.75rem; border: 1px solid #e5e5e5; background-color: #ffffff; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); padding: 1rem; } .YearPickerHeader { display: flex; justify-content: space-between; align-items: center; } .YearPickerNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2rem; height: 2rem; color: #000000; background-color: transparent; cursor: pointer; border-radius: 0.375rem; } .YearPickerNavButton:hover { background-color: #fafaf9; } .YearPickerNavButton:focus { box-shadow: 0 0 0 2px #000000; } .YearPickerHeading { font-size: 0.875rem; font-weight: 500; color: #000000; } .YearPickerWrapper { padding-top: 1rem; } .YearPickerGrid { width: 100%; user-select: none; } .YearPickerGridWrapper { display: grid; gap: 0.25rem 0; } .YearPickerGridRow { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.25rem; } .YearPickerCell { position: relative; text-align: center; } .YearPickerCellTrigger { position: relative; display: flex; justify-content: center; align-items: center; width: 3rem; height: 3rem; border-radius: 0.5rem; font-size: 0.875rem; font-weight: 400; color: #000000; background-color: transparent; outline: none; cursor: pointer; border: none; } .YearPickerCellTrigger:hover { background-color: var(--grass-5); } .YearPickerCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .YearPickerCellTrigger[data-disabled] { color: rgba(0, 0, 0, 0.3); pointer-events: none; } .YearPickerCellTrigger[data-selected] { background-color: var(--grass-10); color: #ffffff; font-weight: 500; } .YearPickerCellTrigger[data-unavailable] { color: rgba(0, 0, 0, 0.3); text-decoration: line-through; pointer-events: none; } .YearPickerCellTrigger::before { content: ''; position: absolute; top: 0.25rem; width: 0.25rem; height: 0.25rem; border-radius: 9999px; display: none; } .YearPickerCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } .YearPickerCellTrigger[data-selected]::before { background-color: #ffffff; } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Highly composable - Configurable years per page ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a year picker **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `calendarLabel` | | `string` | The accessible label for the year picker | | `defaultPlaceholder` | | `DateValue` | The default placeholder date | | `defaultValue` | | `DateValue` | The default value for the year picker | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the calendar when applicable. If omitted, inherits globally from `ConfigProvider` or assumes LTR. | | `disabled` | `false` | `boolean` | Whether the year picker is disabled | | `initialFocus` | `false` | `boolean` | If true, the year picker will focus the selected year, today, or the first year of the range on mount | | `isYearDisabled` | | `Matcher` | A function that returns whether or not a year is disabled | | `isYearUnavailable` | | `Matcher` | A function that returns whether or not a year is unavailable | | `locale` | | `string` | The locale to use for formatting dates | | `maxValue` | | `DateValue` | The maximum date that can be selected | | `minValue` | | `DateValue` | The minimum date that can be selected | | `modelValue` | | `DateValue \| DateValue[] \| null` | The controlled selected year value of the year picker. Can be bound as `v-model`. | | `multiple` | `false` | `boolean` | Whether multiple years can be selected | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the next page of the year picker. Receives the current placeholder as an argument. | | `placeholder` | | `DateValue` | The placeholder date, which is used to determine what year range to display when no date is selected | | `preventDeselect` | `false` | `boolean` | Whether or not to prevent the user from deselecting a date without selecting another date first | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the previous page of the year picker. Receives the current placeholder as an argument. | | `readonly` | `false` | `boolean` | Whether the year picker is readonly | | `yearsPerPage` | `12` | `number` | Number of years to display per page | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: DateValue \| DateValue[]` | Event handler called whenever the model value changes | | `update:placeholder` | `date: DateValue` | Event handler called whenever the placeholder value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `date` | `DateValue` | The current date of the placeholder | | `grid` | `Grid` | The grid of years | | `locale` | `string` | The year picker locale | | `modelValue` | `DateValue \| DateValue[]` | The current selected value | [YearPickerRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker/YearPickerRoot.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Header Contains the navigation buttons and the heading segments. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [YearPickerHeader.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker/YearPickerHeader.vue) ### Prev Button Calendar navigation button. It navigates the calendar one page (default: 12 years) in the past. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the prev page. Overwrites the `prevPage` function set on the `YearPickerRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [YearPickerPrev.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker/YearPickerPrev.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Next Button Calendar navigation button. It navigates the calendar one page (default: 12 years) in the future. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the next page. Overwrites the `nextPage` function set on the `YearPickerRoot`. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [YearPickerNext.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker/YearPickerNext.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Heading Heading for displaying the current year range (e.g., "2020 - 2031"). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `headingValue` | `string` | Current year range heading | [YearPickerHeading.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker/YearPickerHeading.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Grid Container for wrapping the year picker grid. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"table"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [YearPickerGrid.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker/YearPickerGrid.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | ### Grid Body Container for wrapping the grid body. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tbody"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [YearPickerGridBody.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker/YearPickerGridBody.vue) ### Grid Row Container for wrapping the grid row. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tr"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [YearPickerGridRow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker/YearPickerGridRow.vue) ### Cell Container for wrapping the year picker cells. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"td"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `date*` | | `DateValue` | The date value for the cell | [YearPickerCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker/YearPickerCell.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Cell Trigger Interactable container for displaying the cell years. Clicking it selects the year. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `year*` | | `DateValue` | The date value provided to the cell trigger | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `yearValue` | `string` | Current year value | | `disabled` | `boolean` | Current disable state | | `selected` | `boolean` | Current selected state | | `today` | `boolean` | Current year is today state | | `unavailable` | `boolean` | Current unavailable state | [YearPickerCellTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker/YearPickerCellTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-selected]` | Present when selected | | `[data-value]` | The ISO string value of the date. | | `[data-disabled]` | Present when disabled | | `[data-unavailable]` | Present when unavailable | | `[data-today]` | Present when the year is the current year | | `[data-focused]` | Present when focused | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the year picker, focuses the first navigation button. | | Space | When the focus is on either `YearPickerNext` or `YearPickerPrev`, it navigates the calendar. Otherwise, it selects the year. | | Enter | When the focus is on either `YearPickerNext` or `YearPickerPrev`, it navigates the calendar. Otherwise, it selects the year. | | ArrowLeft / ArrowRight / ArrowUp / ArrowDown | When the focus is on `YearPickerCellTrigger`, it navigates the years, changing the page if necessary. | | PageUp | When the focus is on `YearPickerCellTrigger`, it navigates to the previous page of years. | | PageDown | When the focus is on `YearPickerCellTrigger`, it navigates to the next page of years. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearPicker) - [npm](https://www.npmjs.com/package/akar) # YearRangePicker > Presents a calendar view tailored for selecting year ranges. ## Year Range Picker `````vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/grass.css'; @scope (.akar-demo-YearRangePicker) { .Icon { width: 1rem; height: 1rem; } .YearRangePicker { margin-top: 1.5rem; border-radius: 0.75rem; border: 1px solid #e5e5e5; background-color: #ffffff; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); padding: 1rem; } .YearRangePickerHeader { display: flex; justify-content: space-between; align-items: center; } .YearRangePickerNavButton { display: inline-flex; justify-content: center; align-items: center; width: 2rem; height: 2rem; color: #000000; background-color: transparent; cursor: pointer; border-radius: 0.375rem; } .YearRangePickerNavButton:hover { background-color: #fafaf9; } .YearRangePickerNavButton:focus { box-shadow: 0 0 0 2px #000000; } .YearRangePickerHeading { font-size: 0.875rem; font-weight: 500; color: #000000; } .YearRangePickerWrapper { padding-top: 1rem; } .YearRangePickerGrid { width: 100%; user-select: none; } .YearRangePickerGridWrapper { display: grid; gap: 0.25rem 0; } .YearRangePickerGridRow { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.25rem; } .YearRangePickerCell { position: relative; text-align: center; } .YearRangePickerCellTrigger { position: relative; display: flex; justify-content: center; align-items: center; width: 3rem; height: 3rem; border-radius: 0.5rem; font-size: 0.875rem; font-weight: 400; color: #000000; background-color: transparent; outline: none; cursor: pointer; border: none; } .YearRangePickerCellTrigger:hover { background-color: var(--grass-5); } .YearRangePickerCellTrigger:focus { box-shadow: 0 0 0 2px #000000; } .YearRangePickerCellTrigger[data-disabled] { color: rgba(0, 0, 0, 0.3); pointer-events: none; } .YearRangePickerCellTrigger[data-selected] { background-color: var(--grass-10); color: #ffffff; font-weight: 500; } .YearRangePickerCellTrigger[data-highlighted] { background-color: var(--grass-5); } .YearRangePickerCellTrigger[data-unavailable] { color: rgba(0, 0, 0, 0.3); text-decoration: line-through; pointer-events: none; } .YearRangePickerCellTrigger::before { content: ''; position: absolute; top: 0.25rem; width: 0.25rem; height: 0.25rem; border-radius: 9999px; display: none; } .YearRangePickerCellTrigger[data-today]::before { display: block; background-color: var(--grass-9); } .YearRangePickerCellTrigger[data-selected]::before { background-color: #ffffff; } } ``` ## Features - Full keyboard navigation - Can be controlled or uncontrolled - Focus is fully managed - Localization support - Highly composable ## Preface The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ## Installation Install the date package. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Root Contains all the parts of a year range picker **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `allowNonContiguousRanges` | `false` | `boolean` | When combined with `isYearUnavailable`, determines whether non-contiguous ranges may be selected. | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `calendarLabel` | | `string` | The accessible label for the calendar | | `defaultPlaceholder` | | `DateValue` | The default placeholder date | | `defaultValue` | `{ start: undefined, end: undefined }` | `DateRange` | The default value for the calendar | | `dir` | | `"ltr" \| "rtl"` | The reading direction of the calendar when applicable. | | `disabled` | `false` | `boolean` | Whether or not the calendar is disabled | | `fixedDate` | | `"start" \| "end"` | Which part of the range should be fixed | | `initialFocus` | `false` | `boolean` | If true, the calendar will focus the selected year on mount | | `isYearDisabled` | | `Matcher` | A function that returns whether or not a year is disabled | | `isYearUnavailable` | | `Matcher` | A function that returns whether or not a year is unavailable | | `locale` | | `string` | The locale to use for formatting dates | | `maximumYears` | | `number` | The maximum number of years that can be selected in a range | | `maxValue` | | `DateValue` | The maximum date that can be selected | | `minValue` | | `DateValue` | The minimum date that can be selected | | `modelValue` | | `DateRange \| null` | The controlled selected year range of the year range picker. Can be bound as `v-model`. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the next page of the calendar. | | `placeholder` | | `DateValue` | The placeholder date, which is used to determine what year range to display when no date is selected. | | `preventDeselect` | `false` | `boolean` | Whether or not to prevent the user from deselecting a date without selecting another date first | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | A function that returns the previous page of the calendar. | | `readonly` | `false` | `boolean` | Whether or not the calendar is readonly | | `yearsPerPage` | `12` | `number` | Number of years to display per page | **Events** | Event | Payload | Description | | --- | --- | --- | | `update:modelValue` | `date: DateRange` | Event handler called whenever the model value changes | | `update:placeholder` | `date: DateValue` | Event handler called whenever the placeholder value changes | | `update:startValue` | `date: DateValue` | Event handler called whenever the start value changes | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `date` | `DateValue` | The current date of the placeholder | | `grid` | `Grid` | The grid of years | | `locale` | `string` | The calendar locale | | `modelValue` | `DateRange` | The current date range | [YearRangePickerRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker/YearRangePickerRoot.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | ### Header Contains the navigation buttons and the heading segments. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [YearRangePickerHeader.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker/YearRangePickerHeader.vue) ### Prev Button Calendar navigation button. It navigates the calendar one page (12 years by default) in the past. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `prevPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the prev page. Overwrites the `prevPage` function set on the Root. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [YearRangePickerPrev.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker/YearRangePickerPrev.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Next Button Calendar navigation button. It navigates the calendar one page (12 years by default) in the future. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `nextPage` | | `((placeholder: DateValue) => DateValue)` | The function to be used for the next page. Overwrites the `nextPage` function set on the Root. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `disabled` | `boolean` | Current disable state | [YearRangePickerNext.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker/YearRangePickerNext.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Heading Heading for displaying the current year range. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `headingValue` | `string` | Current year range heading | [YearRangePickerHeading.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker/YearRangePickerHeading.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Grid Container for wrapping the year range picker grid. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"table"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [YearRangePickerGrid.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker/YearRangePickerGrid.vue) | Data attribute | Value | | --- | --- | | `[data-readonly]` | Present when readonly | | `[data-disabled]` | Present when disabled | ### Grid Body Container for wrapping the grid body. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tbody"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [YearRangePickerGridBody.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker/YearRangePickerGridBody.vue) ### Grid Row Container for wrapping the grid row. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"tr"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | [YearRangePickerGridRow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker/YearRangePickerGridRow.vue) ### Cell Container for wrapping the year range picker cells. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"td"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `date*` | | `DateValue` | The date value for the cell | [YearRangePickerCell.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker/YearRangePickerCell.vue) | Data attribute | Value | | --- | --- | | `[data-disabled]` | Present when disabled | ### Cell Trigger Interactable container for displaying the cell years. Clicking it selects the year. **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](/akar/guides/composition) guide for more details. | | `year*` | | `DateValue` | The date value provided to the cell trigger | **Slots** | Slot | Payload | Description | | --- | --- | --- | | `yearValue` | `string` | Current year value | | `disabled` | `boolean` | Current disable state | | `selected` | `boolean` | Current selected state | | `today` | `boolean` | Current year is today's year state | | `unavailable` | `boolean` | Current unavailable state | | `highlighted` | `boolean` | Current highlighted state | | `highlightedStart` | `boolean` | Current highlighted start state | | `highlightedEnd` | `boolean` | Current highlighted end state | | `selectionStart` | `boolean` | Current selection start state | | `selectionEnd` | `boolean` | Current selection end state | [YearRangePickerCellTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker/YearRangePickerCellTrigger.vue) | Data attribute | Value | | --- | --- | | `[data-selected]` | Present when selected | | `[data-value]` | The ISO string value of the date. | | `[data-disabled]` | Present when disabled | | `[data-unavailable]` | Present when unavailable | | `[data-today]` | Present when the year is the current year | | `[data-selection-start]` | Present when the year is the start of the selection. | | `[data-selection-end]` | Present when the year is the end of the selection. | | `[data-highlighted]` | Present when the year is highlighted by the user as they select a range. | | `[data-highlighted-start]` | Present when the year is the start of the range that is highlighted by the user. | | `[data-highlighted-end]` | Present when the year is the end of the range that is highlighted by the user. | | `[data-focused]` | Present when focused | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | Tab | When focus moves onto the year range picker, focuses the first navigation button. | | Space | When the focus is on either `YearRangePickerNext` or `YearRangePickerPrev`, it navigates the calendar. Otherwise, it selects the year. | | Enter | When the focus is on either `YearRangePickerNext` or `YearRangePickerPrev`, it navigates the calendar. Otherwise, it selects the year. | | ArrowLeft / ArrowRight / ArrowUp / ArrowDown | When the focus is on `YearRangePickerCellTrigger`, it navigates the years, changing the page if necessary. | | PageUp | When the focus is on `YearRangePickerCellTrigger`, it navigates to the previous page of years. | | PageDown | When the focus is on `YearRangePickerCellTrigger`, it navigates to the next page of years. | | Escape | Cancels the current range selection and restores the previous valid range. | --- - [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/YearRangePicker) - [npm](https://www.npmjs.com/package/akar) # Guides > How to compose, style, animate, and internationalize Akar primitives. Pick a guide. Composition and styling are the two you will use on every component. [**Composition**](https://vinicunca.dev/akar/guides/composition) Use the `asChild` prop to compose Akar's functionality onto alternative element types or your own Vue components. [**Styling**](https://vinicunca.dev/akar/guides/styling) Akar are unstyled—and compatible with any styling solution—giving you complete control over styling. [**Animation/Transition**](https://vinicunca.dev/akar/guides/animation) Animate Akar with CSS keyframes, native Vue Transition or JavaScript animation library of your choice. [**Controlled State**](https://vinicunca.dev/akar/guides/controlled-state) How to work with controlled vs. uncontrolled state in Akar. [**Dates & Times**](https://vinicunca.dev/akar/guides/dates) How to work with dates and times in Akar. [**Internationalization (RTL)**](https://vinicunca.dev/akar/guides/i18n) Akar support both LTR/RTL directions. Learn more about how to integrate internationalization. [**Inject Context**](https://vinicunca.dev/akar/guides/inject-context) Utilize `injectContext` to enhance component composition in Akar, enabling powerful and flexible UI development. [**Server side rendering**](https://vinicunca.dev/akar/guides/server-side-rendering) Akar can be rendered on the server. [**Virtualization**](https://vinicunca.dev/akar/guides/virtualization) Learn how to efficiently render large datasets with Akar, powered by `@tanstack/virtual`. [**Migration - Radix Vue to Akar**](https://vinicunca.dev/akar/guides/migration) This guide provides step-by-step instructions for developers transitioning their projects from Radix Vue to Akar. # Animation/Transition > Animate Akar with CSS keyframes, native Vue Transition or JavaScript animation library of your choice. ## Animation Adding animation to Akar should feel similar to any other component, but there are some caveats noted here in regards to exiting animations with JS animation libraries. ## Animating with CSS animation The simplest way to animate Primitives is with CSS. You can use CSS animation to animate both mount and unmount phases. The latter is possible because the Akar will suspend unmount while your animation plays out. ```css @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } .DialogOverlay[data-state='open'], .DialogContent[data-state='open'] { animation: fadeIn 300ms ease-out; } .DialogOverlay[data-state='closed'], .DialogContent[data-state='closed'] { animation: fadeOut 300ms ease-in; } ``` ## Animating with Vue Transition Other than using CSS animation, you might prefer to use the native Vue ``. Great news! It should be as easy as wrapping component (that has `forceMount` prop), and you are done! ```vue ``` ## ⭐️ Animating with Motion Vue [Motion Vue](https://motion.dev/docs/vue) is the recommended animation library for Akar. This lightweight, powerful library integrates seamlessly with components and offers extensive flexibility for creating smooth, performant animations. ```vue ``` > [!TIP] > > Check out this [Stackblitz Demo](https://stackblitz.com/edit/x7y44ngl?file=src%2FApp.vue) 🤩 ## Delegating unmounting for JavaScript Animation When many stateful Primitives are hidden from view, they are actually removed from the DOM. JavaScript animation libraries need control of the unmounting phase, so we provide the `forceMount` prop on many components to allow consumers to delegate the mounting and unmounting of children based on the animation state determined by those libraries. For example, if you want to use [@vueuse/motion](https://motion.vueuse.org/) to animate a `Dialog`, you would do so by conditionally rendering the dialog `Overlay` and `Content` parts based on the animation state from one of its composable like `useSpring`: ```vue ``` > [!TIP] > > Check out this [Stackblitz Demo](https://stackblitz.com/edit/macsaz-xuwbw3im?file=src%2FApp.vue) # Composition > Use the `asChild` prop to compose Akar's functionality onto alternative element types or your own Vue components. All Akar parts that render a DOM element accept an `asChild` prop. When `asChild` is set to `true`, Akar will not render a default DOM element, instead passing the props and behavior required to make it functional to the first child of the slots. ## Changing the element type In the majority of cases you shouldn’t need to modify the element type as Akar has been designed to provide the most appropriate defaults. However, there are cases where it is helpful to do so. A good example is with `TooltipTrigger`. By default this part is rendered as a `button`, though you may want to add a tooltip to a link (`a` tag) as well. Let's see how you can achieve this using `asChild`: ```vue ``` > [!WARNING] > > If you do decide to change the underlying element type, it is your responsibility to ensure it remains accessible and functional. In the case of `TooltipTrigger` for example, it must be a focusable element that can respond to pointer and keyboard events. If you were to switch it to a `div`, it would no longer be accessible. In reality, you will rarely modify the underlying DOM element like we've seen above. Instead it's more common to use your own Vue components. This is especially true for most `Trigger` parts, as you usually want to compose the functionality with the custom buttons and links in your design system. ## Composing with your own Vue components This works exactly the same as above, you pass `asChild` to the part and then wrap your own component with it. However, there are a few gotchas to be aware of. ## Composing multiple primitives `asChild` can be used as deeply as you need to. This means it is a great way to compose multiple primitive's behavior together. Here is an example of how you can compose `TooltipTrigger` and `DialogTrigger` together with your own button: ```vue ``` # Controlled State > How to work with controlled vs. uncontrolled state in Akar. Akar provides flexible state management for components, allowing developers to use either **controlled** or **uncontrolled** state. Understanding when to use each approach ensures better integration with Vue's reactivity system. --- ## Controlled vs. Uncontrolled State ### Controlled State A **controlled** component receives its state as a prop and requires explicit updates via event listeners. The parent component manages and synchronizes the state. #### Example: Controlled `SwitchRoot` ```vue ``` **How it works:** - The `SwitchRoot` component’s state is managed by the `isActive` ref. - The `@update:modelValue` event ensures updates propagate correctly. > [!TIP] > > **Use controlled state when:** > > - You need to sync state with Vuex, Pinia, or an API. > - Multiple components rely on the same state. > - You want fine-grained control over updates. #### Using v-model with Controlled Components Vue’s `v-model` syntax provides a convenient way to bind values to controlled components in Akar. It automatically handles passing the value and listening for updates. Example: Using `v-model` with `SwitchRoot` ```vue ``` ### Uncontrolled State An **uncontrolled** component manages its own state internally, without requiring a parent-controlled prop. Instead of `modelValue`, Akar components use `defaultValue` to initialize state. #### Example: Uncontrolled `SwitchRoot` ```vue ``` **How it works:** - The `SwitchRoot` initializes its state with `defaultValue`. - State changes occur internally without external control. > [!TIP] > > **Use uncontrolled state when:** > > - The component does not need to sync with external logic. > - You want a simpler setup without explicit state management. > - The state is local and does not impact other components. ## Common Mistakes & Fixes ### 1. Forgetting `@update:modelValue` ```vue ``` ### 2. Using `modelValue` Instead of `defaultValue` ```vue ``` ### 3. Not Providing a Setter for Computed Props ```ts // ❌ Incorrect: const isActive = computed(() => store.state.toggleState); // ✅ Correct: const isActive = computed({ get: () => store.state.toggleState, set: (val) => store.commit('setToggleState', val) }); ``` # Dates & Times > How to work with dates and times in Akar. > [!TIP] > > The inner-workings of our date-related components are heavily inspired by the research and work done > by the [React Aria](https://react-spectrum.adobe.com/react-aria/) team at Adobe, who have created > robust date components that excel in terms of accessibility, user experience, and flexibility. The component depends on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package, which solves a lot of the problems that come with working with dates and times in JavaScript. We highly recommend reading through the documentation for the package to get a solid feel for how it works, and you'll need to install it in your project to use the date-related components. ```bash [pnpm] pnpm add @internationalized/date ``` ```bash [yarn] yarn add @internationalized/date ``` ```bash [npm] npm install @internationalized/date ``` ```bash [bun] bun add @internationalized/date ``` ## Date Objects We use the `DateValue` objects provided by `@internationalized/date` to represent dates in the various components. These objects are immutable, and provide information about the type of date they represent: - `CalendarDate`: A date with no time component, such as `2023-10-11`. - `CalendarDateTime`: A date with a time component, but without a timezone, such as `2023-10-11T12:30:00`. - `ZonedDateTime`: A date with a time component and a timezone, such as `2023-10-11T21:00:00:00-04:00[America/New_York]`. The benefit of using these objects is that we can be very specific about the type of date we want, and the behavior of the builder will adapt to that type. Additionally, you don't have to worry about wrangling timezones, daylight savings time, or any other date-related nuance. ## Utility Functions This package also provides a number of utility functions which solves a lot of the problems that come with working with dates and times in JavaScript. Specially designed to work well with [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html). ## DateValue Types ## CalendarDate Represents a date without any time component. This is ideal for dates like birthdays, anniversaries, or deadlines where only the date matters. ```ts // Creating a CalendarDate import { CalendarDate, getLocalTimeZone, parseDate, today } from '@internationalized/date'; // From year, month, day parameters const date = new CalendarDate(2024, 7, 10); // From ISO 8601 string const parsedDate = parseDate('2024-07-10'); // Current date in specific timezone const losAngelesToday = today('America/Los_Angeles'); // Current date in user's timezone const localToday = today(getLocalTimeZone()); ``` See the [CalendarDate API Documentation](https://react-spectrum.adobe.com/internationalized/date/CalendarDate.html) for additional methods. ## CalendarDateTime Represents a date with a time component, but without timezone information. This is useful for events that have a specific time but are not tied to a particular timezone, such as local appointments. ```ts // Creating a CalendarDateTime import { CalendarDateTime, parseDateTime } from '@internationalized/date'; // From date and time components const dateTime = new CalendarDateTime(2024, 7, 10, 12, 30, 0); // From ISO 8601 string const parsedDateTime = parseDateTime('2024-07-10T12:30:00'); ``` See the [CalendarDateTime API Documentation](https://react-spectrum.adobe.com/internationalized/date/CalendarDateTime.html) for additional methods. ## ZonedDateTime Represents a specific date and time in a specific timezone. This is crucial for events that occur at an exact moment regardless of the user's location, such as conferences, live broadcasts, or international meetings. ```ts // Creating a ZonedDateTime import { parseAbsolute, parseAbsoluteToLocal, parseZonedDateTime, ZonedDateTime, } from '@internationalized/date'; const date = new ZonedDateTime( 2024, // year 7, // month 10, // day 'America/Los_Angeles', // timezone -25200000, // UTC offset in milliseconds (PDT) 12, // hour 30, // minute 0 // second ); // From ISO 8601 strings using different parsing functions const date1 = parseZonedDateTime('2024-07-12T00:45[America/New_York]'); const date2 = parseAbsolute('2024-07-12T07:45:00Z', 'America/New_York'); const date3 = parseAbsoluteToLocal('2024-07-12T07:45:00Z'); ``` See the [ZonedDateTime](https://react-spectrum.adobe.com/internationalized/date/ZonedDateTime.html) API documentation for more information. ## Updating DateValue Objects Since DateValue objects are immutable, you must create new instances when updating them. Here are the correct ways to modify them: ```ts // INCORRECT - will not work let placeholder = new CalendarDate(2024, 7, 10); placeholder.month = 8; // Error! DateValue objects are immutable // CORRECT - using methods that return new instances let placeholder = new CalendarDate(2024, 7, 10); // Method 1: Using set() to change specific properties placeholder = placeholder.set({ month: 8 }); // Method 2: Using add() to increment values placeholder = placeholder.add({ months: 1 }); // Method 3: Using subtract() to decrement values placeholder = placeholder.subtract({ days: 5 }); // Method 4: Using cycle() to cycle through valid values placeholder = placeholder.cycle('month', 'forward', [1, 3, 5, 7, 9, 11]); ``` ## Parsing ### Parsing Date Strings When working with date strings from APIs or databases, use the appropriate parsing function based on the type of DateValue you need: ```ts import { parseAbsolute, // For ZonedDateTime from UTC string + timezone parseAbsoluteToLocal, // For ZonedDateTime in local timezone parseDate, // For CalendarDate parseDateTime, // For CalendarDateTime parseZonedDateTime, // For ZonedDateTime with timezone name } from '@internationalized/date'; // Examples const date = parseDate('2024-07-10'); // CalendarDate const dateTime = parseDateTime('2024-07-10T12:30:00'); // CalendarDateTime const zonedDate = parseZonedDateTime('2024-07-12T00:45[America/New_York]'); // ZonedDateTime const absoluteDate = parseAbsolute('2024-07-12T07:45:00Z', 'America/New_York'); // ZonedDateTime const localDate = parseAbsoluteToLocal('2024-07-12T07:45:00Z'); // ZonedDateTime in user's timezone ``` ## Common Gotchas and Tips - **Month Indexing**: Unlike JavaScript's Date object (which is 0-indexed), @internationalized/date uses 1-indexed months (January = 1). - **Immutability**: Always reassign when modifying date objects: `date = date.add({ days: 1 })`. - **Timezone Handling**: Use `ZonedDateTime` for schedule-critical events like meetings or appointments. - **Type Consistency**: Match your DateValue types to your needs - if you need time selection, use `CalendarDateTime` instead of `CalendarDate`. - **Parsing Functions**: Choose the right parsing function to avoid unexpected results. For example, use `parseDate` for date-only strings and `parseDateTime` for date-time strings without timezone. ### How to use? ```ts import type { DateValue } from '@internationalized/date'; import { CalendarDate } from '@internationalized/date'; import { createDateRange, createDecade, createMonth, createYear, createYearRange, getDaysInMonth, getWeekNumber, hasTime, isAfter, isAfterOrSame, isBefore, isBeforeOrSame, isBetween, isBetweenInclusive, isCalendarDateTime, isZonedDateTime, parseStringToDateValue, toDate, } from 'akar/date'; const date = new CalendarDate(1995, 8, 18); const minDate = new CalendarDate(1995, 8, 1); const maxDate = new CalendarDate(1995, 8, 31); parseStringToDateValue('1995-08-18', date); // returns a DateValue object toDate(date); // returns a Date object isCalendarDateTime(date); // returns false isZonedDateTime(date); // returns false hasTime(date); // returns false getDaysInMonth(date); // returns 31 getWeekNumber(new CalendarDate(1995, 8, 18), 'en-US', 'sun'); // returns 33 isAfter(date, minDate); // returns true isBeforeOrSame(date, maxDate); // returns true isAfterOrSame(date, minDate); // returns true isBefore(date, maxDate); // returns true isBetweenInclusive(date, minDate, maxDate); // returns true isBetween(date, minDate, maxDate); // returns true createMonth({ dateObj: new CalendarDate(1995, 8, 18), weekStartsOn: 0, locale: 'en', fixedWeeks: true }); // returns a grid of days as DateValue for the month, also containing the dateObj, plus an array of days for the month createYear({ dateObj: new CalendarDate(1995, 8, 18), numberOfMonths: 2, pagedNavigation: true }); // returns an array of months as DateValue, centered around the dateObj taking into account the numberOfMonths and pagedNavigation when returning the months createDecade({ dateObj: new CalendarDate(1995, 8, 18), startIndex: -10, endIndex: 10 }); // returns a decade centered around the dateObj createDateRange({ start: new CalendarDate(1995, 8, 18), end: new CalendarDate(2005, 8, 18) }); // returns an array of dates as DateValue between the start and end date createYearRange({ start: new CalendarDate(1995, 8, 18), end: new CalendarDate(2005, 8, 18) }); // returns an array of years as DateValue between the start and end date ``` # Internationalization (RTL) > Akar support both LTR/RTL directions. Learn more about how to integrate internationalization. ## Internationalization & RTL ## Multi-Direction Support ### Introduction This documentation provides guidance on how to utilize multi-directional support in Akar with SSR support. Akar rely on [`Floating UI`](https://floating-ui.com/) to position floating elements, which requires to be fed the current direction of the web app. Akar components are LTR by default, but you are in control of what direction (only LTR, RTL, or both) you want to support. This section provides best practices to easily support RTL direction. ### RTL [`ConfigProvider`](https://vinicunca.dev/akar/utilities/config-provider) is a wrapper component to provide global configurations, including the directionality of the web app. When creating localized apps that require right-to-left (RTL) reading direction, you need to wrap your application with the `ConfigProvider` component to ensure all of the primitives adjust their behavior based on the `dir` prop. To make all Akar RTL, wrap your entire App in `ConfigProvider` and pass the `dir` prop with the value `rtl`. Add the following code to your `app.vue` or main layout component: ```vue ``` All Akar components that are wrapped in the provider inherit the `dir` attribute. ### Dynamic Direction To dynamically change the direction of Akar, we could leverage the [`useTextDirection`](https://vueuse.org/core/useTextDirection/) composable and combine it with our `ConfigProvider`. But first, we need to install the [`@vueuse/core`](https://vueuse.org/) package. ```bash [pnpm] pnpm add @vueuse/core ``` ```bash [yarn] yarn add @vueuse/core ``` ```bash [npm] npm install @vueuse/core ``` ```bash [bun] bun add @vueuse/core ``` Then in your root Vue file: ```vue ``` To support SSR - when the server has no access to the `html` and its direction, set `initialValue` in `useTextDirection`. ```vue ``` > [!NOTE] > > The `dir` prop doesn't support `auto` as a value, so we need an intermediate Ref to explicitly define the direction. `textDirection` is a [`Ref`](https://vuejs.org/api/reactivity-core.html#ref), and by changing the value of it to either "ltr" or "rtl", the `dir` attribute on the `html` tag changes as well. ## Internationalization Some languages are written from LTR and others are written in RTL. In a multi-language web app, you need to configure directionality alongside the translations. This is a simplified guide on how to achieve that using Akar primitives. But first, let's install some required packages. ### Dependencies We rely on [`VueI18n`](https://vue-i18n.intlify.dev/) to manage different translations we want to support. ```bash [pnpm] pnpm add vue-i18n@latest ``` ```bash [yarn] yarn add vue-i18n@latest ``` ```bash [npm] npm install vue-i18n@latest ``` ```bash [bun] bun add vue-i18n@latest ``` Go ahead and add some translations for the word "hello" in different languages at `main.ts`. ```ts import { createApp } from 'vue' import './style.css' import App from './App.vue' import { createI18n } from 'vue-i18n' const messages = { en: { hello: 'Hello', }, fa: { hello: 'درود', }, ar: { hello: 'مرحبا', }, ja: { hello: 'こんにちは', } } const i18n = createI18n({ legacy: false, // you must set `false` to use the Composition API locale: 'en', // set default locale availableLocales: ['en', 'fa', 'ar', 'ja'], messages, }) createApp(App) .use(i18n) .mount('#app') ``` ### Language Selector After setting the translations and adding the `vue-i18n` plugin, we need a language selector in your `app.vue`. By changing the language using this Akar select primitive: 1. The translations are reactive to the new language 2. The direction of the web app is reactive to the new language ```vue ``` # Inject Context > Utilize `injectContext` to enhance component composition in Akar, enabling powerful and flexible UI development. > [!WARNING] > > **Use with caution! API might change** > > Akar exposes internal `injectContext` to further extend the ability to compose and construct complex components. However, this API was primarily designed to be internal use. Thus the API might change without notice. ## Introduction to `injectContext` In Akar, all root component, and some other component exports an `injectContext` function, which is a key feature for managing component state and enabling seamless composition. This guide will show you how to craft your own child component based on the provided context. ## What is `injectContext`? `injectContext` is a function provided by each Akar component that allows you to access the internal state and methods of that component. It leverages Vue's [Provide / Inject](https://vuejs.org/guide/components/provide-inject) to provide a powerful way of extending and customizing component behavior. ## Basic Usage Here's a simple example of how to use `injectContext` with a Akar Accordion component: ```vue ``` ## Common Use Cases 1. **Custom Styling**: Access internal state to apply dynamic styles based on component state. 2. **Extended Functionality**: Build upon existing component logic to add new features. 3. **Complex Layouts**: Create intricate UI patterns by composing multiple components and sharing state between them. 4. **Accessibility Enhancements**: Utilize internal methods and state to improve keyboard navigation or screen reader support. ## Best Practices 1. Use `injectContext` in child components or composables, not in the component itself. 2. Always check if the injected context exists before using it, as it may be `undefined` if used outside the component's scope. 3. Prefer using provided props and events when possible, and use `injectContext` for more advanced scenarios. 4. When using TypeScript, leverage the type information provided by `injectContext` for better code quality. # Migration - Radix Vue to Akar > This guide provides step-by-step instructions for developers transitioning their projects from Radix Vue to Akar. > [!NOTE] > > Akar v2.0.20 already includes these Reka v2 API changes. If you are coming from `radix-vue` or `reka-ui`, switch the package name to `akar` and apply the breakages below that you have not already adopted. ## Installation First, install the latest `akar`. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` Congratulations! 🎉 Now that you've installed the above package, let's perform the migration! The first 2 steps are relatively simple. Just do a global search and replace for the following changes. ## Import Statement Changes The primary change in imports is replacing `radix-vue` or `reka-ui` with `akar`. ```vue ``` ## Naming Convention Changes CSS variable and data attributes names have been updated to use the `reka` prefix instead of `radix`. ```css --radix-accordion-content-width: 300px; /* [!code --] */ --akar-accordion-content-width: 300px; /* [!code ++] */ [data-radix-collection-item] { } /* [!code --] */ [data-reka-collection-item] { } /* [!code ++] */ ``` ## Component Breaking Changes ### Combobox - [Remove `filter-function` props](https://github.com/unovue/reka-ui/commit/ee8a3f2366a5c27c2bf1cc0a1ecbb0fea559a9f7) - `Combobox` has been refactored and improved to support better custom filtering. Read more.```vue ``` - [Replace `searchTerm` props of Root to Input's `v-model`](https://github.com/unovue/reka-ui/commit/e1bab6598c3533dfbf6a86ad26b471ab826df069#diff-833593a5ce28a8c3fabc7d77462b116405e25df2b93bcab449798b5799e73474) - [Move `displayValue` props from Root to Input](https://github.com/unovue/reka-ui/commit/e1bab6598c3533dfbf6a86ad26b471ab826df069#diff-833593a5ce28a8c3fabc7d77462b116405e25df2b93bcab449798b5799e73474)```vue ``` ### Arrow - [Improve arrow polygon](https://github.com/unovue/reka-ui/commit/ac8f3c34760f4c9c0f952ecd027b32951b9c416c) - Change the svg polygon to allow better styling. ### Form component - [Rename controlled state to `v-model`](https://github.com/unovue/reka-ui/commit/87aa5ba6016fa7a98f02ea43062212906b2633a0) - Replace `v-model:checked`, `v-model:pressed` with more familiar API for form component. ```vue ``` - [Reposition `VisuallyHidden`](https://github.com/unovue/reka-ui/commit/107389a9c230d2c94232887b9cbe2710222564aa) - Previously, `VisuallyHidden` were positioned at the root node, causing style scoped to not be applied. ### Menu CheckboxItem - Similar to the changes in form component, the API for binding `CheckboxItem` has been changed from `v-model:checked` to `v-model`. ```vue ``` ### Pagination - [Required `itemsPerPage` prop](https://github.com/unovue/reka-ui/commit/37bba0c26a3cbe7e7e3e4ac36770be3ef5224f0c) - The `itemsPerPage` prop is now required instead of relying on a default value.```vue ``` ### Calendar - [Remove deprecated step prop](https://github.com/unovue/reka-ui/commit/ec146dd8fa0f95f64baf0b29c3424ee31cfb9666) - Use `prevPage/nextPage` props for greater control.```vue ``` ### Select - [`SelectValue` no longer renders a teleported element](https://github.com/unovue/reka-ui/commit/6a623484d610cc3b7c1a23a77c253c8e95cef518) - The previous implementation of `SelectValue` rendered the selected `SelectItem` through a teleported fragment. This caused SSR flicker and unnecessary computation.```vue ``` ### Presence To have better support for SSR content, we also modified the logic around the usage of `forceMount` for components that utilize Presence: - `Accordion` - `Collapsible` - `Tabs` - `NavigationMenu` [`forceMount` will now render the component](https://github.com/unovue/reka-ui/commit/6f7f29abe79ac6c3ace117a398b6f7613ab6d2bc) even though the state is inactive. You are now required to handle the visibility logic of the component manually. ```vue ``` ## For Nuxt module users If you are using Nuxt, you need to update your module import. ```ts // nuxt.config.ts export default defineNuxtConfig({ modules: [ "radix-vue/nuxt", // [!code --] "akar/nuxt", // [!code ++] ], }); ``` # Namespaced components > Import a whole primitive as an object (`Dialog.Root`) instead of listing every part. Akar's design pattern is to create primitives for each component and let you [compose](https://vinicunca.dev/akar/guides/composition) them however you want. Importing every part one-by-one can be noisy, and it is easy to forget a required piece. `akar/namespaced` groups the parts under one object. ## How to use? First, you need to import the namespaced components via `akar/namespaced` in your Vue component. ```vue ``` Then, you can use all the relevant components within the namespace. ```vue ``` # Server side rendering > Akar can be rendered on the server. ## Overview Server side rendering or `SSR`, is a technique used to render components to HTML on the server, as opposed to rendering them only on the client. Static rendering is another similar approach. Instead it pre-renders pages to HTML at build time rather than on each request. You should be able to use all of our primitives with both approaches, for example with [Nuxt.js](https://nuxt.com/). ## Nuxt Hydration issue (Vue < 3.5) Akar offers a [Nuxt module](https://vinicunca.dev/akar/overview/installation.html#nuxt-modules) that supports auto importing components. However, if you are using Vue < 3.5, minor hydration issues might arise because as of vue <= 3.4 there is [currently no way](https://github.com/vuejs/rfcs/discussions/557) to ensure consistent DOM element `id` between the client and server renders. This is something that Akar relies on. As a temporary workaround, we expose a way to allow Nuxt (with version > `3.10`) inject its `useId` implementation to Akar. To provide a custom `useId` implementation, please follow this [guide](https://vinicunca.dev/akar/utilities/config-provider.html#hydration-issue-vue-3-5). # Styling > Akar are unstyled—and compatible with any styling solution—giving you complete control over styling. ## Styling overview ### Functional styles You are in control of all aspects of styling, including functional styles. For example, by default, a [Dialog Overlay](https://vinicunca.dev/akar/components/dialog) won't cover the entire viewport. You're responsible for adding those styles, plus any presentation styles. ### Classes All components accept `class` attributes, just like normal component. This class will be passed through to the DOM element. You can use it in CSS as expected. #### Teleported elements Some elements, such as modals or popovers, are teleported to the `body`. When using scoped style to apply CSS, you will need to use [deep selectors](https://vuejs.org/api/sfc-css-features.html#deep-selectors) to target them. ### Data attributes When components are stateful, their state will be exposed in a `data-state` attribute. For example, when an [Accordion Item](https://vinicunca.dev/akar/components/accordion) is opened, it includes a `data-state="open"` attribute. ## Styling with CSS ### Styling a part You can style a component part by targeting the `class` that you provide. ```vue ``` ### Styling a state You can style a component state by targeting its `data-state` attribute. ```css .AccordionItem { border-bottom: 1px solid gainsboro; } .AccordionItem[data-state='open'] { border-bottom-width: 2px; } ``` ### Scoped style You can style a component using scoped style. Be wary of teleported elements, as they require the use of [deep selectors](https://vuejs.org/api/sfc-css-features.html#deep-selectors) to be targeted. ```vue ``` ## Styling with Tailwind CSS The examples below are using [Tailwind CSS](https://tailwindcss.com/), but you can use any library of your choice. ### Styling a part You can style a component part by targeting the `class`. ```vue ``` ### Styling a state With Tailwind CSS's powerful variant selector, you can style a component state by targeting its `data-state` attribute. ```vue ``` ## Extending a primitive Extending a primitive is done the same way you extend any Vue component. ```vue [CustomAccordion.vue] ``` ## Summary Akar were designed to encapsulate accessibility concerns and other complex functionalities, while ensuring you retain complete control over styling. For convenience, stateful components include a `data-state` attribute. # Virtualization > Learn how to efficiently render large datasets with Akar, powered by `@tanstack/virtual`. > [!NOTE] > > **What is Virtualization?** > > Virtualization is a technique used to efficiently render large lists or tree structures by only rendering the items currently visible in the viewport. This approach significantly improves performance and reduces memory usage, especially when dealing with thousands of items. ## Benefits of Using Virtualization - Improved Performance: Render thousands of items without lag - Reduced Memory Usage: Only mount DOM nodes for visible items - Better User Experience: Fast initial load times and responsive interactions ## Customization Options All virtualizer ([Combobox](https://vinicunca.dev/akar/components/combobox#virtualizer), [Listbox](https://vinicunca.dev/akar/components/listbox#virtualizer), and [Tree](https://vinicunca.dev/akar/components/tree#virtualizer)) components offer the following props and customization: - Custom item rendering: Flexibility to render complex item structures - `estimateSize`: Set estimate item heights for static or dynamic item - `overscan`: Control the number of items rendered outside the visible area - `textContent`: Text content for each item to achieve type-ahead feature ## Usage Here's a few important note to make sure virtualization works! 1. A fixed height/max-height wrapping ``. 2. Consistent item height, and set the `estimateSize` props appropriately. 3. Set `textContent` props to make sure type-ahead accessibility. ## Example ```vue ``` ## Common issue ### Virtualization is not working Do ensure that ``'s parent element has a defined height! ```vue ``` # Accessibility > Akar follow the WAI-ARIA authoring practices guidelines and are tested in a wide selection of modern browsers and commonly used assistive technologies. We take care of many of the difficult implementation details related to accessibility, including `aria` and `role` attributes, focus management, and keyboard navigation. That means that users should be able to use our components as-is in most contexts and rely on functionality to follow the expected accessibility design patterns. ## WAI-ARIA [WAI-ARIA](https://www.w3.org/TR/wai-aria-1.2/), published and maintained by the W3C, specifies the semantics for many common UI patterns that show up in Akar. This is designed to provide meaning for controls that aren't built using elements provided by the browser. For example, if you use a `div` instead of a `button` element to create a button, there are attributes you need to add to the `div` in order to convey that it's a button for screen readers or voice recognition tools. In addition to semantics, there are behaviors that are expected from different types of components. A `button` element is going to respond to certain interactions in ways that a `div` will not, so it's up to the developer to reimplement those interactions with JavaScript. The [WAI-ARIA authoring practices](https://www.w3.org/TR/wai-aria-practices-1.2/) provide additional guidance for implementing behaviors for various controls that come with Akar. ## Accessible Labels With many built-in form controls, the native HTML `label` element is designed to provide semantic meaning and context for corresponding `input` elements. For non-form control elements, or for custom controls like those provided by Akar, [WAI-ARIA provides a specification](https://www.w3.org/TR/wai-aria-1.2/#namecalculation) for how to provide accessible names and descriptions to those controls. Where possible, Akar includes abstractions to make labelling our controls simple. The [`Label`](https://vinicunca.dev/akar/components/label) primitive is designed to work with many of our controls. Ultimately it's up to you to provide those labels so that users have the proper context when navigating your application. ## Keyboard Navigation Many complex components, like [`Tabs`](https://vinicunca.dev/akar/components/tabs) and [`Dialog`](https://vinicunca.dev/akar/components/dialog), come with expectations from users on how to interact with their content using a keyboard or other non-mouse input modalities. Akar provides basic keyboard support in accordance with the [WAI-ARIA authoring practices](https://www.w3.org/TR/wai-aria-practices-1.2/). ## Focus Management Proper keyboard navigation and good labelling often go hand-in-hand with managing focus. When a user interacts with an element and something changes as a result, it's often helpful to move focus with the interaction so that the next tab stop is logical depending on the new context of the app. And for screen reader users, moving focus often results in an announcement to convey this new context, which relies on proper labelling. In many Akar, we move focus based on the interactions a user normally takes in a given component. For example, in [`AlertDialog`](https://vinicunca.dev/akar/components/alert-dialog), when the modal is opened, focus is programmatically moved to a `Cancel` button element to anticipate a response to the prompt. # Getting started > A quick tutorial to get you up and running with Akar. ## Implementing a Popover In this quick tutorial, we will install and style the [Popover](https://vinicunca.dev/akar/components/popover) component. ### 1. Install the library Install the component from your command line. ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` ### 2. Import the parts Import and structure the parts. ```vue ``` ### 3. Add your styles Add styles where desired. ```vue ``` ### Demo Here's a complete demo. ```vue [index.vue] ``` ```css [styles.css] @import '../_colors/black-alpha.css'; @import '../_colors/mauve.css'; @import '../_colors/grass.css'; @scope (.akar-demo-Popover) { /* reset */ button, fieldset, input { all: unset; } .PopoverContent { border-radius: 4px; padding: 20px; width: 260px; background-color: white; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; animation-duration: 400ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); will-change: transform, opacity; } .PopoverContent:focus { box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px, 0 0 0 2px var(--grass-7); } .PopoverContent[data-state='open'][data-side='top'] { animation-name: slideDownAndFade; } .PopoverContent[data-state='open'][data-side='right'] { animation-name: slideLeftAndFade; } .PopoverContent[data-state='open'][data-side='bottom'] { animation-name: slideUpAndFade; } .PopoverContent[data-state='open'][data-side='left'] { animation-name: slideRightAndFade; } .PopoverArrow { fill: white; } .PopoverClose { font-family: inherit; border-radius: 100%; height: 25px; width: 25px; display: inline-flex; align-items: center; justify-content: center; color: var(--grass-11); position: absolute; top: 5px; right: 5px; } .PopoverClose:hover { background-color: var(--grass-4); } .PopoverClose:focus { box-shadow: 0 0 0 2px var(--grass-7); } .IconButton { font-family: inherit; border-radius: 100%; height: 35px; width: 35px; display: inline-flex; align-items: center; justify-content: center; color: var(--grass-11); background-color: white; box-shadow: 0 2px 10px var(--black-a7); } .IconButton:hover { background-color: var(--grass-3); } .IconButton:focus { box-shadow: 0 0 0 2px black; } .Fieldset { display: flex; gap: 20px; align-items: center; } .Label { font-size: 13px; color: var(--grass-11); width: 75px; } .Input { width: 100%; display: inline-flex; align-items: center; justify-content: center; flex: 1; border-radius: 4px; padding: 0 10px; font-size: 13px; line-height: 1; color: var(--grass-11); box-shadow: 0 0 0 1px var(--grass-7); height: 25px; } .Input:focus { box-shadow: 0 0 0 2px var(--grass-8); } .Text { margin: 0; color: var(--mauve-12); font-size: 15px; line-height: 19px; font-weight: 500; } @keyframes slideUpAndFade { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideRightAndFade { from { opacity: 0; transform: translateX(-2px); } to { opacity: 1; transform: translateX(0); } } @keyframes slideDownAndFade { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideLeftAndFade { from { opacity: 0; transform: translateX(2px); } to { opacity: 1; transform: translateX(0); } } } ``` ## Summary The steps above outline briefly what's involved in using Akar in your application. These components are low-level enough to give you control over how you want to wrap them. You're free to introduce your own high-level API to better suit the needs of your team and product. In a few simple steps, we've implemented a fully accessible Popover component, without having to worry about many of its complexities. - Adheres to [WAI-ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/) design pattern. - Can be controlled or uncontrolled. - Customize side, alignment, offsets, collision handling. - Optionally render a pointing arrow. - Focus is fully managed and customizable. - Dismissing and layering behavior is highly customizable. ## Working with LLMs Akar documentation is optimized for Large Language Models (LLMs) to help you get AI-powered assistance while working with our components. ### LLM-Friendly Documentation Our documentation includes a special LLM-friendly format that makes it easier for AI assistants to understand and provide accurate help with Akar components. This format: - Removes visual elements and complex formatting that can confuse LLMs - Structures content in a way that's optimized for text processing - Includes comprehensive component information in a linear format - Maintains all the essential technical details while being machine-readable ### Accessing LLM Documentation You can access the LLM-optimized version of our documentation at [llms.txt](https://vinicunca.dev/llms.txt). This file contains: - Complete overview of all Akar components - Detailed API documentation - Usage examples and implementation patterns - Accessibility guidelines - Styling and customization options ### Using LLMs with Akar When working with LLMs like ChatGPT, Claude, or other AI assistants, you can: 1. **Reference the llms.txt file**: Direct your AI assistant to the `/llms.txt` file for comprehensive context about Akar 2. **Ask specific questions**: Get help with implementation, styling, or accessibility features 3. **Generate code examples**: Request custom implementations based on your specific needs 4. **Troubleshoot issues**: Get assistance with common problems or edge cases ### Example Prompts Here are some example prompts you can use with LLMs: ```text "Using the Akar documentation at https://vinicunca.dev/raw/akar/overview.md, help me implement a custom Dialog component with form validation." "Based on https://vinicunca.dev/raw/akar/components/select.md, show me how to create an accessible Select with custom styling." "Refer to https://vinicunca.dev/.well-known/skills/akar/SKILL.md and explain keyboard navigation for Combobox." ``` By leveraging our LLM-optimized documentation, you can get more accurate and helpful responses from AI assistants when working with Akar components. # Installation > Install Akar with npm, add the Nuxt module, or wire the unplugin Vue resolver. ## Package ```bash [pnpm] pnpm add akar ``` ```bash [yarn] yarn add akar ``` ```bash [npm] npm install akar ``` ```bash [bun] bun add akar ``` Import parts from `akar`. Date helpers live on `akar/date`. Namespaced objects (for example `Dialog.Root`) come from `akar/namespaced`. ```vue ``` ## Nuxt module Akar ships `akar/nuxt`. Add it to `modules` and every primitive is auto-imported with **no prefix** (`AccordionRoot`, `DialogTrigger`, …). ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['akar/nuxt'] }); ``` Options (`configKey: 'akar'`): **prefix** (`string`): Prepended to every auto-imported name. Default ''. **components** (`boolean | Record`): true (default) registers every group. false registers none. Pass a map of group keys from akar/constant (accordion, dialog, …) to opt in per group. ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['akar/nuxt'], akar: { prefix: '', components: true } }); ``` ## unplugin-vue-components For Vite (and other unplugin hosts), use `akar/resolver`. Names match the Nuxt module: no prefix unless you set one. ```ts [vite.config.ts] import vue from '@vitejs/plugin-vue'; import AkarResolver from 'akar/resolver'; import Components from 'unplugin-vue-components/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ vue(), Components({ dts: true, resolvers: [ AkarResolver() // AkarResolver({ prefix: 'Akar' }) ] }) ] }); ``` ## Next [**Getting started**](https://vinicunca.dev/akar/overview/getting-started) Assemble a Popover and add styles. [**Composition**](https://vinicunca.dev/akar/guides/composition) `asChild`, wrapping your own buttons, stacking primitives. --- - [npm](https://www.npmjs.com/package/akar) # Releases > Akar version history and changelog live on GitHub. The published package is `akar` on npm. This hub documents **v2.0.20**. See every tag, changelog entry, and migration note on [GitHub Releases](https://github.com/vinicunca/akar/releases). --- - [GitHub releases](https://github.com/vinicunca/akar/releases) # Utilities > Config provider, presence, primitive, and composables for wrapping Akar parts. Low-level helpers used by the primitives and by your own wrappers. [**Config Provider**](https://vinicunca.dev/akar/utilities/config-provider) Wraps your app to provide global configurations. [**Focus Scope**](https://vinicunca.dev/akar/utilities/focus-scope) Manages focus within a component boundary with support for trapping and looping focus navigation. [**Presence**](https://vinicunca.dev/akar/utilities/presence) Manages mounting and unmounting of element with transition support. [**Primitive**](https://vinicunca.dev/akar/utilities/primitive) Compose Akar's functionality onto alternative element types or your own Vue components. [**Roving Focus**](https://vinicunca.dev/akar/utilities/roving-focus) Utility component that implements the roving tabindex method to manage focus between items. [**Slot**](https://vinicunca.dev/akar/utilities/slot) Merges its props onto its immediate child. [**useDateFormatter**](https://vinicunca.dev/akar/utilities/use-date-formatter) Creates a wrapper around the `DateFormatter`, which is an improved version of the Intl.DateTimeFormat API, that is used internally by the various date builders to easily format dates in a consistent way. [**useDirection**](https://vinicunca.dev/akar/utilities/use-direction) Access the current direction [**useEmitAsProps**](https://vinicunca.dev/akar/utilities/use-emit-as-props) Convert emits into object similar to props [**useFilter**](https://vinicunca.dev/akar/utilities/use-filter) Locale-Aware string filtering [**useForwardExpose**](https://vinicunca.dev/akar/utilities/use-forward-expose) Forward component's exposed value, props and $el. [**useForwardPropsEmits**](https://vinicunca.dev/akar/utilities/use-forward-props-emits) Combinations for useForwardProps & useEmitAsProps [**useForwardProps**](https://vinicunca.dev/akar/utilities/use-forward-props) Forward component's props without boolean casting [**useId**](https://vinicunca.dev/akar/utilities/use-id) Generate random id [**useLocale**](https://vinicunca.dev/akar/utilities/use-locale) Access the current locale [**Visually Hidden**](https://vinicunca.dev/akar/utilities/visually-hidden) Hides content from the screen in an accessible way. # Config Provider > Wraps your app to provide global configurations. - Enables all primitives to inherit global reading direction. - Enables changing the behavior of scroll body when setting body lock. - Much more controls to prevent layout shifts. ## Anatomy Import the component. ```vue ``` ## API Reference ### Config Provider When creating localized apps that require right-to-left (RTL) reading direction, you need to wrap your application with the `ConfigProvider` component to ensure all of the primitives adjust their behavior based on the `dir` prop. You can also change the global behavior of `bodylock` for components such as `Alert`, `DropdownMenu` and etc to fit your layout to prevent any [content shifts](https://github.com/unovue/reka-ui/issues/385). **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `dir` | `"ltr"` | `"ltr" \| "rtl"` | The global reading direction of your application. This will be inherited by all primitives. | | `locale` | `"en"` | `string` | The global locale of your application. This will be inherited by all primitives. | | `nonce` | | `string` | The global `nonce` value of your application. This will be inherited by the related primitives. | | `scrollBody` | `true` | `boolean \| ScrollBodyOption` | The global scroll body behavior of your application. This will be inherited by the related primitives. | | `teleportTo` | | `string \| HTMLElement` | The global default teleport target for all portalled primitives (e.g. `Dialog`, `Popover`, `Tooltip`).
Individual `*Portal` components can still override this via their own `to` prop.
Useful when rendering inside a custom element / shadow DOM. | | `useId` | | `(() => string)` | The global `useId` injection as a workaround for preventing hydration issue. | [ConfigProvider.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ConfigProvider/ConfigProvider.vue) ## Example Use the config provider. Set global direction to `rtl`, and scroll body behavior to `false` (will not set any padding/margin). ```vue ``` ## Hydration issue `ConfigProvider` can accept a custom `useId` function for frameworks that need to provide their own SSR-stable ID source. Akar uses this function before Vue's native `useId`, so every primitive that generates accessibility IDs follows the same app-provided source. This is useful in Nuxt projects where prerendered HTML and client hydration can use different Vue app ID prefixes. Pass Nuxt's [`useId`](https://nuxt.com/docs/api/composables/use-id) through `ConfigProvider` so Reka-generated IDs stay stable across server and client rendering. > Inspired by [Headless UI](https://github.com/tailwindlabs/headlessui/pull/2959) ```vue ``` # Focus Scope > Manages focus within a component boundary with support for trapping and looping focus navigation. Focus Scope provides enhanced control over keyboard focus management within component boundaries. It can trap focus within its container and optionally loop focus navigation, making it ideal for modal interfaces and other interactive components that need to manage focus states. ## API Reference **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `loop` | `false` | `boolean` | When `true`, tabbing from last item will focus first tabbable
and shift+tab from first item will focus last tababble. | | `present` | `true` | `boolean` | Whether the scope is currently visible. Lets a consumer keep the scope
mounted but hidden (e.g. `display: none`) and still get correct auto-focus:
the mount auto-focus is skipped while not present, and re-runs when it
becomes present again. Defaults to `true` so consumers that mount the scope
only while visible are unaffected. | | `trapped` | `false` | `boolean` | When `true`, focus cannot escape the focus scope via keyboard,
pointer, or a programmatic focus. | **Events** | Event | Payload | Description | | --- | --- | --- | | `mountAutoFocus` | `event: Event` | Event handler called when auto-focusing on mount.
Can be prevented. | | `unmountAutoFocus` | `event: Event` | Event handler called when auto-focusing on unmount.
Can be prevented. | [FocusScope.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/FocusScope/FocusScope.vue) ## Example Basic usage with focus trapping ```vue ``` ### With Focus Looping Enable both trapping and looping for complete focus management: ```vue ``` ### Handling Focus Event ```vue ``` :br> [!WARNING] > > When using trapped mode, ensure there is always at least one focusable element within the scope to prevent focus from being trapped in an inaccessible state. # Presence > Manages mounting and unmounting of element with transition support. > [!NOTE] > > **Question** > > How is this component different from [Vue Transition](https://vuejs.org/guide/built-ins/transition.html#transition)? > > A: The biggest difference is it accepts css animation, and control the visibility of element. Presence component provides enhanced control over element mounting/unmounting. It ensures animations and transitions complete before removing elements from the DOM, making it perfect for animated UI components. ## API Reference | Prop | Default | Type | Description | | --- | --- | --- | --- | | `present*` | | `boolean` | Conditional to mount or unmount the child element. Similar to `v-if` | | `forceMount` | `false` | `boolean` | Force the element to render all the time. Useful for programmatically render grandchild component with the exposed `present` | | Event | Type | Description | | --- | --- | --- | | `enter` | `CustomEvent` | Event handler called when the enter animation has started | | `after-enter` | `CustomEvent` | Event handler called when the enter animation has finished | | `leave` | `CustomEvent` | Event handler called when the leave animation has started | | `after-leave` | `CustomEvent` | Event handler called when the leave animation has finished | > [!TIP] > > Read our [Animation Guide](https://vinicunca.dev/akar/guides/animation) to learn more about implementing animations with Presence component. ## Example ```vue ``` ### Force Mount When you need to ensure content is always rendered regardless of the present state: ```vue ``` # Primitive > Compose Akar's functionality onto alternative element types or your own Vue components. When you are building a component, in some cases you might want to allow user to compose some functionalities onto the underlying element, or alternative element. This is where `Primitive` comes in handy as it expose this capability to the user. ## API Reference | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `div` | `string \| Component` | The element or component the current element should render as. Can be overwrite by `asChild` | | `asChild` | `false` | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | ## Usage ### Changing `as` value If you want to change the default element or component being render, you can set the default `as` when defining the props. ```vue ``` ### Render `asChild` Change the default rendered element for the one passed as a child, merging their props and behavior.:br:brRead our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. # Roving Focus > Utility component that implements the roving tabindex method to manage focus between items. ```vue [index.vue] ``` > [!NOTE] > > Learn more about roving tabindex in [Keyboard Navigation Inside Composite Components](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#x6-6-keyboard-navigation-inside-components) ## Anatomy Import all parts and piece them together. ```vue ``` ## API Reference ### Group Contains all the parts of a Roving Focus **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `currentTabStopId` | | `string \| null` | The controlled value of the current stop item. Can be binded as `v-model`. | | `defaultCurrentTabStopId` | | `string` | The value of the current stop item.

Use when you do not need to control the state of the stop item. | | `dir` | | `"ltr" \| "rtl"` | The direction of navigation between items. | | `loop` | `false` | `boolean` | Whether keyboard navigation should loop around | | `orientation` | | `"vertical" \| "horizontal"` | The orientation of the group.
Mainly so arrow navigation is done accordingly (left & right vs. up & down) | | `preventScrollOnEntryFocus` | `false` | `boolean` | When `true`, will prevent scrolling to the focus item when focused. | **Events** | Event | Payload | Description | | --- | --- | --- | | `entryFocus` | `event: Event` | | | `update:currentTabStopId` | `value: string \| null` | | **Methods** | Method | Type | Description | | --- | --- | --- | | `getItems` | `(includeDisabledItem?: boolean) => { ref: HTMLElement; value?: any; }[]` | | [RovingFocusGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RovingFocus/RovingFocusGroup.vue) | Data attribute | Value | | --- | --- | | `[data-orientation]` | "vertical" \\| "horizontal" \\| "null" | ### Item The item that would inherit the roving tabindex **Props** | Prop | Default | Type | Description | | --- | --- | --- | --- | | `active` | | `boolean` | When `true`, item will be initially focused. | | `allowShiftKey` | | `boolean` | When `true`, shift + arrow key will allow focusing on next/previous item. | | `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. | | `asChild` | | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. | | `focusable` | `true` | `boolean` | When `false`, item will not be focusable. | | `tabStopId` | | `string` | | [RovingFocusItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/RovingFocus/RovingFocusItem.vue) | Data attribute | Value | | --- | --- | | `[data-active]` | Present when not active | | `[data-disabled]` | Present when not focusable | | `[data-orientation]` | "vertical" \\| "horizontal" \\| "null" | ## Examples ### Vertical orientation ```vue ``` ### Loop Use `loop` property to enable roving from last item to the first item, and vice versa. ```vue ``` ### Initial focus item Set `active` prop to item to initially focused item. ```vue ``` ### Unfocusable item Set `focusable="false"` prop to item will prevent them from being focused. ```vue ``` ## Accessibility Adheres to the [Keyboard Navigation Inside Composite Components](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#x6-6-keyboard-navigation-inside-components). ### Keyboard Interactions | Key | Description | | --- | --- | | ArrowDown | Moves focus to the next roving focus item in the group. | | ArrowRight | Moves focus to the next roving focus item in the group. | | ArrowUp | Moves focus to the previous roving focus item in the group. | | ArrowLeft | Moves focus to the previous roving focus item in the group. | | Space / Enter | Triggers click on the roving focus item. | # Slot > Merges its props onto its immediate child. > [!NOTE] > > **Question** > > How is this component different from [Vue native slot](https://vuejs.org/guide/components/slots.html)? > > A: The biggest different is how it handles the `attributes` assigned to it. Native slot treat any binded value as [Scoped Slots](https://vuejs.org/guide/components/slots.html#scoped-slots), where the values will be exposed to the parent template and be consumed. But Akar's slot behave differently, it would merge all the assigned attributes onto it's immediate child. ## Example Say we want to assign an `id` attribute to whatever component/element that was rendered, but Native slot will convert it into a scoped slot, and you will need to assign that id manually. ```vue