@bitrix24/b24ui-nuxt
Version:
Bitrix24 UI-Kit for developing web applications REST API for NUXT & VUE
1,710 lines (1,350 loc) • 46.6 kB
Markdown
# Bitrix24 UI Kit — AI Reference
This guide is for AI agents and developers generating UIs with the Bitrix24 UI Kit for Nuxt/Vue. It covers:
- Installation and initialization (Nuxt and Vite + Vue)
- A catalog of components and composables with props, slots, and rich examples
- Theming conventions and patterns for overlays and toasts
Note on variants: Most visual options (colors, sizes, states) come from theme variants. The exact sets are generated at build time and may differ per theme. Typical values are shown; to enumerate the exact values at runtime, read theme.variants for each component.
## Table of Contents
- [Bitrix24 UI Kit — AI Reference](#bitrix24-ui-kit--ai-reference)
- [Table of Contents](#table-of-contents)
- [Initialization and Setup](#initialization-and-setup)
- [Install](#install)
- [Nuxt (recommended)](#nuxt-recommended)
- [Vue + Vite](#vue--vite)
- [Naming conventions](#naming-conventions)
- [About theme variants](#about-theme-variants)
- [Theme Variants — Enumerated Values](#theme-variants--enumerated-values)
- [Components](#components)
- [B24App — root provider](#b24app--root-provider)
- [B24Button — button/link](#b24button--buttonlink)
- [B24FieldGroup — grouped button-like elements](#b24fieldgroup--grouped-button-like-elements)
- [B24Input — text input](#b24input--text-input)
- [B24Textarea — textarea](#b24textarea--textarea)
- [B24InputNumber — numeric input](#b24inputnumber--numeric-input)
- [B24Select — select](#b24select--select)
- [B24SelectMenu / B24InputMenu — ready-made menu patterns](#b24selectmenu--b24inputmenu--ready-made-menu-patterns)
- [B24Checkbox — checkbox](#b24checkbox--checkbox)
- [B24RadioGroup — radio group](#b24radiogroup--radio-group)
- [B24Form \& B24FormField — form and field](#b24form--b24formfield--form-and-field)
- [B24Avatar / B24AvatarGroup — avatar and group](#b24avatar--b24avatargroup--avatar-and-group)
- [B24Badge — badge](#b24badge--badge)
- [B24Accordion / B24Collapsible — accordion/collapsible](#b24accordion--b24collapsible--accordioncollapsible)
- [B24Chip — chip](#b24chip--chip)
- [B24Separator — separator](#b24separator--separator)
- [B24Skeleton — skeleton loader](#b24skeleton--skeleton-loader)
- [B24Countdown — countdown](#b24countdown--countdown)
- [B24DescriptionList — description list](#b24descriptionlist--description-list)
- [B24TableWrapper — table wrapper (content)](#b24tablewrapper--table-wrapper-content)
- [B24Kbd — keyboard key](#b24kbd--keyboard-key)
- [B24DropdownMenu — dropdown menu](#b24dropdownmenu--dropdown-menu)
- [B24NavigationMenu — navigation menu](#b24navigationmenu--navigation-menu)
- [B24Navbar and sections](#b24navbar-and-sections)
- [B24Progress — progress bar](#b24progress--progress-bar)
- [B24Range — range slider](#b24range--range-slider)
- [B24Switch — switch](#b24switch--switch)
- [B24Tabs — tabs](#b24tabs--tabs)
- [B24Tooltip — tooltip](#b24tooltip--tooltip)
- [B24Popover — popover](#b24popover--popover)
- [B24Modal — modal dialog](#b24modal--modal-dialog)
- [B24Slideover — side panel](#b24slideover--side-panel)
- [B24Toast — toasts](#b24toast--toasts)
- [Sidebar: B24SidebarLayout and parts](#sidebar-b24sidebarlayout-and-parts)
- [Content \& Prose](#content--prose)
- [Alert / Advice — alerts and tips](#alert--advice--alerts-and-tips)
- [Calendar — calendar](#calendar--calendar)
- [Link — link](#link--link)
- [Composables (core)](#composables-core)
- [useToast](#usetoast)
- [useOverlay](#useoverlay)
- [defineShortcuts](#defineshortcuts)
- [useLocale / defineLocale](#uselocale--definelocale)
- [useConfetti](#useconfetti)
- [Patterns and Best Practices](#patterns-and-best-practices)
- [Links](#links)
- [Exhaustiveness note on variant values](#exhaustiveness-note-on-variant-values)
## Initialization and Setup
Nuxt and plain Vite + Vue are supported.
### Install
- Install the UI Kit and the icons package.
- pnpm/yarn/npm/bun are supported.
```bash
pnpm add @bitrix24/b24ui-nuxt @bitrix24/b24icons-vue
# or
yarn add @bitrix24/b24ui-nuxt @bitrix24/b24icons-vue
# or
npm i @bitrix24/b24ui-nuxt @bitrix24/b24icons-vue
# or
bun add @bitrix24/b24ui-nuxt @bitrix24/b24icons-vue
```
### Nuxt (recommended)
1. Add the module to nuxt.config.ts
```ts
export default defineNuxtConfig({
modules: ['@bitrix24/b24ui-nuxt']
})
```
1. Add styles in your CSS
```css
@import "tailwindcss";
@import "@bitrix24/b24ui-nuxt";
```
1. Wrap your app with `B24App` (e.g., in `app.vue`)
```vue
<template>
<B24App>
<NuxtPage />
</B24App>
</template>
```
Notes:
- Components that use overlays/toasts/tooltips (e.g., Toast, Tooltip, Modal/Slideover programmatically) require `B24App` to provide overlay/toast providers.
- Consider installing VS Code Tailwind CSS IntelliSense and configure it to pick up classes in the `b24ui` prop.
### Vue + Vite
1. Enable the plugin in `vite.config.ts`:
```ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite'
export default defineConfig({
plugins: [vue(), bitrix24UIPluginVite()]
})
```
1. Register the plugin in `main.ts` and the router (if used):
```ts
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import b24UiPlugin from '@bitrix24/b24ui-nuxt/vue-plugin'
import App from './App.vue'
const app = createApp(App)
const router = createRouter({ routes: [], history: createWebHistory() })
app.use(router)
app.use(b24UiPlugin)
app.mount('#app')
```
1. Add styles to your CSS:
```css
@import "tailwindcss";
@import "@bitrix24/b24ui-nuxt";
```
### Naming conventions
- All components are exported with the `B24` prefix (e.g., `B24Button`, `B24Input`, `B24Modal`).
- Many components accept a `b24ui` prop — an object with class hooks for internal parts (tailwind-variants slots). This enables targeted styling.
- Icons come from `@bitrix24/b24icons-vue`.
## Using icons
We provide access to icons via the module `@bitrix24/b24icons-vue`.
Example
```vue
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
</script>
<template>
<RocketIcon class="size-[15px]" />
</template>
```
The list of icons is in the file `node_modules/@bitrix24/b24icons-vue/dist/metadata.json`.
The data format is `{ list: string[] }`. Each line of the `list` array is written in the format `some-type:SomeNameIcon`.
The icon needs to be imported according to the following rule:
```ts
import SomeNameIcon from '@bitrix24/b24icons-vue/some-type/SomeNameIcon'
```
The text will further mention the `IconComponent` type. It means that the imported icon needs to be substituted into `props`.
Example
```vue
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
</script>
<template>
<B24Avatar :icon="RocketIcon" />
</template>
```
## About theme variants
- Most visual props (`color`, `size`, `accent`, `indicator`, `overlayBlur`, etc.) are derived from a theme (imported from `#build/b24ui/<component>`).
- To get the exhaustive set of allowed values, read `theme.variants.<key>` for a component (see demo at `/playgrounds/demo/app/pages/components/button.vue`).
- Typical sets:
- color: `air-*` families (e.g., `air-primary`, `air-secondary-no-accent`, `air-primary-success`, `air-primary-alert`, `air-primary-warning`, `air-primary-copilot`) and more depending on the component.
- size: commonly `xs | sm | md | lg | xl` (exact set depends on component and theme).
- accent: enumerations specific to the component.
## Theme Variants — Enumerated Values
This section lists the concrete enum keys found in the default theme files under `src/theme/*.ts`. Values marked as deprecated exist for compatibility with the old theme and should be avoided in new code.
- Shared tokens
- Sizes (by component):
- Button, Badge, Tabs, FormField: xss, xs, sm, md, lg, xl
- Input, Select: xss, xs, sm, md, lg, xl
- Switch, Progress, Range: xs, sm, md, lg
- Avatar: 3xs, 2xs, xs, sm, md, lg, xl, 2xl, 3xl
- AvatarGroup uses the same labels and adjusts overlap per size
- DescriptionList: sm, md
- Content/TableWrapper: xs, sm, md, lg
- Orientations: horizontal, vertical (where applicable)
- Accents: default, accent, less (for components that expose accent)
- Button
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-secondary, air-secondary-alert, air-secondary-accent, air-secondary-accent-1, air-secondary-accent-2, air-secondary-no-accent, air-tertiary, air-tertiary-accent, air-tertiary-no-accent, air-selection, air-boost; deprecated: default, danger, success, warning, primary, secondary, collab, ai, link
- size: xss, xs, sm, md, lg, xl
- booleans: loading, block, rounded, active, loadingAuto, useDropdown, useWait, useClock, normalCase
- FieldGroup
- orientation: horizontal, vertical
- size: xss, xs, sm, md, lg, xl
- noSplit: true|false
- Badge
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning, air-secondary, air-secondary-alert, air-secondary-accent, air-secondary-accent-1, air-secondary-accent-2, air-tertiary, air-selection; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- size: xss, xs, sm, md, lg, xl
- square: true|false
- inverted: true|false
- useLink: true|false
- useClose: true|false
- Input
- size: xss, xs, sm, md, lg, xl
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- type: hidden, text, password, email, search, tel, url, date, datetime-local, month, week, time, file
- booleans: required, autofocus, rounded, noPadding, noBorder, underline, loading, highlight
- placeholder: string
- tag: string
- tagColor: Badge color variant
- InputNumber
- inherits Input variants
- InputMenu
- inherits Input variants
- adds:
- items: InputMenuItem[] | InputMenuItem[][]
- multiple: boolean
- addNew: boolean
- Textarea
- inherits Input variants
- specific: autoresize (boolean)
- Select
- inherits Input variants
- adds:
- items: SelectItem[] | SelectItem[][]
- multiple: boolean
- SelectMenu
- inherits Select variants
- specific:
- items: SelectMenuItem[] | SelectMenuItem[][]
- adds:
- addNew: boolean
- Checkbox
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- variant: list, card
- indicator: start, end, hidden
- size: xs, sm, md, lg
- booleans: required, disabled, checked
- RadioGroup
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- variant: list, card, table
- orientation: horizontal, vertical
- indicator: start, end, hidden
- size: xs, sm, md, lg
- booleans: disabled, required
- Tabs
- variant: link
- orientation: horizontal, vertical
- size: xss, xs, sm, md, lg, xl
- Range
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- size: xs, sm, md, lg
- orientation: horizontal, vertical
- disabled: boolean
- Progress
- animation: loading, carousel, carousel-inverse, swing, elastic
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning, air-secondary; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- size: xs, sm, md, lg
- orientation: horizontal, vertical
- inverted: boolean
- DescriptionList
- size: sm, md
- orientation: horizontal, vertical
- legend: string
- text: string
- Separator
- accent: default, accent, less
- orientation: horizontal, vertical
- size: thin, thick
- type: solid, dashed, dotted, double
- Skeleton
- accent: default, accent, less
- Kbd
- accent: default, accent, less
- size: sm, md, lg
- Avatar
- size: 3xs, 2xs, xs, sm, md, lg, xl, 2xl, 3xl
- src: string
- icon: IconComponent
- AvatarGroup
- size: 3xs, 2xs, xs, sm, md, lg, xl, 2xl, 3xl
- Switch
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- size: xs, sm, md, lg
- booleans: checked, unchecked, loading, required, disabled
- Alert
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning, air-secondary, air-secondary-alert, air-secondary-accent, air-secondary-accent-1, air-secondary-accent-2, air-tertiary; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- size: sm, md
- orientation: horizontal, vertical
- inverted: boolean
- title: string
- description: string
- Advice
- angle: top, bottom
- description: string
- icon: IconComponent
- avatar: AvatarProps
- DropdownMenu
- items: DropdownMenuItem[] | DropdownMenuItem[][]
- NavigationMenu
- orientation: horizontal, vertical
- items: NavigationMenuItem[] | NavigationMenuItem[][]
- Modal
- title: string
- description: string
- overlayBlur: auto, on, off
- transition: boolean
- fullscreen: boolean
- Slideover
- title: string
- description: string
- overlayBlur: auto, on, off
- side: bottom (preferably), right, left, top
- transition: boolean
- Tooltip
- text: string
- Toast
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning, air-secondary; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- orientation: horizontal, vertical
- title: boolean
- description: string
- icon: IconComponent
- avatar: AvatarProps
- TableWrapper
- size: xs, sm, md, lg
- rounded: boolean
- zebra: boolean
- pinRows: boolean
- pinCols: boolean
- rowHover: boolean
- bordered: boolean
- Chip
- text: string | number
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning, air-secondary, air-secondary-accent, air-secondary-accent-1, air-tertiary; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- size: sm, md, lg
- position: top-right, bottom-right, top-left, bottom-left
- inverted: boolean
- inset: boolean
- standalone: boolean
- hideZero: boolean
- Calendar
- color: air-primary, air-primary-success, air-primary-alert, air-primary-copilot, air-primary-warning; deprecated: default, danger, success, warning, primary, secondary, collab, ai
- size: xs, sm, md, lg
- SidebarLayout
- inner: boolean
- offContentScrollbar: boolean
- useLightContent: boolean
- loading: boolean
- Sidebar, SidebarHeader, SidebarBody, SidebarFooter, Navbar, NavbarSection, NavbarDivider, Popover
- no enumerated variants (style configured via slots)
## Components
Below are key components with their main props, slots, and usage examples. If a prop takes values from `theme.variants`, refer to the theme section above.
Note: many components share icon-related props from a common pattern:
- icon?: IconComponent — leading icon
- avatar?: AvatarProps — leading avatar
- loading?: boolean — loading state (spinner/indicator)
- trailing?: boolean — if true, move icon to the right
- trailingIcon?: IconComponent — right-side icon
Form components also integrate with `B24FormField` for id/name/aria wiring.
### B24App — root provider
Wraps the app and wires overlay/toast/tooltip providers and global config.
Example:
```vue
<B24App>
<RouterView />
</B24App>
```
### B24Button — button/link
Action or navigation. Can act as a link (forwards `Link` props).
Key props:
- label?: string — text or use default slot
- color?: theme.variants.color — e.g., `air-primary`, `air-secondary-no-accent`
- activeColor?: theme.variants.color — active-state color
- depth?: theme.variants.depth — visual depth
- activeDepth?: theme.variants.depth — active-state depth
- size?: theme.variants.size — size
- rounded?: boolean — rounded corners
- block?: boolean — full width
- loading?: boolean — external loading state
- loadingAuto?: boolean — auto loading while awaiting @click Promise
- normalCase?: boolean — disable uppercase transform
- useWait?: boolean — hourglass loader icon
- useClock?: boolean — clock loader icon
- useDropdown?: boolean — show right chevron
- onClick?: `(event: MouseEvent) => void | Promise<void>`
- Link props: subset of `B24Link` (e.g., `to`, `target`, `rel`)
- activeClass?/inactiveClass?: string — link state classes
- class?: any — extra classes for the root
- b24ui?: object with internal part keys (base, baseLine, label, leadingIcon, etc.)
Slots:
- leading — custom leading content (icon/avatar)
- default — main content
- trailing — custom trailing content
Example:
```vue
<B24Button
:icon="MyActionIcon"
:avatar="{ src: '/path/user.png', alt: 'User', size: 'sm' }"
label="Create task"
color="air-primary"
:active-color="'air-primary-alert'"
size="md"
rounded
:block="false"
:loading-auto="true"
:use-wait="false"
use-clock
use-dropdown
to="/tasks"
active-class="italic"
inactive-class="opacity-80"
:b24ui="{ baseLine: 'justify-center min-w-48', leadingIcon: 'text-(--ui-color-copilot-accent-primary)' }"
@click="() => new Promise(res => setTimeout(res, 800))"
/>
```
### B24FieldGroup — grouped button-like elements
Provides `orientation`, `size`, and `noSplit` to child buttons via provide/inject.
Example:
```vue
<B24FieldGroup orientation="horizontal" size="md">
<B24Button label="One" />
<B24Button label="Two" />
<B24Button label="Three" />
</B24FieldGroup>
<B24FieldGroup orientation="horizontal" size="md">
<B24Input class="w-40" name="search" placeholder="Search..." aria-label="Search" />
<B24Button label="Action" loading-auto @click="someAction" />
</B24FieldGroup>
```
### B24Input — text input
Text input with leading/trailing icon/avatar, tag label, and focus highlight.
Key props:
- as?: any — root tag (default div)
- id?, name?
- type?: HTMLInputElement['type'] — default 'text'
- placeholder?: string
- color?: theme.variants.color — ring highlight
- size?: theme.variants.size
- noPadding?: boolean — remove inner padding
- noBorder?: boolean — remove borders/rings
- underline?: boolean — bottom border only
- rounded?: boolean — rounded corners
- required?: boolean
- autocomplete?: 'on'|'off'|...
- autofocus?: boolean, autofocusDelay?: number
- disabled?: boolean
- tag?: string — small label over input
- tagColor?: BadgeProps['color']
- highlight?: boolean
- v-model modelValue?: string|number|null with modifiers string/number/trim/lazy/nullify
- defaultValue?: AcceptableValue
- class?, b24ui?
Slots:
- leading — left area (icon/avatar)
- default — extra content
- trailing — right area (icon)
Example:
```vue
<B24Input
v-model.trim.number.nullify="login"
id="login"
name="login"
placeholder="Login"
color="air-primary"
size="md"
rounded
:underline="false"
:no-border="false"
:no-padding="false"
tag="Login"
tag-color="air-primary"
:highlight="hasError"
autocomplete="off"
:disabled="false"
autofocus
:autofocus-delay="100"
>
<template #leading>
<MyUserIcon />
</template>
<template #trailing>
<MyStatusIcon />
</template>
</B24Input>
```
### B24Textarea — textarea
Props mirror `B24Input` (no type). Supports leading/trailing, size, color, rounded, noBorder/underline/noPadding, v-model.
Example:
```vue
<B24Textarea
placeholder="Description"
color="air-primary"
size="md"
:rounded="true"
v-model.trim="descr"
/>
```
### B24InputNumber — numeric input
Number input with steppers/formatting.
Key props (via Reka NumberField):
- modelValue?, defaultValue?
- min?, max?, step?, stepSnapping?
- formatOptions? — Intl.NumberFormatOptions
- disableWheelChange?, invertWheelChange?
- id?, name?, required?, disabled?, readonly?
- color/size/rounded/noBorder/underline/noPadding and shared props like Input via FormField
Example:
```vue
<B24InputNumber
v-model.number="amount"
:min="0"
:max="100"
:step="1"
:format-options="{ maximumFractionDigits: 0 }"
color="air-primary"
size="md"
/>
```
### B24Select — select
Single or multiple selection. Supports groups, label/separator, icons/avatars/chips in items.
Key props:
- placeholder?: string
- color?: theme.variants.color, size?: theme.variants.size
- noPadding?, noBorder?, underline?, rounded?
- tag?: string
- tagColor?: BadgeProps['color']
- trailingIcon?: IconComponent — open icon (default chevron)
- selectedIcon?: IconComponent — selected item icon (default check)
- content?: popper/content props
- portal?: boolean | string | HTMLElement
- valueKey?: string (default 'value'), labelKey?: string (default 'label')
- items?: Array<SelectItem | SelectItem[]> — primitives or objects: { label?, value?, type?: 'label'|'separator'|'item', icon?, avatar?, chip?, disabled?, onSelect?, class?, b24ui? }
- defaultValue?, v-model:modelValue?
- multiple?: boolean
- highlight?: boolean
- autofocus?, autofocusDelay?
- class?, b24ui?
Slots:
- leading, default (trigger text), trailing — trigger slots
- item, item-leading, item-label, item-trailing — item slots
- content-top, content-bottom — custom content above/below the list
Example:
```vue
<B24Select
v-model="selectedValues"
:items="[
{ type: 'label', label: 'Team' },
{ label: 'Marketing', value: 'mkt', icon: MarketingIcon },
{ label: 'Sales', value: 'sales', avatar: { src: '/avatars/sales.png' } },
{ type: 'separator' },
{ label: 'AI', value: 'ai', chip: { color: 'ai', text: 'AI' } }
]"
placeholder="Choose department"
color="air-primary"
size="md"
:rounded="true"
:multiple="true"
value-key="value"
label-key="label"
:content="{ side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }"
:portal="true"
>
<template #leading="{ open }">
<MyFilterIcon :class="open ? 'rotate-180' : ''" />
</template>
<template #item-trailing>
<!-- custom right slot -->
</template>
</B24Select>
```
### B24SelectMenu / B24InputMenu — ready-made menu patterns
Prebuilt UX for dropdown menus on inputs. Props mirror Select/Input with menu additions. See `/docs/components/select-menu.md` and `/docs/components/input-menu.md`.
### B24Checkbox — checkbox
Boolean control with optional indeterminate.
Key props:
- as?: any — container (default div, for variant=list)
- label?: string, description?: string
- color?: theme.variants.color
- variant?: theme.variants.variant — e.g., 'list' | 'inline' (see theme)
- size?: theme.variants.size
- indicator?: theme.variants.indicator — indicator position ('start'|'end')
- required?, disabled?, name?, id?, value?, defaultValue?
- class?, b24ui?
Slots:
- label({ label }) — custom label
- description({ description }) — custom description
Example:
```vue
<B24Checkbox
v-model="checked"
label="Accept terms"
description="Required"
color="air-primary"
size="md"
indicator="start"
required
/>
```
### B24RadioGroup — radio group
Choose one option.
Key props:
- as?: any
- legend?: string — group heading
- items?: Array<{ label?, description?, disabled?, value?, class?, b24ui? } | string | number>
- valueKey?: string = 'value', labelKey?: string = 'label', descriptionKey?: string = 'description'
- size?: theme.variants.size, variant?: theme.variants.variant, color?: theme.variants.color
- orientation?: 'vertical'|'horizontal'
- indicator?: theme.variants.indicator — radio circle position
- v-model:modelValue?, defaultValue?
- name?, required?
- class?, b24ui?
Slots:
- legend — header slot
- label({ item, modelValue }) — item label
- description({ item, modelValue }) — item description
Example:
```vue
<B24RadioGroup
v-model="priority"
legend="Priority"
:items="[
{ label: 'Low', value: 'low' },
{ label: 'Medium', value: 'med', description: 'Default' },
{ label: 'High', value: 'high', disabled: true }
]"
color="air-primary"
size="md"
orientation="vertical"
/>
```
### B24Form & B24FormField — form and field
- `B24FormField` renders label/description/hint/help/error and binds ARIA to a child control.
- `B24Form` integrates fields and manages submit/validation (see `/docs/components/form.md`).
B24FormField props:
- as?: any
- name?: string — field name (for mapping errors)
- errorPattern?: RegExp — match error by pattern
- label?, description?, help?, error?, hint?
- size?: theme.variants.size, required?: boolean
- eagerValidation?: boolean — start validating on input immediately
- validateOnInputDelay?: number (default 300ms)
- class?, b24ui?
B24FormField slots:
- label({ label })
- hint({ hint })
- description({ description })
- help({ help })
- error({ error })
- default({ error })
Example:
```vue
<B24Form @submit="onSubmit">
<B24FormField name="email" label="Email" required hint="Work email">
<template #default="{ error }">
<B24Input
v-model.trim="email"
type="email"
:highlight="!!error"
placeholder="name@company.com"
/>
</template>
</B24FormField>
<B24Button type="submit" color="air-primary" loading-auto>Submit</B24Button>
</B24Form>
```
### B24Avatar / B24AvatarGroup — avatar and group
Avatar props:
- as?: any (default span)
- src?, alt?, icon?: IconComponent, text?: string
- size?: theme.variants.size (xs/sm/md/lg... depends on theme)
- chip?: boolean | ChipProps — chip framing
- class?, style?, b24ui?
Slot: default — custom fallback
Example:
```vue
<B24Avatar src="/u.png" alt="User" size="md" />
<B24Avatar :icon="UserIcon" size="sm" />
<B24Avatar text="AB" chip size="lg" />
```
### B24Badge — badge
Props:
- as?: any = 'span'
- label?: string|number
- color?: theme.variants.color (incl. air-* family)
- inverted?: boolean — invert color
- size?: theme.variants.size
- square?: boolean — equal paddings
- useLink?: boolean — underline on hover
- useClose?: boolean — close (×) icon
- `onCloseClick?: (event: MouseEvent) => void | Promise<any>
- icon/avatar/leading, class?, b24ui?
Slots: leading, default, trailing
Example:
```vue
<B24Badge
:icon="InfoIcon"
label="New"
color="air-primary"
size="sm"
use-link
use-close
@onCloseClick="() => console.log('closed')"
/>
```
### B24Accordion / B24Collapsible — accordion/collapsible
`B24Accordion` props:
- type: 'single'|'multiple'
- collapsible?: boolean (default true)
- unmountOnHide?: boolean (default true)
- items?: Array<{ label?, icon?, trailingIcon?, slot?, content?, value?, disabled?, class?, b24ui? }>
- trailingIcon?: IconComponent — default right icon
- labelKey?: string = 'label'
- disabled?, class?, b24ui?
Slots: leading({ item,index,open }), default({ item,... }), trailing(...), content(...), body(...), dynamic slots by `slot` name.
Example:
```vue
<B24Accordion
:items="[
{ label: 'First', content: 'Content 1', icon: DocIcon },
{ label: 'Second', slot: 'custom', trailingIcon: ChevronIcon }
]"
>
<template #custom-body="{ item }">
<div class="p-[12px]">Custom body for: {{ item.label }}</div>
</template>
</B24Accordion>
```
`B24Collapsible` — wrapper for show/hide with default trigger and `#content` slot.
### B24Chip — chip
Can wrap content (e.g., a button) or be standalone.
Example:
```vue
<B24Chip text="1">
<B24Button label="Button" />
</B24Chip>
```
### B24Separator — separator
A horizontal or vertical separator with optional label, icon, or avatar.
Key props:
- as?: any = 'div'
- label?: string
- icon?: IconComponent
- avatar?: AvatarProps
- accent?: theme.variants.accent — visual accent
- size?: theme.variants.size — line thickness (e.g., thin)
- type?: theme.variants.type — line style (e.g., solid)
- orientation?: 'horizontal' | 'vertical'
- decorative?: boolean — mark as decorative for a11y
- class?, b24ui?
Example:
```vue
<B24Separator label="Or" />
<B24Separator orientation="vertical" decorative class="h-8" />
```
### B24Skeleton — skeleton loader
Accessible loading placeholder.
Key props:
- as?: any = 'div'
- accent?: theme.variants.accent — intensity/accent color
- class?, b24ui?
Example:
```vue
<!-- Avatar and two lines -->
<div class="flex items-center gap-3">
<B24Skeleton class="h-12 w-12 rounded-full" />
<div class="space-y-2">
<B24Skeleton class="h-4 w-[150px]" />
<B24Skeleton class="h-4 w-[100px]" />
</div>
</div>
```
### B24Countdown — countdown
Visual countdown with events, textual or circular display.
Key props:
- as?: any = 'span'
- size?: theme.variants.size
- seconds?: number | string — total seconds to count
- showMinutes?: boolean = true — show mm:ss instead of seconds
- useCircle?: boolean = false — circular progress ring
- interval?: number = 1000 — tick interval (ms)
- needStartImmediately?: boolean = true — autostart
- emitEvents?: boolean = true — emit lifecycle events
- now?: () => number — supply custom time source
- class?, b24ui?
Emits: start, progress(CountdownData), end, abort
Slots:
- leading — icon/avatar before label
- default({ formatTime, days, hours, minutes, seconds, totalSeconds, ... })
Example:
```vue
<B24Countdown :seconds="90" @end="notifyDone">
<template #default="{ formatTime }">
<span class="tabular-nums">{{ formatTime }}</span>
</template>
</B24Countdown>
<B24Countdown :seconds="30" use-circle />
```
### B24DescriptionList — description list
Structured label/description pairs with optional leading icon/avatar and inline actions.
Key props:
- legend?: string — heading above the list
- text?: string — intro paragraph
- items?: Array<{ label?, description?, icon?, avatar?, actions?, orientation?: 'vertical'|'horizontal', class?, b24ui?, slot? }>
- labelKey?: string = 'label'
- descriptionKey?: string = 'description'
- size?: theme.variants.size
- class?, b24ui?
Slots:
- legend, text, footer
- content-top/content/content-bottom — per-item wrappers
- leading({ item, index }) — icon/avatar area
- label({ item, index }) — label
- description({ item, index }) — description
- actions({ item, index }) — inline actions
Example:
```vue
<B24DescriptionList
legend="Task"
:items="[
{ icon: InfoIcon, label: 'Owner', description: 'John Smith' },
{ avatar: { src: '/u.png' }, label: 'Assignee', description: 'Mary' , actions: [{ label: 'Change' }]},
{ label: 'Status', description: 'In progress', orientation: 'horizontal' }
]"
/>
```
### B24TableWrapper — table wrapper (content)
Wrapper for tables with scrollbars, zebra, pinning, and borders. Lives under content theme.
Key props:
- as?: any = 'div'
- size?: theme.variants.size
- rounded?: boolean
- zebra?: boolean — striped rows
- pinRows?: boolean — sticky header/footer rows
- pinCols?: boolean — sticky first/last columns
- rowHover?: boolean
- bordered?: boolean
- scrollbarThin?: boolean = true
- class?, b24ui?
Example:
```vue
<B24TableWrapper zebra bordered rounded>
<table>
<colgroup>
<col>
<col class="min-w-[200px]">
</colgroup>
<thead>
<tr>
<th>Name</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>Owner</td>
</tr>
<tr>
<td>Bob</td>
<td>Editor</td>
</tr>
</tbody>
<tfoot>
<tr>
<th />
<td>Deal Name</td>
</tr>
</tfoot>
</table>
</B24TableWrapper>
```
### B24Kbd — keyboard key
Renders a key label; used inside Tooltip and menus.
Key props:
- as?: any = 'kbd'
- value?: string — key name (e.g., 'meta', 'ctrl', 'alt', 'win', 'command', 'shift', 'control', 'option', 'enter', 'delete', 'backspace', 'escape', 'tab', 'capslock', 'arrowup', 'arrowright', 'arrowdown', 'arrowleft', 'pageup', 'pagedown', 'home', 'end' )
- accent?: theme.variants.accent
- size?: theme.variants.size (sm/md/lg depends on theme)
- class?
Example:
```vue
Find <div class="inline-flex items-center justify-center gap-[4px]"><B24Kbd value="meta" /> <B24Kbd value="k" /></div>
```
### B24DropdownMenu — dropdown menu
Slots: trigger (default asChild) and content (via `B24DropdownMenuContent`).
Example:
```vue
<B24DropdownMenu
:items="dropdownMenuItems"
>
<B24Button label="Open menu" use-dropdown />
</B24DropdownMenu>
```
### B24NavigationMenu — navigation menu
Hierarchical menu built on Reka NavigationMenu and Accordion. Props: items[], hover/click delays, disabled, type/collapsible, unmountOnHide.
```vue
<B24NavigationMenu
:items="navigationMenuItems"
orientation="horizontal"
/>
```
### B24Navbar and sections
- `B24Navbar` — container
- `B24NavbarSection`, `B24NavbarDivider`, `B24NavbarSpacer` — sectioning/dividers in the header.
### B24Progress — progress bar
Example:
```vue
<B24Progress
:value="60"
:max="100"
color="air-primary"
/>
```
### B24Range — range slider
Props: min/max/step, inverted, minStepsBetweenThumbs; name/disabled; size/color.
Example:
```vue
<B24Range
v-model="value"
:min="0"
:max="100"
:step="1"
/>
```
### B24Switch — switch
Boolean toggle.
Example:
```vue
<B24Switch
v-model="enabled"
color="air-primary"
/>
```
### B24Tabs — tabs
Slots for tab list and panels.
```vue
<B24Tabs
v-model="active"
:items="[
{
label: 'Account',
description: 'Make changes to your account here. Click save when you\'re done.',
icon: UserIcon,
slot: 'account'
},
{
label: 'Password',
description: 'Change your password here. After saving, you\'ll be logged out.',
icon: Shield2ContourIcon,
slot: 'password'
}
]"
:items="items"
class="w-full"
>
<template #account="{ item }">
<ProseP accent="less" class="mb-4 text-md">
{{ item.description }}
</ProseP>
</template>
<template #password="{ item }">
<ProseP accent="less" small class="mb-4">
{{ item.description }}
</ProseP>
</template>
</B24Tabs>
```
### B24Tooltip — tooltip
Example:
```vue
<B24Tooltip text="Tooltip">
<B24Button :icon="HelpIcon" />
</B24Tooltip>
```
### B24Popover — popover
Use trigger and content slots; supports portal and positioning.
Example:
```vue
<B24Popover :b24ui="{ content: 'p-[10px]' }">
<B24Button label="Open" />
<template #content>
<ProseP>
Some text
</ProseP>
</template>
</B24Popover>
```
### B24Modal — modal dialog
Key props:
- title?, description?
- content?: Partial<DialogContentProps & Emits>
- overlay?: boolean
- overlayBlur?: 'auto'|'on'|'off'
- transition?: boolean
- fullscreen?: boolean
- portal?: boolean | string | HTMLElement
- close?: boolean | Partial<ButtonProps>
- closeIcon?: IconComponent
- dismissible?: boolean
- scrollbarThin?: boolean
- open/defaultOpen/modal (from Reka DialogRoot)
- class?, b24ui?
Slots:
- default({ open }) — trigger (asChild)
- content({ close }) — full custom content
- header({ close }), title, description, actions, close({ close, b24ui })
- body({ close }), footer({ close })
Example:
```vue
<B24Modal
title="Title"
description="Description"
>
<B24Button color="air-primary">Open</B24Button>
<template #body>
<ProseP>Modal content</ProseP>
</template>
<template #footer="{ close }">
<div class="flex flex-row gap-[10px]">
<B24Button color="air-primary" @click="save">Save</B24Button>
<B24Button color="air-tertiary" @click="close">Cancel</B24Button>
</div>
</template>
</B24Modal>
```
### B24Slideover — side panel
Like `B24Modal` but slides in from a side.
```vue
<B24Slideover :open="open" @update:open="v => open = v">
<template #body>
<ProseP>Content</ProseP>
</template>
<template #footer="{ close }">
<div class="w-1/5 flex justify-start" />
<div class="w-full flex flex-row justify-center gap-[10px]">
<B24Button label="Send" color="air-primary" @click="send" />
<B24Button label="Cancel" color="air-tertiary" @click="close" />
</div>
<div class="w-1/5 flex justify-end">
<B24Button label="Full version" size="sm" color="air-tertiary-no-accent" @click="someAction" />
</div>
</template>
</B24Slideover>
```
### B24Toast — toasts
- `B24Toast` — a toast item (usually use `useToast` instead).
Example (via composable):
```ts
const toast = useToast()
toast.add({ title: 'Success', description: 'Saved', color: 'air-primary-success' })
```
### Sidebar: B24SidebarLayout and parts
- `B24SidebarLayout` — main layout with header/body/footer/sections.
- Parts: `B24Sidebar`, `B24SidebarHeader`, `B24SidebarBody`, `B24SidebarFooter`, `B24SidebarSection`, `B24SidebarHeading`, `B24SidebarSpacer`.
Example:
```vue
<B24SidebarLayout>
<template #sidebar>
<B24SidebarHeader>
<!-- Navigation header -->
<div class="h-full flex items-center relative my-0 ps-[25px] pe-xs rtl:pe-[25px]">
<ProseH4 class="font-(--ui-font-weight-medium) mb-0">SideBar</ProseH4>
</div>
</B24SidebarHeader>
<B24SidebarBody>
<!-- Navigation elements -->
<B24SidebarSection>
<B24NavigationMenu
:items="[{ label: 'Page 1', type: 'trigger', active: true }, { label: 'Page 2', type: 'trigger' }]"
orientation="vertical"
/>
</B24SidebarSection>
<B24SidebarSpacer />
<B24SidebarSection>
<B24NavigationMenu
:items="[{ label: 'Page 3', type: 'trigger' }, { label: 'Page 4', type: 'trigger' }]"
orientation="vertical"
/>
</B24SidebarSection>
</B24SidebarBody>
<B24SidebarFooter>
<!-- Navigation footer -->
<B24SidebarSection>
<B24Link
class="text-(length:--ui-font-size-sm) mb-2 flex flex-row items-center justify-between"
to="https://bitrix24.github.io/b24ui/"
target="_blank"
>
<div>@bitrix24/b24ui</div>
<GoToLIcon class="size-4" />
</B24Link>
<B24Button
block
label="Use our Vue starter"
color="air-boost"
size="sm"
:icon="RocketIcon"
to="https://bitrix24.github.io/b24ui/"
target="_blank"
/>
</B24SidebarSection>
</B24SidebarFooter>
</template>
<template #navbar>
<!-- Your navigation bar -->
<B24NavbarSection class="hidden sm:inline-flex">
<B24NavigationMenu
:items="[{ label: 'Page 1', type: 'trigger', active: true }, { label: 'Page 2', type: 'trigger' }]"
orientation="horizontal"
/>
</B24NavbarSection>
<B24NavbarSpacer />
<B24NavbarSection class="flex-row items-center justify-start gap-4">
<B24DropdownMenu
arrow
:items="[{ label: 'Value 1' }, { label: 'Value 2' }]"
>
<B24Button
color="air-secondary-accent"
size="xs"
rounded
use-dropdown
label="Action"
/>
</B24DropdownMenu>
<B24Switch
v-model="checkedUseLightContent"
size="xs"
/>
<B24Button
label="Reload"
color="air-secondary-accent"
rounded
size="xs"
loading-auto
@click="handleAction"
/>
</B24NavbarSection>
</template>
<template #content-top>
<div class="w-full flex flex-col gap-[20px]">
<div class="backdrop-blur-sm backdrop-brightness-110 px-[15px] py-[10px] flex flex-col items-start justify-between gap-[20px]">
<div class="w-full flex flex-row items-center justify-between gap-[20px]">
<div class="flex-1 flex flex-row items-center justify-end gap-[12px]">
<B24Avatar
:icon="BusinesProcessStagesIcon"
alt="Workflows"
size="xl"
:b24ui="{
root: 'bg-(--ui-color-primary-alt)',
icon: 'size-[36px] text-(--ui-color-palette-white-base)'
}"
/>
<div class="flex-1">
<!-- Page Title -->
<ProseH1 class="text-(--b24ui-typography-label-color) leading-[29px] font-(--ui-font-weight-light)">
Some title
</ProseH1>
</div>
</div>
<div class="flex-1 hidden sm:flex flex-row items-center justify-end gap-[12px]">
<B24DropdownMenu
:items="[{ label: 'Value 1' }, { label: 'Value 2' }]"
arrow
:content="{ side: 'bottom', align: 'center' }"
>
<B24Button size="sm" :icon="MoreMIcon" color="air-secondary-accent" />
</B24DropdownMenu>
</div>
</div>
<div>
<MockSidebarLayoutMenu orientation="horizontal" />
</div>
</div>
<!-- Page SubTitle -->
<ProseH2 class="font-(--ui-font-weight-semi-bold) mb-0">
Some sub-title
</ProseH2>
</div>
</template>
<template #content-actions>
<!-- Actions on page -->
<B24Button
color="air-secondary-accent"
label="Action"
loading-auto
@click="handleAction"
/>
</template>
<!-- Main content -->
<div>
<ProseP>Your main content goes here</ProseP>
</div>
<template #content-bottom>
<!-- Bottom of page -->
<ProseP small accent="less-more" class="px-[22px] pb-[2px]">
Footer or additional information
</ProseP>
</template>
</B24SidebarLayout>
```
### Content & Prose
- Prose components (`ProseH1/H2/...`, `ProseP`, `ProseA`, `ProseTable`, etc.) — styled content tags.
### Alert / Advice — alerts and tips
Simple information blocks with slots and color/size variants.
Example:
```vue
<B24Alert
:icon="SignIcon"
:title="title"
:description="description"
:color="air-primary"
inverted
/>
<B24Advice :description="description" :avatar="{ src: '/b24ui/avatar/assistant.png' }" />
<B24Advice :avatar="{ src: '/b24ui/avatar/assistant.png' }">
<ProseP>Typically, instructions on how to add a SAML application and add the ACS URL and SP Entity ID can be found in the Microsoft Azure technical documentation. </ProseP>
<B24Link to="https://github.com/bitrix24/b24ui/" target="_blank" is-action>
Read more
</B24Link>
</B24Advice>
<B24Advice angle="top" :avatar="{ src: '/b24ui/avatar/employee.png' }">
<div class="flex flex-col items-start justify-between gap-1.5">
<ProseH3>
Reference information
</ProseH3>
<ProseP>Typically, instructions on how to add a SAML application and add the ACS URL and SP Entity ID can be found in the Microsoft Azure technical documentation.</ProseP>
<div class="mt-2 flex flex-row flex-wrap items-start justify-between gap-2">
<B24Button size="xs" color="air-primary" label="some action 1" />
<B24Button size="xs" color="air-secondary" label="some action 2" />
<B24Button size="xs" color="air-tertiary-no-accent" :icon="DotsIcon" />
</div>
</div>
</B24Advice>
```
### Calendar — calendar
Date/range picker.
```vue
<script setup lang="ts">
import { shallowRef } from 'vue'
import { CalendarDate } from '@internationalized/date'
const value = shallowRef(new CalendarDate(2012, 4, 12))
</script>
<template>
<B24Calendar v-model="value" />
</template>
```
### Link — link
Low-level link, used by `B24Button`. Props mirror routing / target / activeClass.
```vue
<B24Link to="/" target="_blank">Home</B24Link>
<B24Link is-action to="https://bitrix24.github.io/b24ui/components/link.html" target="_blank">
Link action
</B24Link>
<B24Link is-action>
Button action
</B24Link>
```
## Composables (core)
### useToast
API for toasts.
- `add(toast: Partial<Toast>): Toast` — add
- `update(id, patch)`
- `remove(id)`
- `clear()`
- `toasts: Ref<Toast[]>`
Example:
```ts
const toast = useToast()
toast.add({ title: 'Saved', description: 'Changes applied', color: 'air-primary-success' })
```
### useOverlay
Programmatic overlays (modals/slideover):
- `create(component, { defaultOpen?, props?, destroyOnClose? }) => instance`
- `instance.open(props?) => PromiseLike` with `result`
- `instance.close(value?)`
- `instance.patch(props)`
- `close(id)`, `closeAll()`, `unmount(id)`, `isOpen(id)`, `overlays`
Example:
```ts
const overlay = useOverlay()
const modal = overlay.create(MyModal, { props: { title: 'Welcome' } })
const opened = modal.open()
const result = await opened.result // wait for emit('close', payload)
```
### defineShortcuts
Register global keyboard shortcuts.
```ts
import { defineShortcuts } from '@bitrix24/b24ui-nuxt'
defineShortcuts({
'meta_k': () => openCommandPalette(),
'escape': () => closeAllOverlays()
})
```
### useLocale / defineLocale
Internationalization helpers.
### useConfetti
Trigger confetti animation.
```ts
import { useConfetti } from '@bitrix24/b24ui-nuxt'
const confetti = useConfetti()
confetti.fire()
```
## Patterns and Best Practices
- Always wrap apps that use overlays/tooltips/toasts with `B24App`.
- For complex inputs, use `B24FormField` for correct ARIA wiring and error messages.
- Leverage slots (`leading`, `trailing`, `content-*`) to match Bitrix24 UX precisely.
- For exact variant values, enumerate from `theme.variants` for each component at build/runtime.
## Links
- Docs: <https://bitrix24.github.io/b24ui/>
- Icons: <https://bitrix24.github.io/b24icons/>
- Demo playground: `/playgrounds/demo/app/`
## Exhaustiveness note on variant values
Some props are bound to theme tokens (theme variants). Get the allowed values programmatically:
```ts
import theme from '#build/b24ui/button'
const colors = Object.keys(theme.variants.color)
const sizes = Object.keys(theme.variants.size)
```
This guarantees AI agents use only the values available in the current build theme.