# Introduction > Bitrix24 UI is a comprehensive UI library for Vue and Nuxt applications, offering a collection of fully styled and accessible components. ## What is Bitrix24 UI? A UI library for Bitrix24 based on [Nuxt UI](https://ui.nuxt.com){rel="nofollow"}. This modern UI library, based on [Reka UI](https://reka-ui.com/){rel="nofollow"}, [Tailwind CSS](https://tailwindcss.com/){rel="nofollow"}, and [Tailwind Variants](https://www.tailwind-variants.org/){rel="nofollow"}, allows you to create beautiful and accessible applications with over 100 ready-to-use components. > Developer Experience First > Intuitive APIs, excellent TypeScript support, auto-completion, and comprehensive docs.> Beautiful by Default > A modern, clean design out of the box with a theme you can adapt in minutes.> Accessible by Default > WAI-ARIA compliant with keyboard navigation, focus management, and screen reader support.> Production Ready > 100+ battle-tested components used by thousands of applications in production. ## What's new in v2? We support almost all components of Nuxt UI v4. Read more in the [migration guide](https://bitrix24.github.io/b24ui/raw/docs/getting-started/migration/v2.md). ## Core technologies ### Reka UI Bitrix24 UI is built on top of [Reka UI](https://reka-ui.com/){rel="nofollow"} as a foundation for the components: - **WAI-ARIA Compliance**: Follows [WAI-ARIA authoring practices](https://reka-ui.com/docs/overview/accessibility){rel="nofollow"} with proper semantics and roles - **Keyboard Navigation**: Built-in keyboard support for complex components like tabs and dialogs - **Focus Management**: Intelligent focus handling that moves focus based on user interactions - **Accessible Labels**: Abstractions to simplify labeling controls for screen readers ### Tailwind CSS Bitrix24 UI integrates the latest [Tailwind CSS](https://tailwindcss.com/){rel="nofollow"} v4, bringing significant improvements: - **5x Faster Builds**: Full builds up to 5x faster, incremental builds over 100x faster - **Unified Toolchain**: Built-in import handling, vendor prefixing, and syntax transforms - **CSS-first Configuration**: Customize and extend directly in CSS instead of JavaScript - **Modern Web Features**: Container queries, cascade layers, wide-gamut colors, and more ### Tailwind Variants Bitrix24 UI takes advantage of [Tailwind Variants](https://www.tailwind-variants.org/){rel="nofollow"} to provide a powerful theming system: - **Dynamic Styling**: Flexible component variants with a powerful API - **Type Safety**: Full TypeScript support with auto-completion - **Conflict Resolution**: Efficient merging of conflicting styles ## Key features ### Ecosystem integration Bitrix24 UI integrates with the Nuxt ecosystem to provide a seamless development experience: - [**@bitrix24/b24icons**](https://bitrix24.github.io/b24icons/){rel="nofollow"}: Bitrix24 Icons for Web Applications - [**Color Mode**](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/color-mode.md): Dark and Light mode with auto-detection - [**i18n**](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/i18n.md): Internationalize your components with 50+ languages - [**Content**](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/content.md): Beautiful typography out of the box ### Vue Compatibility Bitrix24 UI works with any Vue project. Simply add the Vite and Vue plugins to your configuration: - **Auto-imports**: Components and composables are automatically imported and available globally - **Theming System**: Full theming support with customizable colors, sizes, variants, and more - **Developer Experience**: Complete TypeScript support with IntelliSense and auto-completion > [Vue installation guide](https://bitrix24.github.io/b24ui/raw/docs/getting-started/installation/vue.md) > Learn how to install and configure Bitrix24 UI in a Vue project in the **Vue installation guide**. ### TypeScript Support Bitrix24 UI provides comprehensive TypeScript integration for a superior developer experience: - **Auto-completion**: For all component props, slots, and events - **Generic Components**: Using [Vue Generics](https://vuejs.org/api/sfc-script-setup.html#generics){rel="nofollow"} - **Type-safe Theming**: In `app.config.ts` - **IntelliSense**: Throughout your entire codebase ## FAQ **What are the differences between Bitrix24 UI and Nuxt UI?** Basically, none. Bitrix24 UI is based on Nuxt UI. However, it's styled to match the overall look of Bitrix24. **Is Bitrix24 UI free to use?** Yes! Bitrix24 UI is completely free and open source under the MIT license. All 100+ components are available to everyone. **Can I use Bitrix24 UI with Vue without Nuxt?** Yes! While optimized for Nuxt, Bitrix24 UI works perfectly with standalone Vue projects via our Vite plugin. You can follow the [installation guide](https://bitrix24.github.io/b24ui/raw/docs/getting-started/installation/vue.md) to get started.**Will Bitrix24 UI work with other CSS frameworks like UnoCSS?** No. Bitrix24 UI is designed exclusively for Tailwind CSS. UnoCSS support would require significant architecture changes due to different class naming conventions. **How does Bitrix24 UI handle accessibility?** Through [Reka UI](https://reka-ui.com/docs/overview/accessibility){rel="nofollow"} integration, Bitrix24 UI provides automatic ARIA attributes, keyboard navigation, focus management, and screen reader support. While offering a strong foundation, testing in your specific use case remains important.**How is Bitrix24 UI tested?** Bitrix24 UI ensures reliability with 1000+ Vitest tests covering core functionality and accessibility. **Is Bitrix24 UI production-ready?** Yes! Bitrix24 UI is used in production by thousands of applications with extensive tests, regular updates, and active maintenance. --- # Installation > Learn how to install and configure Bitrix24 UI in your Nuxt application. > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/getting-started/installation/vue.md) > Looking for the **Vue** version? ## Setup ### Use our Nuxt Starter Start your project using the [bitrix24/starter-b24ui](https://github.com/bitrix24/starter-b24ui){rel="nofollow"} template with Bitrix24 UI pre-configured. Create a new project locally by running the following command: ```bash \[Terminal] git clone https://github.com/bitrix24/starter-b24ui.git cd pnpm install pnpm run dev ``` > !NOTE > The `` argument is the name of the directory where the project will be created, replace it with your project name. ### Add to a Nuxt project ::steps{level="4"} #### Install the Bitrix24 UI package ```bash \[pnpm] pnpm add @bitrix24/b24ui-nuxt ``````bash \[yarn] yarn add @bitrix24/b24ui-nuxt ``````bash \[npm] npm install @bitrix24/b24ui-nuxt ``````bash \[bun] bun add @bitrix24/b24ui-nuxt ``` > !WARNING > If you're using **pnpm**, ensure that you either set [`shamefully-hoist=true`](https://pnpm.io/npmrc#shamefully-hoist){rel="nofollow"} in your `.npmrc` file or install `tailwindcss` in your project's root directory. #### Add the Bitrix24 UI module in your `nuxt.config.ts`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['@bitrix24/b24ui-nuxt'] }) ``` #### Import Tailwind CSS and Bitrix24 UI in your CSS ```css \[app/assets/css/main.css] @import "tailwindcss"; @import "@bitrix24/b24ui-nuxt"; ``````ts \[nuxt.config.ts] {3} export default defineNuxtConfig({ modules: ['@bitrix24/b24ui-nuxt'], css: ['~/assets/css/main.css'] }) ``` > !NOTE > It's recommended to install the [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss){rel="nofollow"} extension for VSCode and add the following settings: > > ```json [.vscode/settings.json] > { > "files.associations": { > "*.css": "tailwindcss" > }, > "editor.quickSuggestions": { > "strings": "on" > }, > "tailwindCSS.classAttributes": ["class", "b24ui"], > "tailwindCSS.experimental.classRegex": [ > ["b24ui:\\s*{([^)]*)\\s*}", "(?:'|\"|`)([^']*)(?:'|\"|`)"] > ] > } > ``` #### Wrap your app with App component ```vue [app.vue] ``` > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/components/app.md) > The `App` component provides global configurations and is required for **Toast**, **Tooltip** components to work as well as **Programmatic Overlays**. :: ## Options You can customize Bitrix24 UI by providing options in your `nuxt.config.ts`. ### `colorMode` Use the `colorMode` option to enable or disable the color mode integration from `@vueuse/core`. - Default: `true`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} ```ts [nuxt.config.ts] {4-6} export default defineNuxtConfig({ modules: ['@bitrix24/b24ui-nuxt'], css: ['~/assets/css/main.css'], b24ui: { colorMode: false } }) ``` ### `theme.prefix` Use the `theme.prefix` option to configure the same prefix you set on your Tailwind CSS import. This ensures Bitrix24 UI components use the correct prefixed utility classes and CSS variables. ```ts \[nuxt.config.ts] {4-8} export default defineNuxtConfig({ modules: ['@bitrix24/b24ui-nuxt'], css: ['~/assets/css/main.css'], b24ui: { theme: { prefix: 'tw' } } }) ``````css \[app/assets/css/main.css] {1} @import "tailwindcss" prefix(tw); @import "@bitrix24/b24ui-nuxt"; ``` This will automatically prefix all Tailwind utility classes and CSS variables in Bitrix24 UI component themes: ```html ``` > [!NOTE](https://tailwindcss.com/docs/styling-with-utility-classes#using-the-prefix-option) > Learn more about using a prefix in the Tailwind CSS documentation. ### `mdc` Use the `mdc` option to force the import of Bitrix24 UI `` components even if `@nuxtjs/mdc` or `@nuxt/content` is not installed. - Default: `true`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} ```ts [nuxt.config.ts] {4-6} export default defineNuxtConfig({ modules: ['@bitrix24/b24ui-nuxt'], css: ['~/assets/css/main.css'], b24ui: { mdc: false } }) ``` ### `content` Use the `content` option to force the import of Bitrix24 UI `` and `` components even if `@nuxt/content` is not installed (`@nuxtjs/mdc` is installed by `@nuxt/content`). - Default: `false`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} ```ts [nuxt.config.ts] {4-6} export default defineNuxtConfig({ modules: ['@bitrix24/b24ui-nuxt'], css: ['~/assets/css/main.css'], b24ui: { content: true } }) ``` ### `experimental.componentDetection` Use the `experimental.componentDetection` option to enable automatic component detection for tree-shaking. This feature scans your source code to detect which components are actually used and only generates the necessary CSS for those components (including their dependencies). - Default: `false`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - Type: `boolean | string[]`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} **Enable automatic detection:** ```ts [nuxt.config.ts] {4-8} export default defineNuxtConfig({ modules: ['@bitrix24/b24ui-nuxt'], css: ['~/assets/css/main.css'], b24ui: { experimental: { componentDetection: true } } }) ``` **Include additional components for dynamic usage:** ```ts [nuxt.config.ts] {4-8} export default defineNuxtConfig({ modules: ['@bitrix24/b24ui-nuxt'], css: ['~/assets/css/main.css'], b24ui: { experimental: { componentDetection: ['Modal', 'Dropdown', 'Popover'] } } }) ``` > !NOTE > When providing an array of component names, automatic detection is enabled and these components (along with their dependencies) are guaranteed to be included. This is useful for dynamic components like `` that can't be statically analyzed. --- # Installation > Learn how to install and configure Bitrix24 UI in your Vue application, compatible with both plain Vite and Inertia. > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/getting-started/installation/nuxt.md) > Looking for the **Nuxt** version? ## Setup ### Use our Vue starter Start your project using the [bitrix24/starter-b24ui-vue](https://github.com/bitrix24/starter-b24ui-vue){rel="nofollow"} template with Bitrix24 UI pre-configured. Create a new project locally by running the following command: ```bash \[Terminal] git clone https://github.com/bitrix24/starter-b24ui-vue.git cd pnpm install pnpm run dev ``` > !NOTE > The `` argument is the name of the directory where the project will be created, replace it with your project name. ### Add to a Vue project ::steps{level="4"} #### Install the Bitrix24 UI package ```bash \[pnpm] pnpm add @bitrix24/b24ui-nuxt ``````bash \[yarn] yarn add @bitrix24/b24ui-nuxt ``````bash \[npm] npm install @bitrix24/b24ui-nuxt ``````bash \[bun] bun add @bitrix24/b24ui-nuxt ``` > !WARNING > If you're using **pnpm**, ensure that you either set [`shamefully-hoist=true`](https://pnpm.io/npmrc#shamefully-hoist){rel="nofollow"} in your `.npmrc` file or install `tailwindcss`, `vue-router` and `@unhead/vue` in your project's root directory. #### Add the Bitrix24 UI Vite plugin in your `vite.config.ts`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} ```ts \[vite.config.ts (Vite)] {3,8} import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite' export default defineConfig({ plugins: [ vue(), bitrix24UIPluginVite() ] }) ``````ts \[vite.config.ts (Laravel Inertia)] {3,20-22} import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite' import laravel from 'laravel-vite-plugin' export default defineConfig({ plugins: [ laravel({ input: ['resources/js/app.ts'], refresh: true }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false } } }), bitrix24UIPluginVite({ inertia: true }) ] }) ``````ts \[vite.config.ts (AdonisJS Inertia)] {3,15-17} import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite' import adonisjs from '@adonisjs/vite/client' import inertia from '@adonisjs/inertia/client' export default defineConfig({ plugins: [ adonisjs({ entrypoints: ['inertia/app/app.ts'], reload: ['resources/views/**/*.edge'] }), inertia(), vue(), bitrix24UIPluginVite({ inertia: true }) ] }) ``` > !TIP > Bitrix24 UI registers `unplugin-auto-import` and `unplugin-vue-components`, which will generate `auto-imports.d.ts` and `components.d.ts` type declaration files. You will likely want to gitignore these, and add them to your `tsconfig`. > > ```json [tsconfig.app.json] > { > "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "auto-imports.d.ts", "components.d.ts"] > } > ``` > > ```bash [.gitignore] > # Auto-generated type declarations > auto-imports.d.ts > components.d.ts > ``` > !TIP > Internally, Bitrix24 UI relies on custom alias to resolve the theme types. If you're using TypeScript, you should add an alias to your `tsconfig` to enable auto-completion in your `vite.config.ts`. > > ```json [tsconfig.node.json] > { > "compilerOptions": { > "paths": { > "#build/b24ui": [ > "./node_modules/.b24ui-nuxt/b24ui" > ] > } > } > } > ``` #### Use the Bitrix24 UI Vue plugin ```ts \[src/main.ts (Vite)] {3,14} 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') ``````ts \[resources/js/app.ts (Laravel Inertia)] {3,19} import type { DefineComponent } from 'vue' import { createInertiaApp } from '@inertiajs/vue3' import b24UiPlugin from '@bitrix24/b24ui-nuxt/vue-plugin' import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers' import { createApp, h } from 'vue' const appName = import.meta.env.VITE_APP_NAME || 'Laravel x Bitrix24 UI' createInertiaApp({ title: title => (title ? `${title} - ${appName}` : appName), resolve: name => resolvePageComponent( `./pages/${name}.vue`, import.meta.glob('./pages/**/*.vue') ), setup({ el, App, props, plugin }) { createApp({ render: () => h(App, props) }) .use(plugin) .use(b24UiPlugin) .mount(el) } }) ``````ts \[inertia/app/app.ts (AdonisJS Inertia)] {3,19} import type { DefineComponent } from 'vue' import { createInertiaApp } from '@inertiajs/vue3' import b24UiPlugin from '@bitrix24/b24ui-nuxt/vue-plugin' import { resolvePageComponent } from '@adonisjs/inertia/helpers' import { createApp, h } from 'vue' const appName = import.meta.env.VITE_APP_NAME || 'AdonisJS x Bitrix24 UI' createInertiaApp({ title: title => (title ? `${title} - ${appName}` : appName), resolve: name => resolvePageComponent( `../pages/${name}.vue`, import.meta.glob('../pages/**/*.vue') ), setup({ el, App, props, plugin }) { createApp({ render: () => h(App, props) }) .use(plugin) .use(b24UiPlugin) .mount(el) } }) ``` #### Import Tailwind CSS and Bitrix24 UI in your CSS ```css \[assets/main.css (Vite)] @import "tailwindcss"; @import "@bitrix24/b24ui-nuxt"; ``````css \[resources/css/app.css (Laravel Inertia)] @import "tailwindcss"; @import "@bitrix24/b24ui-nuxt"; ``````css \[inertia/css/app.css (AdonisJS Inertia)] @import "tailwindcss"; @import "@bitrix24/b24ui-nuxt"; ``` > !TIP > Import the CSS file in your entrypoint. > > ```ts \[src/main.ts] {1} > import './assets/main.css' > > 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') > ``````ts \[resources/js/app.ts (Laravel Inertia)] {1} > import '../css/app.css' > import type { DefineComponent } from 'vue' > import { createInertiaApp } from '@inertiajs/vue3' > import b24UiPlugin from '@bitrix24/b24ui-nuxt/vue-plugin' > import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers' > import { createApp, h } from 'vue' > > const appName = import.meta.env.VITE_APP_NAME || 'Laravel x Bitrix24 UI' > > createInertiaApp({ > title: title => (title ? `${title} - ${appName}` : appName), > resolve: name => > resolvePageComponent( > `./pages/${name}.vue`, > import.meta.glob('./pages/**/*.vue') > ), > setup({ el, App, props, plugin }) { > createApp({ render: () => h(App, props) }) > .use(plugin) > .use(b24UiPlugin) > .mount(el) > } > }) > ``````ts \[inertia/app/app.ts (AdonisJS Inertia)] {1} > import '../css/app.css' > import type { DefineComponent } from 'vue' > import { createInertiaApp } from '@inertiajs/vue3' > import b24UiPlugin from '@bitrix24/b24ui-nuxt/vue-plugin' > import { resolvePageComponent } from '@adonisjs/inertia/helpers' > import { createApp, h } from 'vue' > > const appName = import.meta.env.VITE_APP_NAME || 'AdonisJS x Bitrix24 UI' > > createInertiaApp({ > title: title => (title ? `${title} - ${appName}` : appName), > resolve: name => > resolvePageComponent( > `../pages/${name}.vue`, > import.meta.glob('../pages/**/*.vue') > ), > setup({ el, App, props, plugin }) { > createApp({ render: () => h(App, props) }) > .use(plugin) > .use(b24UiPlugin) > .mount(el) > } > }) > ``` > !NOTE > It's recommended to install the [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss){rel="nofollow"} extension for VSCode and add the following settings: > > ```json [.vscode/settings.json] > { > "files.associations": { > "*.css": "tailwindcss" > }, > "editor.quickSuggestions": { > "strings": "on" > }, > "tailwindCSS.classAttributes": ["class", "b24ui"], > "tailwindCSS.experimental.classRegex": [ > ["b24ui:\\s*{([^)]*)\\s*}", "(?:'|\"|`)([^']*)(?:'|\"|`)"] > ] > } > ``` #### Wrap your app with App component ```vue \[src/App.vue (Vite)] ``````vue \[resources/js/pages/index.vue (Laravel Inertia)] ``````vue \[inertia/pages/index.vue (AdonisJS Inertia)] ``` > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/components/app.md) > The `App` component sets up global config and is required for **Toast**, **Tooltip** and **programmatic overlays**. #### Add the `isolate` class to your root container ```html \[index.html (Vite)] {9} Bitrix24 UI
``````blade \[resources/views/app.blade.php (Laravel Inertia)] {10} @inertiaHead @vite('resources/js/app.ts')
@inertia
``````edge \[resources/views/inertia\_layout.edge (AdonisJS Inertia)] {10} @inertiaHead() @vite(['inertia/app/app.ts', `inertia/pages/${page.component}.vue`]) @inertia({ class: 'isolate' }) ``` > !NOTE > This ensures styles are scoped to your app and prevents issues with overlays and stacking contexts. :: ## Options You can customize Bitrix24 UI by providing options in your `vite.config.ts`. ### `colorMode` Use the `colorMode` option to enable or disable the color mode integration from `@vueuse/core`. - Default: `true`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} ```ts [vite.config.ts] {9} import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite' export default defineConfig({ plugins: [ vue(), bitrix24UIPluginVite({ colorMode: false }) ] }) ``` ### `theme.prefix` Use the `theme.prefix` option to configure the same prefix you set on your Tailwind CSS import. This ensures Bitrix24 UI components use the correct prefixed utility classes and CSS variables. ```ts \[vite.config.ts] {9-11} import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite' export default defineConfig({ plugins: [ vue(), bitrix24UIPluginVite({ theme: { prefix: 'tw' } }) ] }) ``````css \[assets/main.css] {1} @import "tailwindcss" prefix(tw); @import "@bitrix24/b24ui-nuxt"; ``` This will automatically prefix all Tailwind utility classes and CSS variables in Bitrix24 UI component themes: ```html ``` > [!NOTE](https://tailwindcss.com/docs/styling-with-utility-classes#using-the-prefix-option) > Learn more about using a prefix in the Tailwind CSS documentation. ### `inertia` Use the `inertia` option to enable compatibility with [Inertia.js](https://inertiajs.com/){rel="nofollow"}. ```ts [vite.config.ts] {9} import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite' export default defineConfig({ plugins: [ vue(), bitrix24UIPluginVite({ inertia: true }) ] }) ``` > !NOTE > When using this option, `vue-router` is not required as Inertia.js provides its own routing system. The components that would normally use `RouterLink` will automatically use Inertia's `InertiaLink` component instead. --- # Migration to v2 > A comprehensive guide to migrate your application from Bitrix24 UI v1 to Bitrix24 UI v2. > !NOTE > Bitrix24 UI v2 requires **Nuxt 4** due to some dependencies. Make sure to upgrade to Nuxt 4 before migrating to Bitrix24 UI v2. This guide provides step-by-step instructions to migrate your application to Bitrix24 UI v2. ## Changes After upgrading to Bitrix24 UI v2, please note the following important changes: ### Renamed ButtonGroup The `ButtonGroup` component has been renamed to [`FieldGroup`](https://bitrix24.github.io/b24ui/raw/docs/components/field-group.md): ```diff ``` ### Renamed model modifiers The `modelModifiers` shape used by [`Input`](https://bitrix24.github.io/b24ui/raw/docs/components/input.md), [`InputNumber`](https://bitrix24.github.io/b24ui/raw/docs/components/input-number.md) and [`Textarea`](https://bitrix24.github.io/b24ui/raw/docs/components/textarea.md) has changed in v2: 1. The `nullify` modifier was renamed to `nullable` (it converts empty/blank values to `null`). 2. A new `optional` modifier was added (it converts empty/blank values to `undefined`). ```diff - + ``` ```diff - + ``` Use `nullable` when you want empty values as `null`, and `optional` when you prefer `undefined` for absent values. ### Changes to Form component The `Form` component has been improved in v2 with better state management and nested form handling. Here are the key changes you need to be aware of: 1. Schema **transformations will only** be applied to the **`@submit` data** and will no longer mutate the form's state. This provides better predictability and prevents unexpected state mutations. 2. **Nested forms must be enabled explicitly** using the `nested` prop. This makes the component behavior more explicit and prevents accidental nested form creation. 3. **Nested forms should now provide a `name`** prop (similar to `B24FormField`) and will automatically inherit their state from their parent form. ```diff ``` ### useSidebarLayout removed Composable `useSidebarLayout` is no longer supported. Support for the loading state of the [SidebarLayout](https://bitrix24.github.io/b24ui/raw/docs/components/sidebar-layout.md) component via [DashboardGroup](https://bitrix24.github.io/b24ui/raw/docs/components/dashboard-group.md) will be added in an upcoming release. ### @bitrix24/b24style removed The [Bitrix24 UI](https://github.com/bitrix24/b24ui/tree/main/src/runtime/air-design-tokens){rel="nofollow"} styles are now responsible for styling. We've tried to maintain compatibility, but if any issues arise, please [let us know](https://github.com/bitrix24/b24ui/issues){rel="nofollow"}. --- # Contribution > A detailed guide on how to contribute to Bitrix24 UI, including insights on project structure, development workflow, and best practices. The goal of this project is to provide components identical to Bitrix24 to enhance the user experience and simplify the development of applications for Bitrix24. We have chosen [Nuxt UI](https://ui.nuxt.com/){rel="nofollow"} as the foundation. We welcome your contributions in the form of bug reports, pull requests, and feedback to make this library even better. > !CAUTION > Before reporting a bug or requesting a feature, make sure that you have read through our [documentation](https://bitrix24.github.io/b24ui/){rel="nofollow"} and existing [issues](https://github.com/bitrix24/b24ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3){rel="nofollow"}. ## Project structure Here's an overview of the key directories and files in the Bitrix24 UI project structure: ### Documentation The documentation lives in the `docs` folder as a Nuxt app using `@nuxt/content` to generate pages from Markdown files. See the [Nuxt Content documentation](https://content.nuxt.com/docs/getting-started){rel="nofollow"} for details on how it works. Here's a breakdown of its structure: ```bash ├── app/ │ ├── assets/ │ ├── components/ │ │ └── content/ │ │ └── examples # Components used in documentation as examples │ ├── composables/ │ └── ... ├── content/ │ ├── 1.getting-started │ ├── 2.composables │ └── 3.components # Components documentation ``` ### Module The module code resides in the `src` folder. Here's a breakdown of its structure: ```bash ├── plugins/ ├── runtime/ │ ├── components/ # Where all the components are located │ │ ├── Accordion.vue │ │ ├── Alert.vue │ │ └── ... │ ├── composables/ │ ├── locale/ │ ├── plugins/ │ ├── types/ │ ├── utils/ │ └── vue/ │ ├── components/ │ └── plugins/ ├── theme/ # This where the theme for each component is located │ ├── accordion.ts # Theme for Accordion component │ ├── alert.ts │ └── ... └── module.ts ``` ## Submit a Pull Request (PR) Before you start, check if there's an existing issue describing the problem or feature request you're working on. If there is, please leave a comment on the issue to let us know you're working on it. If there isn't, open a new issue to discuss the problem or feature. ### Local development To begin local development, follow these steps: ::steps{level="4"} #### Clone the `@bitrix24/b24ui-nuxt` repository to your local machine ```sh git clone https://github.com/bitrix24/b24ui.git ``` #### Enable [Corepack](https://github.com/nodejs/corepack){rel="nofollow"} ```sh corepack enable ``` #### Install dependencies ```sh pnpm install ``` #### Generate type stubs ```sh pnpm run dev:prepare ``` #### Start development - To work on the **documentation** located in the `docs` folder, run: ```sh pnpm run docs ``` - To test the Nuxt components using the **playground**, run: ```sh pnpm run dev ``` - To test the Vue components using the **playground**, run: ```sh pnpm run dev:vue ``` :: ### IDE Setup We recommend using VSCode alongside the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint){rel="nofollow"}. You can enable auto-fix and formatting when saving your code. Here's how: ```json { "editor.codeActionsOnSave": { "source.fixAll": false, "source.fixAll.eslint": true } } ``` > !WARNING > Since ESLint is already configured to format the code, there's no need for duplicating functionality with **Prettier**. If you have it installed in your editor, we recommend disabling it to avoid conflicts. ### Linting You can use the `lint` command to check for linting errors: ```sh pnpm run lint # check for linting errors pnpm run lint:fix # fix linting errors ``` ### Type checking We use TypeScript for type checking. You can use the `typecheck` command to check for type errors: ```sh pnpm run typecheck ``` ### Testing Before submitting a PR, ensure that you run the tests for both `nuxt` and `vue`: ```sh pnpm run test # for Nuxt pnpm run test:vue # for Vue ``` > !TIP > If you have to update the snapshots, press `u` after the tests have finished running. ### Commit conventions We use [Conventional Commits](https://www.conventionalcommits.org/){rel="nofollow"} for commit messages, which allows a changelog to be auto-generated based on the commits. Please read the [guide](https://www.conventionalcommits.org/en/v1.0.0/#summary){rel="nofollow"} through if you aren't familiar with it already. - Use `fix` and `feat` for code changes that affect functionality or logic - Use `docs` for documentation changes and `chore` for maintenance tasks ### Making a Pull Request - Follow along the [instructions](https://github.com/bitrix24/b24ui/blob/main/.github/PULL_REQUEST_TEMPLATE.md?plain=1){rel="nofollow"} provided when creating a PR - Ensure your PR's title adheres to the [Conventional Commits](https://www.conventionalcommits.org/){rel="nofollow"} since it will be used once the code is merged. - Multiple commits are fine; no need to rebase or force push. We'll use `Squash and Merge` when merging. - Ensure `lint`, `typecheck` and `tests` work before submitting the PR. Avoid making unrelated changes. Thanks! --- # Design System > Bitrix24 UI's design system uses Tailwind CSS for simple theming and easy customization. > !WARNING > We are still updating this page. Some data may be missing here — we will complete it shortly. ## Tailwind CSS Tailwind CSS uses a CSS-first configuration, letting you define your design tokens with the [`@theme`](https://tailwindcss.com/docs/functions-and-directives#theme-directive){rel="nofollow"} directive directly in your CSS. This makes your theme portable, maintainable and easy to customize. ```css [app/assets/css/main.css] @import "tailwindcss"; @import "@bitrix24/b24ui-nuxt"; @theme { /* Your custom design tokens go here */ } ``` > [!NOTE](https://tailwindcss.com/docs/theme/) > Check the Tailwind CSS documentation for all available theme variable customization options. ### Breakpoints Use the `--breakpoint-*` theme variables to [customize your breakpoints](https://tailwindcss.com/docs/responsive-design#customizing-your-theme){rel="nofollow"}. ```css [app/assets/css/main.css] @import "tailwindcss"; @import "@bitrix24/b24ui-nuxt"; @theme { --breakpoint-3xl: 1920px; --breakpoint-4xl: 2560px; --breakpoint-5xl: 3840px; } ``` --- # CSS Variables > Bitrix24 UI uses CSS variables as design tokens for flexible, consistent theming with built-in light and dark mode support. ## Colors > !WARNING > We are still updating this page. Some data may be missing here — we will complete it shortly. ## Text Bitrix24 UI provides Tailwind CSS utility classes for text colors, allowing you to use class names like `text-legend` or `text-description`: ::code-preview [Dimmed]{.text-dimmed.text-sm.px-4.inline-block.rounded-md class="py-1.5"}[Muted]{.text-muted.text-sm.px-4.inline-block.rounded-md class="py-1.5"}[Description]{.text-description.text-sm.px-4.inline-block.rounded-md class="py-1.5"}[Legend]{.text-legend.text-sm.px-4.inline-block.rounded-md class="py-1.5"}[Label]{.text-label.text-sm.px-4.inline-block.rounded-md class="py-1.5"} #code ```vue ``` :: ## Background > !WARNING > We are still updating this page. Some data may be missing here — we will complete it shortly. ## Border > !WARNING > We are still updating this page. Some data may be missing here — we will complete it shortly. ## Radius > !WARNING > We are still updating this page. Some data may be missing here — we will complete it shortly. ## Container > !WARNING > We are still updating this page. Some data may be missing here — we will complete it shortly. ## Header > !WARNING > We are still updating this page. Some data may be missing here — we will complete it shortly. ## Body Bitrix24 UI applies default classes on the ``{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="html"} element of your app for consistent theming across light, edge-light, edge-dark and dark modes: ```css body { scrollbar-gutter: stable; background: var(--air-theme-background); @apply antialiased font-(family-name:--ui-font-family-system) text-(--b24ui-typography-legend-color) scheme-light dark:scheme-dark edge-light:scheme-light edge-dark:scheme-light } ``` --- # Customize components > Learn how to customize Bitrix24 UI components with the Tailwind Variants API for advanced, flexible, and maintainable styling. ## Tailwind Variants Bitrix24 UI components are styled using the [Tailwind Variants](https://www.tailwind-variants.org/){rel="nofollow"} API, which provides a powerful way to create variants and manage component styles. ### Slots Components can have multiple `slots`, each representing a distinct HTML element or section within the component. These slots allow for flexible content insertion and styling. Let's take the [Card](https://bitrix24.github.io/b24ui/raw/docs/components/card.md) component as an example which has multiple slots: ```ts \[src/theme/card.ts] export default { slots: { root: 'bg-(--ui-color-design-filled-bg) border border-(--ui-color-design-filled-stroke) border-(length:--ui-design-filled-stroke-weight) text-(--ui-color-design-filled-content)', header: 'p-[24px] sm:px-[22px] sm:py-[15px]', body: 'p-[24px] sm:px-[22px] sm:py-[15px]', footer: 'p-[24px] sm:px-[22px] sm:py-[15px]' } } ``````vue \[src/runtime/components/Card.vue] ``` Some components don't have slots, they are just composed of a single root element. In this case, the theme only defines the `base` slot like the [Container](https://bitrix24.github.io/b24ui/raw/docs/components/container.md) component for example: ```ts \[src/theme/container.ts] export default { base: 'w-full max-w-[1280px] mx-auto px-[22px]' } ``````vue \[src/runtime/components/Container.vue] ``` > !WARNING > Components without slots don't have a [`b24ui` prop](https://bitrix24.github.io/b24ui/#ui-prop), only the [`class` prop](https://bitrix24.github.io/b24ui/#class-prop) is available to override styles. ### Variants Components support `variants`, which allow you to dynamically adjust the styles of different `slots` based on component props. For example, the [Avatar](https://bitrix24.github.io/b24ui/raw/docs/components/avatar.md) component uses a `size` variant to control its appearance: ```ts [src/theme/avatar.ts] {6-18} export default { slots: { root: 'air-secondary-accent inline-flex items-center justify-center shrink-0 select-none rounded-full align-middle bg-(--ui-color-base-8) ring ring-(--ui-color-base-7)', image: 'h-full w-full rounded-[inherit] object-cover' }, variants: { size: { sm: { root: 'size-[28px] text-(length:--ui-font-size-xs)/(--ui-font-line-height-reset)' }, md: { root: 'size-[32px] text-(length:--ui-font-size-sm)/(--ui-font-line-height-reset)' }, lg: { root: 'size-[42px] text-(length:--ui-font-size-2xl)/(--ui-font-line-height-reset)' } } }, defaultVariants: { size: 'md' } } ``` This way, the `size` prop will apply the corresponding styles to the `root` slot: ::component-code --- ignore: - src props: src: https://github.com/bitrix24.png size: lg slug: avatar --- :: ### Default Variants The `defaultVariants` property sets the default value for each variant when no prop is passed. For example, the [Avatar](https://bitrix24.github.io/b24ui/raw/docs/components/avatar.md) component has its default size set to `md`: ```ts [src/theme/avatar.ts] {19-21} export default { slots: { root: 'air-secondary-accent inline-flex items-center justify-center shrink-0 select-none rounded-full align-middle bg-(--ui-color-base-8) ring ring-(--ui-color-base-7)', image: 'h-full w-full rounded-[inherit] object-cover' }, variants: { size: { sm: { root: 'size-[28px] text-(length:--ui-font-size-xs)/(--ui-font-line-height-reset)' }, md: { root: 'size-[32px] text-(length:--ui-font-size-sm)/(--ui-font-line-height-reset)' }, lg: { root: 'size-[42px] text-(length:--ui-font-size-2xl)/(--ui-font-line-height-reset)' } } }, defaultVariants: { size: 'md' } } ``` ### Compound Variants Some components use the `compoundVariants` property to apply classes when multiple variant conditions are met at the same time. For example, the [Alert](https://bitrix24.github.io/b24ui/raw/docs/components/alert.md) component uses the `compoundVariants` property to apply classes for a specific `color` and `inverted` combination: ```ts [src/theme/button.ts] {27-31} export default { slots: { root: [ 'relative overflow-hidden w-full flex', 'text-(--b24ui-color)', 'bg-(--b24ui-background)', 'border-(--b24ui-border-color) border-(length:--b24ui-border-width)', 'rounded-(--ui-border-radius-md)' ].join(' ') }, variants: { color: { 'air-primary': { root: 'style-filled' }, 'air-primary-success': { root: 'style-filled-success' } }, inverted: { true: '', false: '' } }, compoundVariants: [ { inverted: true, color: 'air-primary', class: { root: 'style-filled-inverted' } }, { inverted: true, color: 'air-primary-success', class: { root: 'style-filled-success-inverted' } } ], defaultVariants: { color: 'primary', variant: 'solid' } } ``` ## Customize theme You have multiple ways to customize the appearance of Bitrix24 UI components, you can do it for all components at once or on a per-component basis. > !NOTE > Tailwind Variants uses [`tailwind-merge`](https://github.com/dcastil/tailwind-merge){rel="nofollow"} under the hood to merge classes so you don't have to worry about conflicting classes. > !TIP > You can explore the theme for each component in two ways: > > - Check the `Theme` section in the documentation of each individual component. > - Browse the source code directly in the GitHub repository at [`src/theme`](https://github.com/bitrix24/b24ui/tree/main/src/theme){rel="nofollow"}. ### `b24ui` prop You can override a component's **slots** using the `b24ui` prop. This takes priority over both global config and resolved `variants`. ::component-code --- ignore: - b24ui.trailingIcon - color - variant - size - icon prettier: true props: useDropdown: true size: md color: air-primary b24ui: trailingIcon: rotate-90 size-10 slots: default: | Button slug: button --- :: > !NOTE > In this example, the `trailingIcon` slot is overwritten with `size-10` even though the `md` size variant would apply a `size-(--ui-btn-icon-size)` class to it. ### `class` prop The `class` prop allows you to override the classes of the `root` or `base` slot. This takes priority over both global config and resolved `variants`. ::component-code --- props: class: font-bold rounded-full slots: default: Button slug: button --- :: > !NOTE > In this example, the `font-bold` class will override the default `font-medium` class on this button. --- # Icons > Bitrix24 UI integrates with @bitrix24/b24icons to access over 1,400+ icons. > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/icons/vue.md) > Looking for the **Vue** version? ## Usage Bitrix24 UI automatically registers the `@bitrix24/b24icons` module for you, so there's no additional setup required. ### Icon component They are very easy to use: ```vue [IconExample.vue] ``` > !NOTE > You can use any from the {rel="nofollow"} collection. ### Component props Some components also have an `icon` prop to display an icon, like the [Button](https://bitrix24.github.io/b24ui/raw/docs/components/button.md) for example: ::component-code --- cast: icon: RocketIcon ignore: - icon props: icon: RocketIcon slots: default: Button slug: button --- :: ## Set of icons The interface uses the following set of icons ::code-collapse ```ts [src/runtime/dictionary/icons.ts] import ArrowToTheLeftIcon from '@bitrix24/b24icons-vue/actions/ArrowToTheLeftIcon' import ArrowToTheRightIcon from '@bitrix24/b24icons-vue/actions/ArrowToTheRightIcon' import CheckIcon from '@bitrix24/b24icons-vue/outline/CheckLIcon' import ChevronTopLIcon from '@bitrix24/b24icons-vue/outline/ChevronTopLIcon' import ChevronToTheLeftIcon from '@bitrix24/b24icons-vue/outline/ChevronLeftLIcon' import ChevronToTheRightIcon from '@bitrix24/b24icons-vue/outline/ChevronRightLIcon' import DoubleShevronsRightIcon from '@bitrix24/b24icons-vue/actions/DoubleShevronsRightIcon' import DoubleShevronsLeftIcon from '@bitrix24/b24icons-vue/actions/DoubleShevronsLeftIcon' import CrossMIcon from '@bitrix24/b24icons-vue/outline/CrossMIcon' import DotsIcon from '@bitrix24/b24icons-vue/button/DotsIcon' import OpenIn50Icon from '@bitrix24/b24icons-vue/actions/OpenIn50Icon' import Refresh6Icon from '@bitrix24/b24icons-vue/actions/Refresh6Icon' import Minus30Icon from '@bitrix24/b24icons-vue/actions/Minus30Icon' import Plus30Icon from '@bitrix24/b24icons-vue/actions/Plus30Icon' import Search2Icon from '@bitrix24/b24icons-vue/main/Search2Icon' import LoaderWaitIcon from '@bitrix24/b24icons-vue/animated/LoaderWaitIcon' import ChevronDownLIcon from '@bitrix24/b24icons-vue/outline/ChevronDownLIcon' import ScreenIcon from '@bitrix24/b24icons-vue/outline/ScreenIcon' import SunIconAir from '@bitrix24/b24icons-vue/outline/SunIcon' import MoonIconAir from '@bitrix24/b24icons-vue/outline/MoonIcon' import TagIcon from '@bitrix24/b24icons-vue/outline/TagIcon' import InfoCircleIcon from '@bitrix24/b24icons-vue/outline/InfoCircleIcon' import IdeaLampIcon from '@bitrix24/b24icons-vue/outline/IdeaLampIcon' import WarningIcon from '@bitrix24/b24icons-vue/main/WarningIcon' import AlertIcon from '@bitrix24/b24icons-vue/outline/AlertIcon' import CopyIcon from '@bitrix24/b24icons-vue/outline/CopyIcon' import CircleCheckIcon from '@bitrix24/b24icons-vue/outline/CircleCheckIcon' import FileIcon from '@bitrix24/b24icons-vue/outline/FileIcon' import UploadFileIcon from '@bitrix24/b24icons-vue/outline/UploadFileIcon' import ArrowDownLIcon from '@bitrix24/b24icons-vue/outline/ArrowDownLIcon' import ArrowTopLIcon from '@bitrix24/b24icons-vue/outline/ArrowTopLIcon' import StopLIcon from '@bitrix24/b24icons-vue/outline/StopLIcon' import RefreshIcon from '@bitrix24/b24icons-vue/outline/RefreshIcon' import SendIcon from '@bitrix24/b24icons-vue/main/SendIcon' export default { arrowLeft: ArrowToTheLeftIcon, arrowRight: ArrowToTheRightIcon, check: CheckIcon, chevronDoubleLeft: DoubleShevronsLeftIcon, chevronDoubleRight: DoubleShevronsRightIcon, chevronDown: ChevronDownLIcon, chevronLeft: ChevronToTheLeftIcon, chevronRight: ChevronToTheRightIcon, chevronUp: ChevronTopLIcon, close: CrossMIcon, ellipsis: DotsIcon, external: OpenIn50Icon, file: FileIcon, loading: LoaderWaitIcon, refresh: Refresh6Icon, minus: Minus30Icon, plus: Plus30Icon, search: Search2Icon, upload: UploadFileIcon, system: ScreenIcon, light: SunIconAir, dark: MoonIconAir, hash: TagIcon, warning: WarningIcon, tip: IdeaLampIcon, info: InfoCircleIcon, caution: AlertIcon, copyCheck: CircleCheckIcon, copy: CopyIcon, imSend: SendIcon, arrowDown: ArrowDownLIcon, arrowUp: ArrowTopLIcon, stop: StopLIcon, reload: RefreshIcon } ``` :: --- # Icons > Bitrix24 UI integrates with @bitrix24/b24icons to access over 1,400+ icons. > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/icons/nuxt.md) > Looking for the **Nuxt** version? ## Usage ### Icon component They are very easy to use: ```vue [IconExample.vue] ``` > !NOTE > You can use any from the {rel="nofollow"} collection. ### Component props Some components also have an `icon` prop to display an icon, like the [Button](https://bitrix24.github.io/b24ui/raw/docs/components/button.md) for example: ::component-code --- cast: icon: RocketIcon ignore: - icon props: icon: RocketIcon slots: default: Button slug: button --- :: ## Set of icons The interface uses the following set of icons ::code-collapse ```ts [src/runtime/dictionary/icons.ts] import ArrowToTheLeftIcon from '@bitrix24/b24icons-vue/actions/ArrowToTheLeftIcon' import ArrowToTheRightIcon from '@bitrix24/b24icons-vue/actions/ArrowToTheRightIcon' import CheckIcon from '@bitrix24/b24icons-vue/outline/CheckLIcon' import ChevronTopLIcon from '@bitrix24/b24icons-vue/outline/ChevronTopLIcon' import ChevronToTheLeftIcon from '@bitrix24/b24icons-vue/outline/ChevronLeftLIcon' import ChevronToTheRightIcon from '@bitrix24/b24icons-vue/outline/ChevronRightLIcon' import DoubleShevronsRightIcon from '@bitrix24/b24icons-vue/actions/DoubleShevronsRightIcon' import DoubleShevronsLeftIcon from '@bitrix24/b24icons-vue/actions/DoubleShevronsLeftIcon' import CrossMIcon from '@bitrix24/b24icons-vue/outline/CrossMIcon' import DotsIcon from '@bitrix24/b24icons-vue/button/DotsIcon' import OpenIn50Icon from '@bitrix24/b24icons-vue/actions/OpenIn50Icon' import Refresh6Icon from '@bitrix24/b24icons-vue/actions/Refresh6Icon' import Minus30Icon from '@bitrix24/b24icons-vue/actions/Minus30Icon' import Plus30Icon from '@bitrix24/b24icons-vue/actions/Plus30Icon' import Search2Icon from '@bitrix24/b24icons-vue/main/Search2Icon' import LoaderWaitIcon from '@bitrix24/b24icons-vue/animated/LoaderWaitIcon' import ChevronDownLIcon from '@bitrix24/b24icons-vue/outline/ChevronDownLIcon' import ScreenIcon from '@bitrix24/b24icons-vue/outline/ScreenIcon' import SunIconAir from '@bitrix24/b24icons-vue/outline/SunIcon' import MoonIconAir from '@bitrix24/b24icons-vue/outline/MoonIcon' import TagIcon from '@bitrix24/b24icons-vue/outline/TagIcon' import InfoCircleIcon from '@bitrix24/b24icons-vue/outline/InfoCircleIcon' import IdeaLampIcon from '@bitrix24/b24icons-vue/outline/IdeaLampIcon' import WarningIcon from '@bitrix24/b24icons-vue/main/WarningIcon' import AlertIcon from '@bitrix24/b24icons-vue/outline/AlertIcon' import CopyIcon from '@bitrix24/b24icons-vue/outline/CopyIcon' import CircleCheckIcon from '@bitrix24/b24icons-vue/outline/CircleCheckIcon' import FileIcon from '@bitrix24/b24icons-vue/outline/FileIcon' import UploadFileIcon from '@bitrix24/b24icons-vue/outline/UploadFileIcon' import ArrowDownLIcon from '@bitrix24/b24icons-vue/outline/ArrowDownLIcon' import ArrowTopLIcon from '@bitrix24/b24icons-vue/outline/ArrowTopLIcon' import StopLIcon from '@bitrix24/b24icons-vue/outline/StopLIcon' import RefreshIcon from '@bitrix24/b24icons-vue/outline/RefreshIcon' import SendIcon from '@bitrix24/b24icons-vue/main/SendIcon' export default { arrowLeft: ArrowToTheLeftIcon, arrowRight: ArrowToTheRightIcon, check: CheckIcon, chevronDoubleLeft: DoubleShevronsLeftIcon, chevronDoubleRight: DoubleShevronsRightIcon, chevronDown: ChevronDownLIcon, chevronLeft: ChevronToTheLeftIcon, chevronRight: ChevronToTheRightIcon, chevronUp: ChevronTopLIcon, close: CrossMIcon, ellipsis: DotsIcon, external: OpenIn50Icon, file: FileIcon, loading: LoaderWaitIcon, refresh: Refresh6Icon, minus: Minus30Icon, plus: Plus30Icon, search: Search2Icon, upload: UploadFileIcon, system: ScreenIcon, light: SunIconAir, dark: MoonIconAir, hash: TagIcon, warning: WarningIcon, tip: IdeaLampIcon, info: InfoCircleIcon, caution: AlertIcon, copyCheck: CircleCheckIcon, copy: CopyIcon, imSend: SendIcon, arrowDown: ArrowDownLIcon, arrowUp: ArrowTopLIcon, stop: StopLIcon, reload: RefreshIcon } ``` :: --- # Color Mode > Bitrix24 UI integrates with VueUse to allow for easy switching between light and dark themes. > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/color-mode/vue.md) > Looking for the **Vue** version? > !WARNING > We are still updating this page. Some data may be missing here — we will complete it shortly. ## Usage Bitrix24 UI automatically registers the [useDark](https://vueuse.org/core/useDark){rel="nofollow"} composable as a Vue plugin, so there's no additional setup required. ### Components You can use the built-in [ColorModeAvatar](https://bitrix24.github.io/b24ui/raw/docs/components/color-mode-avatar.md) or [ColorModeImage](https://bitrix24.github.io/b24ui/raw/docs/components/color-mode-image.md) components to display different images for light and dark mode and the [ColorModeButton](https://bitrix24.github.io/b24ui/raw/docs/components/color-mode-button.md), [ColorModeSwitch](https://bitrix24.github.io/b24ui/raw/docs/components/color-mode-switch.md) or [ColorModeSelect](https://bitrix24.github.io/b24ui/raw/docs/components/color-mode-select.md) components to switch between light and dark modes. You can also use the [useColorMode](https://vueuse.org/core/useColorMode/){rel="nofollow"} composable to build your own custom component: ```vue [ColorModeButton.vue] ``` ### Configuration You can disable this plugin with the `b24ui.colorMode` option in your `nuxt.config.ts`: ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['@bitrix24/b24ui-nuxt'], css: ['~/assets/css/main.css'], b24ui: { colorMode: false } }) ``` --- # Color Mode > Bitrix24 UI integrates with VueUse to allow for easy switching between light and dark themes. > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/color-mode/nuxt.md) > Looking for the **Nuxt** version? > !WARNING > We are still updating this page. Some data may be missing here — we will complete it shortly. ## Usage Bitrix24 UI automatically registers the [useDark](https://vueuse.org/core/useDark){rel="nofollow"} composable as a Vue plugin, so there's no additional setup required. ### Components You can use the built-in [ColorModeAvatar](https://bitrix24.github.io/b24ui/raw/docs/components/color-mode-avatar.md) or [ColorModeImage](https://bitrix24.github.io/b24ui/raw/docs/components/color-mode-image.md) components to display different images for light and dark mode and the [ColorModeButton](https://bitrix24.github.io/b24ui/raw/docs/components/color-mode-button.md), [ColorModeSwitch](https://bitrix24.github.io/b24ui/raw/docs/components/color-mode-switch.md) or [ColorModeSelect](https://bitrix24.github.io/b24ui/raw/docs/components/color-mode-select.md) components to switch between light and dark modes. You can also use the [useColorMode](https://vueuse.org/core/useColorMode/){rel="nofollow"} composable to build your own custom component: ```vue [ColorModeButton.vue] ``` ### Configuration You can disable this plugin with the `colorMode` option in your `vite.config.ts`: ```ts [vite.config.ts] import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite' export default defineConfig({ plugins: [ vue(), bitrix24UIPluginVite({ colorMode: false }) ] }) ``` --- # Internationalization (i18n) > Bitrix24 UI supports 19 locales and multi-directional (LTR/RTL) internationalization. > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/i18n/vue.md) > Looking for the **Vue** version? ## Usage > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/components/app.md) > Bitrix24 UI provides an **App** component that wraps your app to provide global configurations. ### Locale Use the `locale` prop with the locale you want to use from `@bitrix24/b24ui-nuxt/locale`: ```vue [app.vue] ``` ### Extend locale You can customize an existing locale by overriding its `messages` using the `extendLocale` composable: ```vue [app.vue] ``` ### Dynamic locale To dynamically switch between languages, you can use the [Nuxt I18n](https://i18n.nuxtjs.org/){rel="nofollow"} module. ::steps{level="4"} #### Install the Nuxt I18n package ```bash \[pnpm] pnpm add @nuxtjs/i18n ``````bash \[yarn] yarn add @nuxtjs/i18n ``````bash \[npm] npm install @nuxtjs/i18n ``````bash \[bun] bun add @nuxtjs/i18n ``` #### Add the Nuxt I18n module in your `nuxt.config.ts`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: [ '@bitrix24/b24ui-nuxt', '@nuxtjs/i18n' ], css: ['~/assets/css/main.css'], i18n: { locales: [ { code: 'de', name: 'Deutsch' }, { code: 'en', name: 'English' }, { code: 'fr', name: 'Français' } ] } }) ``` #### Set the `locale` prop using `useI18n` ```vue [app.vue] ``` :: ### Dynamic direction Each locale has a `dir` property which will be used by the `App` component to set the directionality of all components. In a multilingual application, you might want to set the `lang` and `dir` attributes on the `` element dynamically based on the user's locale, which you can do with the [useHead](https://nuxt.com/docs/api/composables/use-head){rel="nofollow"} composable: ```vue [app.vue] ``` ## Supported languages ::supported-languages :: --- # Internationalization (i18n) > Bitrix24 UI supports 19 locales and multi-directional (LTR/RTL) internationalization. > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/i18n/nuxt.md) > Looking for the **Nuxt** version? ## Usage > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/components/app.md) > Bitrix24 UI provides an **App** component that wraps your app to provide global configurations. ### Locale Use the `locale` prop with the locale you want to use from `@bitrix24/b24ui-nuxt/locale`: ```vue [App.vue] ``` ### Extend locale You can customize an existing locale by overriding its `messages` using the `extendLocale` composable: ```vue [App.vue] ``` ### Dynamic locale To dynamically switch between languages, you can use the [Vue I18n](https://vue-i18n.intlify.dev/){rel="nofollow"} plugin. ::steps{level="4"} #### Install the Vue I18n package ```bash \[pnpm] pnpm add vue-i18n@11 ``````bash \[yarn] yarn add vue-i18n@11 ``````bash \[npm] npm install vue-i18n@11 ``````bash \[bun] bun add vue-i18n@11 ``` #### Use the Vue I18n plugin in your `main.ts` ```ts [main.ts] {3,14-26,29} import { createApp } from 'vue' import { createRouter, createWebHistory } from 'vue-router' import { createI18n } from 'vue-i18n' import b24UiPlugin from '@bitrix24/b24ui-nuxt/vue-plugin' import App from './App.vue' const app = createApp(App) const router = createRouter({ routes: [], history: createWebHistory() }) const i18n = createI18n({ legacy: false, locale: 'en', availableLocales: ['en', 'de'], messages: { en: { // ... }, de: { // ... } } }) app.use(router) app.use(i18n) app.use(b24UiPlugin) app.mount('#app') ``` #### Set the `locale` prop using `useI18n` ```vue [App.vue] ``` :: ### Dynamic direction Each locale has a `dir` property which will be used by the `App` component to set the directionality of all components. In a multilingual application, you might want to set the `lang` and `dir` attributes on the `` element dynamically based on the user's locale, which you can do with the [useHead](https://unhead.unjs.io/usage/composables/use-head){rel="nofollow"} composable: ```vue [App.vue] ``` ## Supported languages ::supported-languages :: --- # Content > Bitrix24 UI integrates with Nuxt Content to deliver beautiful typography and consistent component styling. ## Installation To get started, you can follow the official [guide](https://content.nuxt.com/docs/getting-started/installation){rel="nofollow"} or in summary: ```bash \[pnpm] pnpm add @nuxt/content ``````bash \[yarn] yarn add @nuxt/content ``````bash \[npm] npm install @nuxt/content ``````bash \[bun] bun add @nuxt/content ``` Then, add the `@nuxt/content` module in your `nuxt.config.ts`: ```ts [nuxt.config.ts] {4} export default defineNuxtConfig({ modules: [ '@bitrix24/b24ui-nuxt', '@nuxt/content' ], css: ['~/assets/css/main.css'] }) ``` > !CAUTION > You need to register `@nuxt/content` after `@bitrix24/b24ui-nuxt` in the `modules` array, otherwise the prose components will not be available. ## Configuration When using Tailwind CSS classes in your markdown content files, you need to ensure Tailwind can detect and generate the necessary utility classes. By default, Tailwind's automatic content detection might not pick up classes written in markdown files. To fix this, use the [`@source` directive](https://tailwindcss.com/docs/functions-and-directives#source-directive){rel="nofollow"} in your CSS file to explicitly include your content directory: ```css [app/assets/css/main.css] @import "tailwindcss"; @import "@bitrix24/b24ui-nuxt"; @source "../../../content/**/*"; ``` This ensures that: - Tailwind scans all markdown files in your content directory - Any utility classes used in your markdown are included in the final CSS - Dynamic classes in MDC components or custom Vue components within your content work properly > !TIP > You can also use glob patterns to be more specific about which files to scan: > > - `@source "../../../content/docs/**/*.md"` - Only scan markdown in the docs folder > - `@source "../../../content/**/*.{md,yml}"` - Include both markdown and YAML files > [!NOTE](https://tailwindcss.com/docs/detecting-classes-in-source-files) > Learn more about Tailwind's automatic content detection and best practices for optimizing build performance. ## Components You might be using `@nuxt/content` to build a documentation. To help you with that, we've built some components that you can use in your pages: - a built-in full-text search command palette with [ContentSearch](https://bitrix24.github.io/b24ui/raw/docs/components/content-search.md), replacing the need for Algolia DocSearch - a sticky Table of Contents with the [ContentToc](https://bitrix24.github.io/b24ui/raw/docs/components/content-toc.md) component - a prev / next navigation with the [ContentSurround](https://bitrix24.github.io/b24ui/raw/docs/components/content-surround.md) component ## Typography Bitrix24 UI provides its own custom implementations of all prose components for seamless integration with `@nuxt/content`. This approach ensures consistent styling, complete control over typography, and perfect alignment with the Bitrix24 UI design system so your content always looks and feels cohesive out of the box. > [!NOTE](https://bitrix24.github.io/b24ui/raw/docs/typography.md) > Discover the full **Typography** system and explore all available prose components for rich, consistent content presentation. ## Utils ### `mapContentNavigation` This util will map the navigation from `queryCollectionNavigation` and transform it recursively into an array of objects that can be used by various components. `mapContentNavigation(navigation, options?)` - `navigation`: The navigation tree (array of ContentNavigationItem). - `options` (optional): - `labelAttribute`: (string) Which field to use as label (`title` by default) - `deep`: (number or undefined) Controls how many levels of navigation are included (`undefined` by default : includes all levels) **Example:** As shown in the breadcrumb example below, it's commonly used to transform the navigation data into the correct format. ```vue [app.vue] ``` --- # MCP Server > Use Bitrix24 UI components in your AI assistants with Model Context Protocol support. > !WARNING > We are still updating this page. Some data may be missing here — we will complete it shortly. --- # LLMs.txt > How to get AI tools like Cursor, Windsurf, GitHub Copilot, ChatGPT, and Claude to understand Bitrix24 UI components, theming, and best practices. ## What is LLMs.txt? LLMs.txt is a structured documentation format specifically designed for large language models (LLMs). Bitrix24 UI provides LLMs.txt files that contain comprehensive information about our component library, making it easy for AI tools to understand and assist with Bitrix24 UI development. These files are optimized for AI consumption and contain structured information about components, APIs, usage patterns, and best practices. ## Available Routes We provide LLMs.txt routes to help AI tools access our documentation: - **`/llms.txt`** - Contains a structured overview of all components and their documentation links (\~5K tokens) - **`/llms-full.txt`** - Provides comprehensive documentation including implementation details, examples, theming, composables, and migration guidance (\~1M+ tokens) ## Choosing the Right File > !NOTE > strong,\[object Object],Most users should start with ,code,\[object Object],/llms.txt - it contains all essential information and works with standard LLM context windows. > > Use `/llms-full.txt` only if you need comprehensive implementation examples and your AI tool supports large contexts (200K+ tokens). ## Important Usage Notes > !WARNING > strong,\[object Object],@-symbol must be typed manually - When using tools like Cursor or Windsurf, the `@` symbol must be typed by hand in the chat interface. Copy-pasting breaks the tool's ability to recognize it as a context reference. ## Usage with AI Tools ### Cursor Bitrix24 UI provides specialized LLMs.txt files that you can reference in Cursor for better AI assistance with component development. #### How to use: 1. **Direct reference**: Mention the LLMs.txt URLs when asking questions 2. Add these specific URLs to your project context using `@docs` [Read more about Cursor Web and Docs Search](https://docs.cursor.com/en/context/@-symbols/@-docs){rel="nofollow"} ### Windsurf Windsurf can directly access the Bitrix24 UI LLMs.txt files to understand component usage and best practices. #### Using LLMs.txt with Windsurf: - Use `@docs` to reference specific LLMs.txt URLs - Create persistent rules referencing these URLs in your workspace [Read more about Windsurf Web and Docs Search](https://docs.windsurf.com/windsurf/cascade/web-search){rel="nofollow"} ### Other AI Tools Any AI tool that supports LLMs.txt can use these routes to better understand Bitrix24 UI. #### Examples for ChatGPT, Claude, or other LLMs: - "Using Bitrix24 UI documentation from {rel="nofollow"}" - "Follow complete Bitrix24 UI guidelines from {rel="nofollow"}" --- # Accordion > This is a stacked set of collapsible panels ## Usage Use the Accordion component to display a list of collapsible items. ```vue ``` ### Items Use the `items` prop as an array of objects with the following properties: - `label?: string`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `icon?: IconComponent`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `trailingIcon?: IconComponent`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `content?: string`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `value?: string`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `disabled?: boolean`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - [`slot?: string`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"}](https://bitrix24.github.io/b24ui/#with-custom-slot) - `class?: any`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `b24ui?: { item?: ClassNameValue, header?: ClassNameValue, trigger?: ClassNameValue, leadingIcon?: ClassNameValue, label?: ClassNameValue, trailingIcon?: ClassNameValue, content?: ClassNameValue, body?: ClassNameValue }`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} ```vue ``` ### Multiple Set the `type` prop to `multiple` to allow multiple items to be active at the same time. Defaults to `single`. ```vue ``` ### Collapsible When `type` is `single`, you can set the `collapsible` prop to `false` to prevent the active item from collapsing. ```vue ``` ### Unmount Use the `unmount-on-hide` prop to prevent the content from being unmounted when the accordion is collapsed. Defaults to `true`. ```vue ``` > !NOTE > You can inspect the DOM to see each item's content being rendered. ### Disabled Use the `disabled` property to disable the Accordion. You can also disable a specific item by using the `disabled` property in the item object. ```vue ``` ### Trailing Icon Use the `trailing-icon` prop to customize the trailing [Icon](https://bitrix24.github.io/b24icons/icons/){rel="nofollow"} of each item. > !TIP > You can also set an icon for a specific item by using the `trailingIcon` property in the item object. ```vue ``` ## Examples ### Control active item(s) You can control the active item by using the `default-value` prop or the `v-model` directive with the `value` of the item. If no `value` is provided, it defaults to the index **as a string**. ```vue [AccordionModelValueExample.vue] ``` > !CAUTION > When `type="multiple"`, ensure to pass an array to the `default-value` prop or the `v-model` directive. ### With drag and drop Use the [`useSortable`](https://vueuse.org/integrations/useSortable/){rel="nofollow"} composable from [`@vueuse/integrations`](https://vueuse.org/integrations/README.html){rel="nofollow"} to enable drag and drop functionality on the Accordion. This integration wraps [Sortable.js](https://sortablejs.github.io/Sortable/){rel="nofollow"} to provide a seamless drag and drop experience. ```vue [AccordionDragAndDropExample.vue] ``` ### With body slot Use the `#body` slot to customize the body of each item. ```vue [AccordionBodySlotExample.vue] ``` > !TIP > The `#body` slot includes some pre-defined styles, use the [`#content` slot](https://bitrix24.github.io/b24ui/#with-content-slot) if you want to start from scratch. ### With content slot Use the `#content` slot to customize the content of each item. ```vue [AccordionContentSlotExample.vue] ``` ### With custom slot Use the `slot` property to customize a specific item. You will have access to the following slots: - `#{{ item.slot }}`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `#{{ item.slot }}-body`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} ```vue [AccordionCustomSlotExample.vue] ``` ### With markdown content You can use the [MDC](https://github.com/nuxt-modules/mdc?tab=readme-ov-file#mdc){rel="nofollow"} component from `@nuxtjs/mdc` to render markdown in the accordion items. ```vue [AccordionMarkdownExample.vue] ``` ## API ### Props ```ts /** * Props for the Accordion component */ interface AccordionProps { /** * The element or component this component should render as. */ as?: any; items?: AccordionItem[] | undefined; /** * The icon displayed on the right side of the trigger. */ trailingIcon?: IconComponent | undefined; /** * The key used to get the label from the item. * @default "\"label\"" */ labelKey?: string | undefined; b24ui?: { root?: ClassNameValue; item?: ClassNameValue; header?: ClassNameValue; trigger?: ClassNameValue; content?: ClassNameValue; body?: ClassNameValue; leadingIcon?: ClassNameValue; trailingIcon?: ClassNameValue; label?: ClassNameValue; } | undefined; /** * When type is "single", allows closing content when clicking trigger for an open item. * When type is "multiple", this prop has no effect. * @default "true" */ collapsible?: boolean | undefined; /** * The default active value of the item(s). * * Use when you do not need to control the state of the item(s). */ defaultValue?: string | string[] | undefined; /** * The controlled value of the active item(s). * * Use this when you need to control the state of the items. Can be binded with `v-model` */ modelValue?: string | string[] | undefined; /** * Determines whether a "single" or "multiple" items can be selected at a time. * * This prop will overwrite the inferred type from `modelValue` and `defaultValue`. * @default "\"single\"" */ type?: SingleOrMultipleType | undefined; /** * When `true`, prevents the user from interacting with the accordion and all its items */ disabled?: boolean | undefined; /** * When `true`, the element will be unmounted on closed state. * @default "true" */ unmountOnHide?: boolean | undefined; } ``` ### Slots ```ts /** * Slots for the Accordion component */ interface AccordionSlots { leading(): any; default(): any; trailing(): any; content(): any; body(): any; } ``` ### Emits ```ts /** * Emitted events for the Accordion component */ interface AccordionEmits { update:modelValue: (payload: [value: string | string[] | undefined]) => void; } ``` ## Theme ```ts [app.config.ts] export default defineAppConfig({ b24ui: { accordion: { slots: { root: 'w-full', item: 'text-(--b24ui-typography-label-color) border-b border-(--ui-color-divider-vibrant-accent-more) last:border-b-0', header: 'flex', trigger: 'min-w-0 group flex-1 flex items-center gap-1.5 py-[12px] font-(--ui-font-weight-medium) text-(length:--ui-font-size-sm) leading-[20px] focus-visible:outline-(--ui-color-accent-soft-element-blue) cursor-pointer', content: 'motion-safe:data-[state=open]:animate-[accordion-down_200ms_ease-out] motion-safe:data-[state=closed]:animate-[accordion-up_200ms_ease-out] overflow-hidden focus:outline-none', body: 'text-(length:--ui-font-size-sm) pb-[12px]', leadingIcon: 'shrink-0 size-[20px]', trailingIcon: 'shrink-0 size-[20px] ms-auto group-data-[state=open]:rotate-180 transition-transform duration-200', label: 'text-start break-words' }, variants: { disabled: { true: { trigger: 'cursor-not-allowed opacity-75' } } } } } }) ``` --- # Advice > A couple of lines of text and an avatar ## Usage ### Description Use the `description` prop to set the description of the Advice. ```vue ``` ### Icon Use the `icon` prop to show an [Icon](https://bitrix24.github.io/b24icons/icons/){rel="nofollow"}. ```vue ``` ### Avatar Use the `avatar` prop to show an [Avatar](https://bitrix24.github.io/b24ui/raw/docs/components/avatar.md). ```vue ``` ### Angle Use the `angle` prop to change the color the position of the corner. ```vue ``` ### With custom slot Use the slot property to customize a description. ```vue [AdviceExample.vue] ``` ## API ### Props ```ts /** * Props for the Advice component */ interface AdviceProps { /** * The element or component this component should render as. * @default "\"div\"" */ as?: any; description?: string | undefined; /** * @default "\"bottom\"" */ angle?: "bottom" | "top" | undefined; b24ui?: { root?: ClassNameValue; descriptionWrapper?: ClassNameValue; descriptionBorder?: ClassNameValue; descriptionBg?: ClassNameValue; descriptionAngle?: ClassNameValue; description?: ClassNameValue; leading?: ClassNameValue; leadingIcon?: ClassNameValue; leadingAvatar?: ClassNameValue; leadingAvatarIcon?: ClassNameValue; leadingAvatarSize?: ClassNameValue; } | undefined; /** * Display an icon on the left side. */ icon?: IconComponent | undefined; /** * Display an avatar on the left side. */ avatar?: AvatarProps | undefined; } ``` ### Slots ```ts /** * Slots for the Advice component */ interface AdviceSlots { leading(): any; default(): any; } ``` ## Theme ```ts [app.config.ts] export default defineAppConfig({ b24ui: { advice: { slots: { root: 'light style-outline-accent-1 flex items-end', descriptionWrapper: 'relative', descriptionBorder: 'fill-(--b24ui-border-color)', descriptionBg: 'fill-(--b24ui-background) dark:fill-(--ui-color-base-6)', descriptionAngle: 'absolute w-[14px] h-[12px]', description: 'grow w-11/12 py-3 px-md2 ms-2 rounded-[23px] font-[family-name:var(--ui-font-family-secondary)] text-(length:--ui-font-size-md)/(--ui-font-line-height-md) font-(--ui-font-weight-normal) border-1 border-(--b24ui-border-color) bg-(--b24ui-background) text-(--b24ui-color) dark:bg-(--ui-color-base-6)', leading: 'me-1.5 ms-2 font-(--ui-font-weight-medium) text-(--ui-color-design-plain-content-icon-secondary)', leadingIcon: 'shrink-0 size-[42px]', leadingAvatar: 'shrink-0', leadingAvatarIcon: 'text-(--b24ui-typography-label-color) bg-(--ui-color-base-8)', leadingAvatarSize: 'lg' }, variants: { angle: { top: { root: 'items-start', leading: 'mt-0.5', descriptionAngle: 'start-[0.8px] top-[9px] scale-x-100 -scale-y-100 rtl:-scale-x-100' }, bottom: { root: 'items-end', descriptionAngle: 'start-[0.8px] bottom-[9px] rtl:-scale-x-100' } } }, defaultVariants: { angle: 'bottom' } } } }) ``` --- # Alert > An alert designed to capture the user's attention. ## Usage ### Title Use the `title` prop to set the title of the Alert. ```vue ``` ### Description Use the `description` prop to set the description of the Alert. ```vue ``` ### Icon Use the `icon` prop to show an [Icon](https://bitrix24.github.io/b24icons/icons/){rel="nofollow"}. ```vue ``` ### Avatar Use the `avatar` prop to show an [Avatar](https://bitrix24.github.io/b24ui/raw/docs/components/avatar.md). ```vue ``` ### Color Use the `color` prop to change the color of the Alert. ```vue ``` ### Inverted Use the `inverted` prop to invert the color of the Alert. > !WARNING > Only available for `air-primary*` colors ```vue ``` ### Size Use the `size` prop to change the size of the Alert. ```vue ``` ### Close Use the `close` prop to display a [Button](https://bitrix24.github.io/b24ui/raw/docs/components/button.md) to dismiss the Alert. > !TIP > An `update:open` event will be emitted when the close button is clicked. ```vue ``` You can pass any property from the [Button](https://bitrix24.github.io/b24ui/raw/docs/components/button.md) component to customize it. ```vue ``` ### Actions Use the `actions` prop to add some [Button](https://bitrix24.github.io/b24ui/raw/docs/components/button.md) actions to the Alert. ```vue ``` ### Orientation Use the `orientation` prop to change the orientation of the Alert. ```vue ``` ## API ### Props ```ts /** * Props for the Alert component */ interface AlertProps { /** * The element or component this component should render as. */ as?: any; title?: string | undefined; description?: string | undefined; /** * Display an icon on the left side. */ icon?: IconComponent | undefined; avatar?: AvatarProps | undefined; color?: "air-primary" | "air-primary-success" | "air-primary-alert" | "air-primary-warning" | "air-primary-copilot" | "air-secondary" | "air-secondary-alert" | "air-secondary-accent" | "air-secondary-accent-1" | "air-secondary-accent-2" | "air-tertiary"; /** * If set to `true` the color is inverted. * Used for 'air-primary', 'air-primary-success', 'air-primary-alert', 'air-primary-copilot' and 'air-primary-warning' colors. * @default "false" */ inverted?: boolean | undefined; /** * The orientation between the content and the actions. * @default "\"vertical\"" */ orientation?: "vertical" | "horizontal" | undefined; size?: "md" | "sm" | undefined; /** * Display a list of actions: * - under the title and description when orientation is `vertical` * - next to the close button when orientation is `horizontal` * `{ size: 'sm' }`{lang="ts"} */ actions?: ButtonProps[] | undefined; /** * Display a close button to dismiss the alert. * `{ size: 'md', color: 'air-tertiary-no-accent' }`{lang="ts"} */ close?: boolean | Partial | undefined; /** * The icon displayed in the close button. */ closeIcon?: IconComponent | undefined; b24ui?: { root?: ClassNameValue; wrapper?: ClassNameValue; title?: ClassNameValue; description?: ClassNameValue; icon?: ClassNameValue; avatar?: ClassNameValue; avatarSize?: ClassNameValue; actions?: ClassNameValue; close?: ClassNameValue; } | undefined; } ``` ### Slots ```ts /** * Slots for the Alert component */ interface AlertSlots { leading(): any; title(): any; description(): any; actions(): any; close(): any; } ``` ### Emits ```ts /** * Emitted events for the Alert component */ interface AlertEmits { update:open: (payload: [value: boolean]) => void; } ``` ## Theme ```ts [app.config.ts] export default defineAppConfig({ b24ui: { alert: { slots: { root: 'relative overflow-hidden w-full flex text-(--b24ui-color) bg-(--b24ui-background) border-(--b24ui-border-color) border-(length:--b24ui-border-width) rounded-(--ui-border-radius-md)', wrapper: 'min-w-0 flex-1 flex flex-col font-[family-name:var(--ui-font-family-primary)]', title: 'font-(--ui-font-weight-bold)', description: '', icon: 'shrink-0 size-6', avatar: 'shrink-0', avatarSize: '', actions: 'flex flex-wrap gap-1.5 shrink-0', close: 'p-0 [--ui-btn-color:var(--b24ui-color)] hover:bg-(--ui-color-base-white-fixed)/10 focus-visible:bg-(--ui-color-base-white-fixed)/10 -me-1.5 lg:me-0' }, variants: { color: { 'air-primary': { root: 'style-filled' }, 'air-primary-success': { root: 'style-filled-success' }, 'air-primary-alert': { root: 'style-filled-alert' }, 'air-primary-copilot': { root: 'style-filled-copilot' }, 'air-primary-warning': { root: 'style-filled-warning' }, 'air-secondary': { root: 'style-tinted' }, 'air-secondary-alert': { root: 'style-tinted-alert' }, 'air-secondary-accent': { root: 'style-outline' }, 'air-secondary-accent-1': { root: 'style-outline-accent-1' }, 'air-secondary-accent-2': { root: 'style-outline-accent-2' }, 'air-tertiary': { root: 'style-outline-no-accent' }, default: { root: 'style-old-default' }, danger: { root: 'style-old-danger' }, success: { root: 'style-old-success' }, warning: { root: 'style-old-warning' }, primary: { root: 'style-old-primary' }, secondary: { root: 'style-old-secondary' }, collab: { root: 'style-old-collab' }, ai: { root: 'style-old-ai' } }, size: { sm: { root: 'py-xs ps-sm pe-xs gap-2', title: 'text-(length:--ui-font-size-sm)/(--ui-font-line-height-lg)', description: 'text-(length:--ui-font-size-sm)/(--ui-font-line-height-lg)', avatarSize: 'md' }, md: { root: 'py-md ps-md pe-xs gap-2.5', title: 'text-(length:--ui-font-size-md)/(--ui-font-line-height-reset)', description: 'text-(length:--ui-font-size-md)/(--ui-font-line-height-3xs)', avatarSize: 'xl' } }, orientation: { horizontal: { root: 'items-center', actions: 'items-center' }, vertical: { root: 'items-start', actions: 'items-start mt-2' } }, title: { true: { description: 'mt-1' } }, inverted: { true: '', false: '' } }, compoundVariants: [ { inverted: true, color: 'air-primary', class: { root: 'style-filled-inverted' } }, { inverted: true, color: 'air-primary-success', class: { root: 'style-filled-success-inverted' } }, { inverted: true, color: 'air-primary-alert', class: { root: 'style-filled-alert-inverted' } }, { inverted: true, color: 'air-primary-copilot', class: { root: 'style-filled-copilot-inverted' } }, { inverted: true, color: 'air-primary-warning', class: { root: 'style-filled-warning-inverted' } } ], defaultVariants: { color: 'air-secondary-accent', size: 'md', inverted: false } } } }) ``` --- # App > Encases your app to deliver global settings and additional features. ## Usage This component implements Reka UI [ConfigProvider](https://reka-ui.com/docs/utilities/config-provider){rel="nofollow"} to provide global configuration to all components: - Enables all primitives to inherit global reading direction. - Enables changing the behavior of scroll body when setting body lock. - Much more controls to prevent layout shifts. It's also using [ToastProvider](https://reka-ui.com/docs/components/toast#provider){rel="nofollow"} and [TooltipProvider](https://reka-ui.com/docs/components/tooltip#provider){rel="nofollow"} to provide global toasts and tooltips. Use it as at the root of your app: ```vue [app.vue] ``` ::framework-only #nuxt > [!TIP](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/i18n/nuxt.md#locale) > Learn how to use the `locale` prop to change the locale of your app. #vue > [!TIP](https://bitrix24.github.io/b24ui/raw/docs/getting-started/integrations/i18n/vue.md#locale) > Learn how to use the `locale` prop to change the locale of your app. :: ## API ### Props ```ts /** * Props for the App component */ interface AppProps { tooltip?: TooltipProviderProps | undefined; toaster?: ToasterProps | null | undefined; locale?: Locale | undefined; /** * @default "\"body\"" */ portal?: string | boolean | HTMLElement | undefined; /** * The global reading direction of your application. This will be inherited by all primitives. */ dir?: Direction | undefined; /** * The global scroll body behavior of your application. This will be inherited by the related primitives. */ scrollBody?: boolean | ScrollBodyOption | undefined; /** * The global `nonce` value of your application. This will be inherited by the related primitives. */ nonce?: string | undefined; } ``` ### Slots ```ts /** * Slots for the App component */ interface AppSlots { default(): any; } ``` --- # Avatar > An img element that includes fallback and supports Nuxt Image. ## Usage The Avatar uses the `` component when [`@nuxt/image`](https://github.com/nuxt/image){rel="nofollow"} is installed, falling back to `img` otherwise. ```vue ``` > !NOTE > You can pass any property from the HTML `` element such as `alt`, `loading`, etc. ### Src Use the `src` prop to set the image URL. ```vue ``` ### Size Use the `size` prop to set the size of the Avatar. ```vue ``` > !NOTE > The `` element's `width` and `height` are automatically set based on the `size` prop. ### Icon Use the `icon` prop to display a fallback [Icon](https://bitrix24.github.io/b24icons/icons/){rel="nofollow"}. ```vue ``` ### Text Use the `text` prop to display a fallback text. ```vue ``` ### Alt When no icon or text is provided, the **initials** of the `alt` prop is used as fallback. ```vue ``` > !NOTE > The `alt` prop is passed to the `img` element as the `alt` attribute. ### Chip Use the `chip` prop to display a chip around the Avatar. ```vue ``` ## Examples ### With tooltip You can use a [Tooltip](https://bitrix24.github.io/b24ui/raw/docs/components/tooltip.md) component to display a tooltip when hovering the Avatar. ```vue [AvatarTooltipExample.vue] ``` ### With mask You can use a CSS mask to display an Avatar with a custom shape instead of a simple circle. ```vue [AvatarMaskExample.vue] ``` ## API ### Props ```ts /** * Props for the Avatar component */ interface AvatarProps { /** * The element or component this component should render as. */ as?: any; src?: string | undefined; alt?: string | undefined; /** * Display an icon on the left side. */ icon?: IconComponent | undefined; text?: string | undefined; size?: "md" | "3xs" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl" | undefined; chip?: boolean | ChipProps | undefined; b24ui?: { root?: ClassNameValue; image?: ClassNameValue; fallback?: ClassNameValue; icon?: ClassNameValue; } | undefined; crossorigin?: "" | "anonymous" | "use-credentials" | undefined; decoding?: "async" | "auto" | "sync" | undefined; height?: Numberish | undefined; loading?: "lazy" | "eager" | undefined; referrerpolicy?: HTMLAttributeReferrerPolicy | undefined; sizes?: string | undefined; srcset?: string | undefined; usemap?: string | undefined; width?: Numberish | undefined; } ``` > [!NOTE](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attributes) > This component also supports all native `` HTML attributes. ## Theme ```ts [app.config.ts] export default defineAppConfig({ b24ui: { avatar: { slots: { root: 'air-secondary-accent inline-flex items-center justify-center shrink-0 select-none rounded-full align-middle bg-(--ui-color-base-8) ring ring-(--ui-color-base-7)', image: 'h-full w-full rounded-[inherit] object-cover', fallback: 'font-(--ui-font-weight-medium) text-(--ui-color-design-plain-content-icon-secondary) truncate', icon: 'text-(--ui-color-design-plain-content-icon-secondary) shrink-0' }, variants: { size: { '3xs': { root: 'size-[10px] text-4xs font-(--ui-font-weight-regular)', icon: 'size-[10px]' }, '2xs': { root: 'size-[20px] text-(length:--ui-font-size-4xs)/(--ui-font-line-height-reset) font-(--ui-font-weight-regular)', icon: 'size-[18px]' }, xs: { root: 'size-[24px] text-(length:--ui-font-size-3xs)/(--ui-font-line-height-reset) font-(--ui-font-weight-regular)', icon: 'size-[22px]' }, sm: { root: 'size-[28px] text-(length:--ui-font-size-xs)/(--ui-font-line-height-reset)', icon: 'size-[26px]' }, md: { root: 'size-[32px] text-(length:--ui-font-size-sm)/(--ui-font-line-height-reset)', icon: 'size-[28px]' }, lg: { root: 'size-[42px] text-(length:--ui-font-size-2xl)/(--ui-font-line-height-reset)', icon: 'size-[38px]' }, xl: { root: 'ring-2 size-[48px] text-(length:--ui-font-size-2xl)/(--ui-font-line-height-reset)', icon: 'size-[44px]' }, '2xl': { root: 'ring-2 size-[60px] text-(length:--ui-font-size-5xl)/(--ui-font-line-height-reset)', icon: 'size-[56px]' }, '3xl': { root: 'ring-2 size-[94px] text-[34px]/(--ui-font-line-height-reset)', icon: 'size-[90px]' } } }, defaultVariants: { size: 'md' } } } }) ``` --- # AvatarGroup > Pile multiple avatars into a single group. ## Usage Wrap multiple [Avatar](https://bitrix24.github.io/b24ui/raw/docs/components/avatar.md) within an AvatarGroup to stack them. ```vue ``` ### Size Use the `size` prop to change the size of all the avatars. ```vue ``` ### Max Use the `max` prop to limit the number of avatars displayed. The rest is displayed as an `+X` avatar. ```vue ``` ## Examples ### With tooltip Wrap each avatar with a [Tooltip](https://bitrix24.github.io/b24ui/raw/docs/components/tooltip.md) to display a tooltip on hover. ```vue [AvatarGroupTooltipExample.vue] ``` ### With chip Wrap each avatar with a [Chip](https://bitrix24.github.io/b24ui/raw/docs/components/chip.md) to display a chip around the avatar. ```vue [AvatarGroupChipExample.vue] ``` ### With link Wrap each avatar with a [Link](https://bitrix24.github.io/b24ui/raw/docs/components/link.md) to make them clickable. ```vue [AvatarGroupLinkExample.vue] ``` ### With mask Wrap an avatar with a CSS mask to display it with a custom shape. ```vue [AvatarGroupMaskExample.vue] ``` > !WARNING > The `chip` prop does not work correctly when using a mask. Chips may be cut depending on the mask shape. ## API ### Props ```ts /** * Props for the AvatarGroup component */ interface AvatarGroupProps { /** * The element or component this component should render as. */ as?: any; size?: "md" | "3xs" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl" | undefined; /** * The maximum number of avatars to display. */ max?: string | number | undefined; b24ui?: { root?: ClassNameValue; base?: ClassNameValue; } | undefined; } ``` ### Slots ```ts /** * Slots for the AvatarGroup component */ interface AvatarGroupSlots { default(): any; } ``` ## Theme ```ts [app.config.ts] export default defineAppConfig({ b24ui: { avatarGroup: { slots: { root: 'inline-flex justify-end', base: 'relative rounded-full last:me-0' }, variants: { size: { '3xs': { base: '-me-0.5' }, '2xs': { base: '-me-0.5' }, xs: { base: '-me-0.5' }, sm: { base: '-me-1.5' }, md: { base: '-me-1.5' }, lg: { base: '-me-1.5' }, xl: { base: '-me-2' }, '2xl': { base: '-me-2' }, '3xl': { base: '-me-2' } } }, defaultVariants: { size: 'md' } } } }) ``` --- # Badge > A short descriptor for a status or category. ## Usage ### Label Use the default slot to set the label of the Badge. ```vue ``` You can achieve the same result by using the `label` prop. Use the `use-link` prop to show underline. ```vue ``` ### Color Use the `color` prop to change the color of the Badge. ```vue ``` ### Inverted Use the `inverted` prop to invert the color of the Badge. > !WARNING > Only available for `air-primary*` colors ```vue ``` ### Size Use the `size` prop to change the size of the Badge. ```vue ``` ### Icon Use the `icon` prop to show an [Icon](https://bitrix24.github.io/b24icons/icons/){rel="nofollow"} inside the Badge. ```vue ``` Use the `use-close` prop to show close icon. ```vue ``` ### Avatar Use the `avatar` prop to show an [Avatar](https://bitrix24.github.io/b24ui/raw/docs/components/avatar.md) inside the Badge. ```vue ``` ## API ### Props ```ts /** * Props for the Badge component */ interface BadgeProps { /** * The element or component this component should render as. * @default "\"span\"" */ as?: any; label?: string | number | undefined; color?: "air-primary" | "air-primary-success" | "air-primary-alert" | "air-primary-warning" | "air-primary-copilot" | "air-secondary" | "air-secondary-alert" | "air-secondary-accent" | "air-secondary-accent-1" | "air-secondary-accent-2" | "air-tertiary" | "air-selection"; /** * If set to `true` the color is inverted. * Used for 'air-primary', 'air-primary-success', 'air-primary-alert', 'air-primary-copilot' and 'air-primary-warning' colors. * @default "false" */ inverted?: boolean | undefined; size?: "xss" | "xs" | "sm" | "md" | "lg" | "xl" | undefined; /** * Render the badge with equal padding on all sides. */ square?: boolean | undefined; /** * Shows 'underline' on hover */ useLink?: boolean | undefined; /** * Shows icons.close on the right side */ useClose?: boolean | undefined; onCloseClick?: ((event: MouseEvent) => void | Promise) | ((event: MouseEvent) => void | Promise)[] | undefined; b24ui?: { base?: ClassNameValue; wrapper?: ClassNameValue; label?: ClassNameValue; leadingIcon?: ClassNameValue; leadingAvatar?: ClassNameValue; leadingAvatarSize?: ClassNameValue; trailingIcon?: ClassNameValue; } | undefined; /** * Display an icon on the left side. */ icon?: IconComponent | undefined; /** * Display an avatar on the left side. */ avatar?: AvatarProps | undefined; /** * When `true`, the icon will be displayed on the right side. */ trailing?: boolean | undefined; /** * Display an icon on the right side. */ trailingIcon?: IconComponent | undefined; } ``` ### Slots ```ts /** * Slots for the Badge component */ interface BadgeSlots { leading(): any; default(): any; trailing(): any; } ``` ## Theme ```ts [app.config.ts] export default defineAppConfig({ b24ui: { badge: { slots: { base: 'ui-label__scope --air select-none font-[family-name:var(--ui-font-family-secondary)] font-(--ui-label-font-weight) text-(length:--ui-label-font-size)/normal inline-flex items-center transition-all duration-200 ease-linear px-(--ui-label-inline-space) text-(--b24ui-color) bg-(--b24ui-background) border-(--b24ui-border-color) border-(length:--b24ui-border-width)', wrapper: 'h-(--ui-label-height) inline-flex items-center', label: 'max-w-full whitespace-nowrap text-ellipsis decoration-from-font', leadingIcon: 'shrink-0', leadingAvatar: 'shrink-0', leadingAvatarSize: '', trailingIcon: 'shrink-0 cursor-pointer hover:rounded-(--ui-border-radius-circle) hover:bg-current/20' }, variants: { fieldGroup: { horizontal: 'focus-visible:outline-none ring ring-inset ring-0 focus-visible:ring-2 group-[.is-field-group]/items:not-only:first:rounded-e-none group-[.is-field-group]/items:not-only:last:rounded-s-none group-[.is-field-group]/items:not-last:not-first:rounded-none group-[.is-field-group]/items:not-only:first:border-e-0 group-[.is-field-group]/items:not-only:not-first:border-s-0 focus-visible:z-[1]', vertical: 'focus-visible:outline-none ring ring-inset ring-0 focus-visible:ring-2 not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]' }, noSplit: { false: "group-[.is-field-group]/items:not-only:not-first:after:content-[''] group-[.is-field-group]/items:not-only:not-first:after:absolute group-[.is-field-group]/items:not-only:not-first:after:top-[7px] group-[.is-field-group]/items:not-only:not-first:after:bottom-[6px] group-[.is-field-group]/items:not-only:not-first:after:left-0 group-[.is-field-group]/items:not-only:not-first:after:w-px group-[.is-field-group]/items:not-only:not-first:after:bg-current/30" }, useLink: { true: { base: 'cursor-pointer', wrapper: 'group', label: 'group-hover:underline group-hover:decoration-dashed' } }, useClose: { true: 'pe-2xs', false: '' }, leading: { true: 'ps-1', false: '' }, color: { 'air-primary': { base: 'style-filled' }, 'air-primary-success': { base: 'style-filled-success' }, 'air-primary-alert': { base: 'style-filled-alert' }, 'air-primary-copilot': { base: 'style-filled-copilot' }, 'air-primary-warning': { base: 'style-filled-warning' }, 'air-secondary': { base: 'style-tinted' }, 'air-secondary-alert': { base: 'style-tinted-alert' }, 'air-secondary-accent': { base: 'style-outline' }, 'air-secondary-accent-1': { base: 'style-outline-accent-1' }, 'air-secondary-accent-2': { base: 'style-outline-accent-2' }, 'air-tertiary': { base: 'style-outline-no-accent' }, 'air-selection': { base: 'style-selection' }, default: { base: 'style-old-default' }, danger: { base: 'style-old-danger' }, success: { base: 'style-old-success' }, warning: { base: 'style-old-warning' }, primary: { base: 'style-old-primary' }, secondary: { base: 'style-old-secondary' }, collab: { base: 'style-old-collab' }, ai: { base: 'style-old-ai' } }, size: { xss: { base: 'ui-label-xss gap-0.5', wrapper: 'gap-0.5', label: 'underline-offset-1', leadingIcon: 'size-[12px]', leadingAvatarSize: '3xs', trailingIcon: 'size-[12px]' }, xs: { base: 'ui-label-xs gap-0.5', wrapper: 'gap-0.5', label: 'underline-offset-1', leadingIcon: 'size-[12px]', leadingAvatarSize: '3xs', trailingIcon: 'size-[12px]' }, sm: { base: 'ui-label-sm gap-1', wrapper: 'gap-1', label: 'underline-offset-1', leadingIcon: 'size-[14px]', leadingAvatarSize: '3xs', trailingIcon: 'size-[14px]' }, md: { base: 'ui-label-md gap-1', wrapper: 'gap-1', label: 'underline-offset-1', leadingIcon: 'size-[15px]', leadingAvatarSize: '3xs', trailingIcon: 'size-[15px]' }, lg: { base: 'ui-label-lg gap-1', wrapper: 'gap-1', label: '', leadingIcon: 'size-[22px]', leadingAvatarSize: '2xs', trailingIcon: 'size-[22px]' }, xl: { base: 'ui-label-xl gap-1', wrapper: 'gap-1', label: '', leadingIcon: 'size-[22px]', leadingAvatarSize: '2xs', trailingIcon: 'size-[22px]' } }, square: { true: { base: 'rounded-[calc(var(--ui-label-height)_/_4)] ', wrapper: 'w-(--ui-label-height)', label: 'overflow-hidden' }, false: { base: 'rounded-[calc(var(--ui-label-height)_/_2)]' } }, inverted: { true: { base: 'border-(--b24ui-color)' }, false: '' } }, compoundVariants: [ { inverted: true, color: 'air-primary', class: { base: 'style-filled-inverted' } }, { inverted: true, color: 'air-primary-success', class: { base: 'style-filled-success-inverted' } }, { inverted: true, color: 'air-primary-alert', class: { base: 'style-filled-alert-inverted' } }, { inverted: true, color: 'air-primary-copilot', class: { base: 'style-filled-copilot-inverted' } }, { inverted: true, color: 'air-primary-warning', class: { base: 'style-filled-warning-inverted' } }, { size: 'xss', square: true, class: { base: 'p-0 ps-0 pe-0', wrapper: 'px-[2px] gap-0', leadingIcon: 'size-[6px]' } }, { size: 'xs', square: true, class: { base: 'p-0 ps-0 pe-0', wrapper: 'px-[2px] gap-0', leadingIcon: 'size-[10px]' } }, { size: 'sm', square: true, class: { base: 'p-0 ps-0 pe-0', wrapper: 'p-[1px] gap-0', leadingIcon: 'size-[16px]' } }, { size: 'md', square: true, class: { base: 'p-0 ps-0 pe-0', wrapper: 'p-[1px] gap-0', leadingIcon: 'size-[18px]' } }, { size: 'lg', square: true, class: { base: 'p-0 ps-0 pe-0', wrapper: 'p-[1px] gap-0', leadingIcon: 'size-[23px]' } }, { size: 'xl', square: true, class: { base: 'p-0 ps-0 pe-0', wrapper: 'p-[1px] gap-0', leadingIcon: 'size-[28px]' } }, { fieldGroup: [ 'horizontal', 'vertical' ], size: [ 'xl', 'lg', 'md' ], class: 'rounded-(--ui-border-radius-md)' }, { fieldGroup: [ 'horizontal', 'vertical' ], size: 'sm', class: 'rounded-(--ui-border-radius-sm)' }, { fieldGroup: [ 'horizontal', 'vertical' ], size: 'xs', class: 'rounded-(--ui-border-radius-xs)' }, { fieldGroup: [ 'horizontal', 'vertical' ], size: 'xss', class: 'rounded-[5px]' } ], defaultVariants: { color: 'air-primary', size: 'md', square: false, inverted: false } } } }) ``` --- # Banner > Top banner for important user messages. ## Usage ### Title Use the `title` prop to display a title on the Banner. ```vue ``` ### Icon Use the `icon` prop to display an icon on the Banner. ```vue ``` ### Color Use the `color` prop to change the color of the Banner. ```vue ``` ### Close Use the `close` prop to display a [Button](https://bitrix24.github.io/b24ui/raw/docs/components/button.md) to dismiss the Banner. Defaults to `false`. > !TIP > A `close` event will be emitted when the close button is clicked. ```vue [BannerExample.vue] ``` > !NOTE > When closed, `banner-${id}` will be stored in the local storage to prevent it from being displayed again. :br For the example above, `banner-example` will be stored in the local storage. ### Close Icon Use the `close-icon` prop to customize the close button [Icon](https://bitrix24.github.io/b24icons/icons/){rel="nofollow"}. Defaults to `CrossMIcon`. ```vue [BannerWithTitleExample.vue] ``` ### Actions Use the `actions` prop to add some [Button](https://bitrix24.github.io/b24ui/raw/docs/components/button.md) actions to the Banner. ```vue ``` > !NOTE > The action buttons default to `color="air-secondary-no-accen"` and `size="xs"`. You can customize these values by passing them directly to each action button. ### Link You can pass any property from the [``](https://nuxt.com/docs/api/components/nuxt-link){rel="nofollow"} component such as `to`, `target`, `rel`, etc. ```vue ``` > !NOTE > The `NuxtLink` component will inherit all other attributes you pass to the `Banner` component. ## Examples ### Within `app.vue` Use the Banner component in your `app.vue` or in a layout: ```vue [app.vue] {3-7} ``` ## API ### Props ```ts /** * Props for the Banner component */ interface BannerProps { /** * The element or component this component should render as. */ as?: any; /** * A unique id saved to local storage to remember if the banner has been dismissed. * Change this value to show the banner again. */ id?: string | undefined; /** * The icon displayed next to the title. */ icon?: IconComponent | undefined; title?: string | undefined; /** * Display a list of actions next to the title. * `{ color: 'air-secondary-no-accent', size: 'xs' }`{lang="ts-type"} */ actions?: ButtonProps[] | undefined; to?: string | RouteLocationAsRelativeGeneric | RouteLocationAsPathGeneric | undefined; target?: "_blank" | "_parent" | "_self" | "_top" | (string & {}) | null | undefined; color?: "air-primary" | "air-primary-success" | "air-primary-alert" | "air-primary-warning" | "air-primary-copilot" | "air-secondary" | "air-secondary-alert" | "air-secondary-accent" | "air-secondary-accent-1" | "air-secondary-accent-2" | "air-tertiary"; /** * Display a close button to dismiss the banner. * `{ size: 'md', color: 'air-tertiary-no-accent' }`{lang="ts-type"} */ close?: boolean | Partial | undefined; /** * The icon displayed in the close button. */ closeIcon?: IconComponent | undefined; b24ui?: { root?: ClassNameValue; container?: ClassNameValue; left?: ClassNameValue; center?: ClassNameValue; right?: ClassNameValue; icon?: ClassNameValue; title?: ClassNameValue; actions?: ClassNameValue; close?: ClassNameValue; } | undefined; } ``` ### Slots ```ts /** * Slots for the Banner component */ interface BannerSlots { leading(): any; title(): any; actions(): any; close(): any; } ``` ### Emits ```ts /** * Emitted events for the Banner component */ interface BannerEmits { close: (payload: []) => void; } ``` ## Theme ```ts [app.config.ts] export default defineAppConfig({ b24ui: { banner: { slots: { root: 'relative z-50 w-full bg-(--b24ui-background) transition-colors', container: 'flex items-center justify-between gap-3 h-12', left: 'hidden lg:flex-1 lg:flex lg:items-center', center: 'flex items-center gap-1.5 min-w-0', right: 'lg:flex-1 flex items-center justify-end', icon: 'size-5 shrink-0 text-(--b24ui-color) pointer-events-none', title: 'text-(length:--ui-font-size-sm)/(--ui-font-line-height-sm) text-(--b24ui-color) font-(--ui-font-weight-medium) truncate', actions: 'flex gap-1.5 shrink-0 isolate', close: '[--ui-btn-color:var(--b24ui-color)] hover:bg-(--ui-color-base-white-fixed)/10 focus-visible:bg-(--ui-color-base-white-fixed)/10 -me-1.5 lg:me-0' }, variants: { color: { 'air-primary': { root: 'style-filled' }, 'air-primary-success': { root: 'style-filled-success' }, 'air-primary-alert': { root: 'style-filled-alert' }, 'air-primary-copilot': { root: 'style-filled-copilot' }, 'air-primary-warning': { root: 'style-filled-warning' }, 'air-secondary': { root: 'style-tinted' }, 'air-secondary-alert': { root: 'style-tinted-alert' }, 'air-secondary-accent': { root: 'style-outline' }, 'air-secondary-accent-1': { root: 'style-outline-accent-1' }, 'air-secondary-accent-2': { root: 'style-outline-accent-2' }, 'air-tertiary': { root: 'style-outline-no-accent' } }, to: { true: '' } }, compoundVariants: [ { to: true, class: { root: 'hover:bg-(--b24ui-background)/90' } } ], defaultVariants: { color: 'air-primary-alert' } } } }) ``` --- # Breadcrumb > A breadcrumb navigation component. ## Usage Use the Breadcrumb component to show the current page's location in your site's hierarchy. ```vue ``` ### Items Use the `items` prop as an array of objects with the following properties: - `label?: string`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - [`icon?: IconComponent`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"}](https://bitrix24.github.io/b24ui/#with-custom-slot) - `avatar?: AvatarProps`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - [`slot?: string`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"}](https://bitrix24.github.io/b24ui/#with-custom-slot) - `class?: any`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `b24ui?: { item?: ClassNameValue, link?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLeadingAvatar?: ClassNameValue, linkLabel?: ClassNameValue, separator?: ClassNameValue, separatorIcon?: ClassNameValue }`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} You can pass any property from the [Link](https://bitrix24.github.io/b24ui/raw/docs/components/link.md#props) component such as `to`, `target`, etc. ```vue ``` > !NOTE > A `span` is rendered instead of a link when the `to` property is not defined. ### Separator Icon Use the `separator-icon` prop to customize the [Icon](https://bitrix24.github.io/b24icons/icons/){rel="nofollow"} between each item. ```vue ``` ## Examples ### With separator slot Use the `#separator` slot to customize the separator between each item. ```vue [BreadcrumbSeparatorSlotExample.vue] ``` ### With custom slot Use the `slot` property to customize a specific item. You will have access to the following slots: - `#{{ item.slot }}`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `#{{ item.slot }}-leading`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `#{{ item.slot }}-label`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} - `#{{ item.slot }}-trailing`{.shiki,shiki-themes,material-theme-palenight,material-theme-palenight,material-theme-palenight lang="ts-type"} ```vue [BreadcrumbCustomSlotExample.vue] ``` > [!TIP](https://bitrix24.github.io/b24ui/#slots) > You can also use the `#item`, `#item-leading`, `#item-label` and `#item-trailing` slots to customize all items. ## API ### Props ```ts /** * Props for the Breadcrumb component */ interface BreadcrumbProps { /** * The element or component this component should render as. * @default "\"nav\"" */ as?: any; items?: BreadcrumbItem[] | undefined; /** * The icon to use as a separator. */ separatorIcon?: IconComponent | undefined; /** * The key used to get the label from the item. * @default "\"label\"" */ labelKey?: GetItemKeys | undefined; b24ui?: { root?: ClassNameValue; list?: ClassNameValue; item?: ClassNameValue; link?: ClassNameValue; linkLeadingIcon?: ClassNameValue; linkLeadingAvatar?: ClassNameValue; linkLeadingAvatarSize?: ClassNameValue; linkLabel?: ClassNameValue; separator?: ClassNameValue; separatorIcon?: ClassNameValue; } | undefined; } ``` ### Slots ```ts /** * Slots for the Breadcrumb component */ interface BreadcrumbSlots { item(): any; item-leading(): any; item-label(): any; item-trailing(): any; separator(): any; } ``` ## Theme ```ts [app.config.ts] export default defineAppConfig({ b24ui: { breadcrumb: { slots: { root: 'relative min-w-0', list: 'flex items-center gap-[6px]', item: 'flex min-w-0', link: 'group relative flex items-center gap-[6px] text-(length:--ui-font-size-sm) min-w-0 -mt-px focus-visible:outline-(--ui-color-accent-main-primary)', linkLeadingIcon: 'shrink-0 size-[20px]', linkLeadingAvatar: 'shrink-0', linkLeadingAvatarSize: '2xs', linkLabel: 'truncate', separator: 'flex', separatorIcon: 'shrink-0 size-[20px] text-(--ui-color-base-6)' }, variants: { active: { true: { link: 'text-(--ui-color-design-selection-content) hover:text-(--ui-color-accent-main-primary-alt-2) hover:underline font-(--ui-font-weight-semi-bold)' }, false: { link: 'text-(--b24ui-typography-legend-color) font-(--ui-font-weight-medium)' } }, disabled: { true: { link: 'cursor-not-allowed opacity-30' } }, to: { true: '' } }, compoundVariants: [ { disabled: false, active: false, to: true, class: { link: 'hover:text-(--ui-color-accent-main-primary-alt-2) hover:underline transition-colors' } } ] } } }) ``` --- # Button > A button capable of linking or performing an action. ## Usage Use the default slot to set the label of the Button. ```vue ``` ### Label Use the `label` prop to set the label of the Button. ```vue ``` ### Color Use the `color` prop to change the color of the Button. ```vue ``` ### Size Use the `size` prop to change the size of the Button. ```vue ``` ### Icon Use the `icon` prop to show an [Icon](https://bitrix24.github.io/b24icons/icons/){rel="nofollow"} inside the Button. ```vue ``` Use the `use-dropdown` prop to show trailing-icon. ```vue ``` The `label` as prop or slot is optional so you can use the Button as an icon-only button. ```vue ``` ### Avatar Use the `avatar` prop to show an [Avatar](https://bitrix24.github.io/b24ui/raw/docs/components/avatar.md) inside the Button. ```vue ``` The `label` as prop or slot is optional so you can use the Button as an avatar-only button. ```vue ``` ### Link You can pass any property from the [Link](https://bitrix24.github.io/b24ui/raw/docs/components/link.md#props) component such as `to`, `target`, etc. ```vue ``` When the Button is a link or when using the `active` prop, you can use the `active-color` props to customize the active state. ```vue ``` You can also use the `active-class` and `inactive-class` props to customize the active state. ```vue ``` ### Loading Use the `loading` prop to show a loading icon and disable the Button. ```vue ``` Use the `loading-auto` prop to show the loading icon automatically while the `@click` promise is pending. ```vue [ButtonLoadingAutoExample.vue] ``` This also works with the [Form](https://bitrix24.github.io/b24ui/raw/docs/components/form.md) component. ```vue [ButtonLoadingAutoFormExample.vue] ``` ### Loading Icon Use `use-clock` or `use-wait` props to show different loading icons. ```vue ``` ### Disabled Use the `disabled` prop to disable the Button. ```vue ``` ### Rounded Use the `rounded` prop to round the Button. ```vue ``` ### Block Use the `block` property to set `w-full` for the Button. ```vue ``` ### NormalCase Use the `normalCase` property to set `uppercase` for the Button. ```vue ``` ## API ### Props ```ts /** * Props for the Button component */ interface ButtonProps { label?: string | undefined; 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" | "link"; activeColor?: "default" | "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" | "danger" | "success" | "warning" | "primary" | "secondary" | "collab" | "ai" | "link" | undefined; size?: "xs" | "md" | "xss" | "sm" | "lg" | "xl" | undefined; /** * Rounds the corners of the button */ rounded?: boolean | undefined; /** * Render the button full width */ block?: boolean | undefined; /** * Set loading state automatically based on the `@click` promise state */ loadingAuto?: boolean | undefined; /** * Disable uppercase label * @default "true" */ normalCase?: boolean | undefined; /** * Shows LoaderWaitIcon in loading mode */ useWait?: boolean | undefined; /** * Shows LoaderClockIcon icon in loading mode */ useClock?: boolean | undefined; /** * Shows icons.ChevronDownSIcon on the right side */ useDropdown?: boolean | undefined; onClick?: ((event: MouseEvent) => void | Promise) | ((event: MouseEvent) => void | Promise)[] | undefined; /** * The class to apply when the link is active */ activeClass?: string | undefined; /** * The class to apply when the link is inactive */ inactiveClass?: string | undefined; b24ui?: { base?: ClassNameValue; baseLoading?: ClassNameValue; baseLoadingWaitIcon?: ClassNameValue; baseLoadingClockIcon?: ClassNameValue; baseLoadingSpinnerIcon?: ClassNameValue; baseLine?: ClassNameValue; label?: ClassNameValue; labelInner?: ClassNameValue; leadingIcon?: ClassNameValue; leadingAvatar?: ClassNameValue; leadingAvatarSize?: ClassNameValue; trailingIcon?: ClassNameValue; safeList?: ClassNameValue; } | undefined; /** * Display an icon on the left side. */ icon?: IconComponent | undefined; /** * Display an avatar on the left side. */ avatar?: AvatarProps | undefined; /** * When `true`, the loading icon will be displayed. */ loading?: boolean | undefined; /** * Route Location the link should navigate to when clicked on. */ to?: string | RouteLocationAsRelativeGeneric | RouteLocationAsPathGeneric | undefined; /** * Class to apply when the link is exact active */ exactActiveClass?: string | undefined; /** * Value passed to the attribute `aria-current` when the link is exact active. */ ariaCurrentValue?: "page" | "step" | "location" | "date" | "time" | "true" | "false" | undefined; /** * Pass the returned promise of `router.push()` to `document.startViewTransition()` if supported. */ viewTransition?: boolean | undefined; /** * Calls `router.replace` instead of `router.push`. */ replace?: boolean | undefined; autofocus?: Booleanish | undefined; disabled?: boolean | undefined; form?: string | undefined; formaction?: string | undefined; formenctype?: string | undefined; formmethod?: string | undefined; formnovalidate?: Booleanish | undefined; formtarget?: string | undefined; name?: string | undefined; /** * The type of the button when not a link. * @default "\"button\"" */ type?: "reset" | "submit" | "button" | undefined; download?: any; /** * An alias for `to`. If used with `to`, `href` will be ignored */ href?: string | RouteLocationAsRelativeGeneric | RouteLocationAsPathGeneric | undefined; hreflang?: string | undefined; media?: string | undefined; ping?: string | undefined; /** * A rel attribute value to apply on the link. Defaults to "noopener noreferrer" for external links. */ rel?: "noopener" | "noreferrer" | "nofollow" | "sponsored" | "ugc" | (string & {}) | null | undefined; /** * Where to display the linked URL, as the name for a browsing context. */ target?: (string & {}) | "_blank" | "_parent" | "_self" | "_top" | null | undefined; referrerpolicy?: HTMLAttributeReferrerPolicy | undefined; /** * The element or component this component should render as when not a link. */ as?: any; /** * Force the link to be active independent of the current route. */ active?: boolean | undefined; /** * Will only be active if the current route is an exact match. */ exact?: boolean | undefined; /** * Allows controlling how the current route query sets the link as active. */ exactQuery?: boolean | "partial" | undefined; /** * Will only be active if the current route hash is an exact match. */ exactHash?: boolean | undefined; /** * When `true`, uses special underlined styling. */ isAction?: boolean | undefined; /** * Forces the link to be considered as external (true) or internal (false). This is helpful to handle edge-cases */ external?: boolean | undefined; /** * If set to true, no rel attribute will be added to the link */ noRel?: boolean | undefined; /** * A class to apply to links that have been prefetched. */ prefetchedClass?: string | undefined; /** * When enabled will prefetch middleware, layouts and payloads of links in the viewport. */ prefetch?: boolean | undefined; /** * Allows controlling when to prefetch links. By default, prefetch is triggered only on visibility. */ prefetchOn?: "visibility" | "interaction" | Partial<{ visibility: boolean; interaction: boolean; }> | undefined; /** * Escape hatch to disable `prefetch` attribute. */ noPrefetch?: boolean | undefined; /** * An option to either add or remove trailing slashes in the `href` for this specific link. * Overrides the global `trailingSlash` option if provided. */ trailingSlash?: "append" | "remove" | undefined; } ``` > [!NOTE](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attributes) > This component also supports all native `