Usage
The slots API
Akaza UI uses Vue's native slot system. Components expose their state through scoped slot props — you render exactly what your design needs.
<script setup lang="ts">
import { Collapsible } from 'akaza-ui'
</script>
<template>
<Collapsible :ui="{ trigger: 'px-4 py-3 hover:bg-neutral-50' }">
<template #trigger="{ isOpen }">
<span>Advanced settings</span>
</template>
<template #icon="{ isOpen }">
<svg :class="{ 'rotate-180': isOpen }" .../>
</template>
<template #content>
<p>Hidden until the trigger is activated.</p>
</template>
</Collapsible>
</template>
The ui prop
Most components accept a ui prop to inject CSS classes onto root and internal elements. Each key targets a named structural part:
<Accordion
:items="items"
:ui="{
item: 'border-b border-neutral-200',
trigger: 'px-4 py-3 font-medium hover:bg-neutral-50',
content: 'px-4 pb-4 text-sm text-neutral-600',
}"
/>
Use plain class for the root of single-root components. Use ui.root when styling root alongside internal parts. For multi-root or teleported components such as Dialog, AlertDialog, and Drawer, use named ui keys like overlay and content.
The available keys for each component are listed in that component's UI Options table. Exact CSS classes and data attributes are listed in Styling Hooks.
v-model
Components with open/close or value state support v-model:
<script setup lang="ts">
import { ref } from 'vue'
import { Dialog } from 'akaza-ui'
const open = ref(false)
</script>
<template>
<Dialog v-model="open">
<template #trigger="{ toggle }">
<button @click="() => toggle()">Open dialog</button>
</template>
<template #body>Dialog content here.</template>
</Dialog>
</template>
Programmatic control
Components that manage open state expose open, close, and toggle via defineExpose. Access them with a template ref:
<script setup lang="ts">
import { ref } from 'vue'
import { Dialog } from 'akaza-ui'
const dialog = ref()
function showConfirmation() {
dialog.value?.open()
}
</script>
<template>
<Dialog ref="dialog">
<template #body>Are you sure?</template>
<template #footer="{ close }">
<button @click="() => close()">Dismiss</button>
</template>
</Dialog>
<button @click="showConfirmation">Show confirmation</button>
</template>
Items-based API
List components (Tabs, Menu, RadioGroup, CheckboxGroup, Accordion) accept an items or options array. Per-item content uses named slots — no sub-component trees:
<script setup lang="ts">
import { ref } from 'vue'
import { Tabs } from 'akaza-ui'
const active = ref('account')
const items = [
{ value: 'account', label: 'Account' },
{ value: 'security', label: 'Security' },
]
</script>
<template>
<Tabs v-model="active" :items="items" aria-label="Settings">
<template #panel-account>Account settings…</template>
<template #panel-security>Security settings…</template>
</Tabs>
</template>
Listening to events
Components emit typed events for state changes. The first argument is the next value. The second argument is details with reason, optional event, and cancel() for cancelable changes:
<Accordion
:items="items"
@value-change="(value, details) => {
if (details.reason === 'trigger') console.log('opened:', value)
}"
/>
<Dialog
@open-change="(open) => analytics.track(open ? 'dialog_open' : 'dialog_close')"
/>
Each component's documentation lists its events in the Emits table.