UNPKG

@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
# 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.