Getting Started

Styling

How to style Akaza UI components — ui prop, CSS classes, and data attributes.

Akaza UI is fully unstyled. Components ship with the minimum CSS needed for correct behavior (animations, positioning, focus management) — visual appearance is entirely up to you.

Styling hooks

Akaza UI exposes relevant hooks on structural elements. Each component page lists exact ui keys, CSS classes, and data attributes for its parts.

  • class — applies to the component's outer root when the component has a single root. Use ui for multi-root or teleported components such as Dialog, AlertDialog, and Drawer.
  • ui — primary styling API for root and named internal parts.
  • akaza-* class — stable semantic CSS selector for each structural part.
  • data-akaza-state — primary exclusive state: open, closed, checked, unchecked, active, loading, submitted, invalid.
  • Granular data-akaza-* attributes — orthogonal form/control state: data-akaza-invalid, data-akaza-focused, data-akaza-dirty, data-akaza-filled, data-akaza-disabled.
  • data-akaza-side / data-akaza-align — floating placement metadata.

The ui prop

The primary styling API. Pass a plain object where each key targets a named part of the component:

<Dialog
  :ui="{
    overlay: 'fixed inset-0 bg-black/50 backdrop-blur-sm',
    content: 'fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white rounded-xl shadow-xl w-full max-w-md',
    header: 'flex items-center justify-between p-6 border-b',
    body: 'p-6',
    footer: 'flex justify-end gap-2 p-6 border-t',
  }"
>

The available ui keys for each component are listed in that component's UI Options table.

class vs ui.root

Use plain class for the outer root of single-root components:

<Button class="rounded-md bg-black px-3 py-2 text-white">
  Save
</Button>

Use ui.root when you prefer one styling object or when styling alongside internal parts:

<Button
  :ui="{
    root: 'rounded-md bg-black px-3 py-2 text-white',
    spinner: 'size-4 animate-spin',
  }"
>
  Save
</Button>

For multi-root or teleported components, use ui keys because there is no single reliable DOM root for fallthrough classes:

<Dialog
  :ui="{
    overlay: 'fixed inset-0 bg-black/50',
    content: 'fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-6',
  }"
/>

Targeting via CSS

You can also target Akaza UI elements using CSS classes or data attribute selectors:

/* Target by semantic class */
.akaza-dialog-overlay { background: rgba(0, 0, 0, 0.5); }
.akaza-dialog-content { border-radius: 12px; }

/* Target by state */
[data-akaza-state="open"] { opacity: 1; }
[data-akaza-state="checked"] { background: black; }

/* Target by positioning side */
.akaza-tooltip-content[data-akaza-side="top"] { margin-bottom: 8px; }

Using with Tailwind CSS

When using Tailwind CSS, Akaza UI's base styles (placed in the akaza-reset CSS layer) need to be declared at the lowest priority so that Tailwind utility classes win. Add this to the top of your CSS entry point — before any Tailwind import:

main.css
@layer akaza-reset;
@import "tailwindcss";

This single line ensures that classes you pass via ui prop or directly on slot content always override component defaults.

State-driven Tailwind classes

Use data attribute variants to apply Tailwind classes based on component state. Since these are applied via the ui prop or directly on your slot markup, they're processed by Tailwind's JIT engine and correctly handle dark mode:

<Switch
  :ui="{
    root: 'data-[akaza-state=checked]:bg-neutral-900 dark:data-[akaza-state=checked]:bg-white data-[akaza-state=unchecked]:bg-neutral-200 dark:data-[akaza-state=unchecked]:bg-neutral-700',
  }"
>
When using @apply with dark mode variants inside Vue <style scoped> blocks, Tailwind may use @media (prefers-color-scheme: dark) instead of the .dark class your app uses. Prefer passing classes directly through the ui prop or slot content to avoid this.

Using with :deep() in scoped styles

Target component internals from a parent component's scoped styles using :deep():

<style scoped>
@reference "tailwindcss";

:deep(.akaza-switch) {
  @apply h-6 w-11 rounded-full transition-colors;
}

:deep(.akaza-switch[aria-checked="true"]) {
  @apply bg-neutral-900;
}

:deep(.akaza-switch[aria-checked="false"]) {
  @apply bg-neutral-200;
}
</style>

Avoid using dark: variants inside @apply in scoped styles — use the ui prop or slot content for dark mode classes instead.