Skip to content

Latest commit

 

History

History
987 lines (768 loc) · 39.5 KB

File metadata and controls

987 lines (768 loc) · 39.5 KB

Bitrix24 UI Kit — Руководство для ИИ агентов

Краткая сводка

Bitrix24 UI Kit (@bitrix24/b24ui-nuxt) — это UI-библиотека для разработки веб-приложений через REST API Bitrix24 на базе Nuxt и Vue. Библиотека предоставляет готовые компоненты, повторяющие дизайн Bitrix24, что позволяет разработчикам быстро создавать красивые и консистентные приложения.

Проект УЖЕ содержит необходимую базовую структуру и настройки для frontend на базе Nuxt с интеграцией Bitrix24 UI Kit. При добавлении функционала нужно придерживаться этой структуры и использовать компоненты из @bitrix24/b24ui-nuxt.

Актуальная структура проекта:

frontend/
├── app/
│   ├── app.config.ts          # Конфигурация B24UI
│   ├── app.vue                # Корневой компонент
│   ├── assets/css/main.css    # Главный CSS файл
│   ├── components/            # Компоненты приложения
│   │   ├── BackendStatus.vue
│   │   └── Logo.vue
│   ├── composables/           # Переиспользуемая логика
│   ├── pages/                 # Страницы Nuxt
│   │   ├── index.client.vue
│   │   ├── install.client.vue
│   │   ├── handler/
│   │   └── slider/
│   └── stores/                # Pinia stores
├── nuxt.config.ts            # Конфигурация Nuxt
├── package.json              # Зависимости
└── i18n/                     # Интернационализация
    ├── locales/
    └── i18n.map.ts

Ключевые особенности:

  • Основан на Nuxt UI, но адаптирован под дизайн-систему Bitrix24
  • Использует Tailwind CSS 4 и Tailwind Variants для стилизации
  • Поддерживает Nuxt 4+ и Vue 3 + Vite
  • Включает 80+ компонентов и composables
  • Интегрируется с @bitrix24/b24icons-vue (1400+ иконок)

Важно: Всегда используйте компоненты именно из @bitrix24/b24ui-nuxt, а НЕ из Nuxt UI!

Особенности настройки frontend проекта с B24UI

nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['@bitrix24/b24ui-nuxt']
})

assets/css/main.css:

@import "tailwindcss";
@import "@bitrix24/b24ui-nuxt";

app.vue:

<template>
  <B24App :locale="locales[locale]">
    <NuxtLoadingIndicator color="var(--ui-color-design-filled-warning-bg)" :height="3" />
    <B24DashboardGroup>
      <NuxtLayout>
        <NuxtPage />
      </NuxtLayout>
    </B24DashboardGroup>
  </B24App>
</template>

Основные требования

1. Обязательное использование B24App

Оборачивайте приложение в <B24App> для корректной работы Toast, Tooltip, Modal и программных оверлеев:

<template>
  <B24App>
    <!-- ваш контент -->
  </B24App>
</template>

📖 Компонент B24App

2. Префикс компонентов

Все компоненты используют префикс B24:

  • <B24Button>, <B24Input>, <B24Modal>, <B24Form> и т.д.

3. Работа с иконками

Иконки импортируются из @bitrix24/b24icons-vue:

<script setup>
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
</script>

<template>
  <B24Button :icon="RocketIcon" label="Запуск" />
</template>

📖 Полный список иконок
📖 Метаданные иконок
📖 Интеграция иконок

4. Страницы и шаблоны страниц

Приложение в базовом виде содержит примеры реализации некоторых страниц в папке pages/:

  • index.client.vue — главная страница приложения
  • install.client.vue — страница установки приложения
  • slider/app-options.client.vue — страница настроек приложения в слайдере
  • handler/placement-crm-deal-detail-tab.client.vue — пример страницы для встройки в карточку сделки
  • handler/uf.demo.client.vue — пример страницы для встройки пользовательского типа поля
  • handler/background-some-problem-client.vue - пример страницы об ошибке

Важно: все страницы выполняются ТОЛЬКО на клиенте, поскольку frontend будет собираться в виде статики для показа внутри фрейма Bitrix24. Поэтому все файлы страниц имеют суффикс .client.vue.

При создании новых страниц подбирай подходящий шаблон из layouts/ для консистентного внешнего вида. Обычно используется default.vue, который уже содержит B24SidebarLayout.

  • placement.vue — для страниц реализующих виджеты;
  • slider.vue - для страниц реализующих слайдеры, открывающиеся вне текущего iframe интерфейса приложения;
  • uf-placement.vue - для страниц реализующих встройку пользовательских типов полей. Подробности про этот тип встройки виджетов.

5. Стилизация через b24ui и class

Компоненты поддерживают два способа кастомизации:

Через b24ui prop (для слотов внутри компонента):

<B24Button 
  :b24ui="{ 
    baseLine: 'justify-center', 
    leadingIcon: 'text-red-500' 
  }" 
/>

Через class prop (для корневого элемента):

<B24Button class="font-bold rounded-full" />

Старайтесь избегать глобальных CSS переопределений, чтобы не нарушить дизайн-систему, а также избегайте лишних стилей оформления без необходимости - компоненты по умолчанию уже стилизованы согласно гайдлайнам Bitrix24.

📖 Кастомизация компонентов

6. Варианты темы (theme variants)

Компоненты используют систему вариантов. Основные параметры:

color: air-primary, air-secondary-no-accent, air-primary-success, air-primary-alert, air-primary-warning, air-primary-copilot, air-secondary-accent, air-tertiary и др.

size: xss, xs, sm, md, lg, xl (зависит от компонента)

Пример:

<B24Button 
  color="air-primary" 
  size="md" 
  rounded
  loading-auto
/>

📖 Все theme файлы

Основные компоненты и заготовки для типовых сценариев

Для реализации пользовательских сценариев в интерфейсе необходимо ориентироваться на заготовки в файлах accordion.md, calendar.md, form.md, selector.md, settings-page.md, table-and-grid.md. Если нужный сценарий этими заготовками реализовать нельзя, следует использовать компоненты из этого раздела.

Кнопки и действия

B24Button — основная кнопка
📖 Исходный код
📖 Theme

<B24Button 
  label="Сохранить"
  color="air-primary"
  size="md"
  :icon="SaveIcon"
  loading-auto
  @click="handleSave"
/>

B24FieldGroup — группа кнопок
📖 Исходный код
📖 Theme

Формы и ввод

B24Input — текстовый инпут
📖 Исходный код
📖 Theme

<B24Input 
  v-model.trim="email"
  type="email"
  placeholder="Email"
  color="air-primary"
  size="md"
/>

B24Textarea — многострочный ввод
📖 Исходный код
📖 Theme

B24Select — выпадающий список
📖 Исходный код
📖 Theme

<B24Select
  v-model="selected"
  :items="[
    { label: 'Опция 1', value: '1' },
    { label: 'Опция 2', value: '2' }
  ]"
  placeholder="Выберите..."
/>

B24Checkbox — чекбокс
📖 Исходный код
📖 Theme

B24RadioGroup — группа радио-кнопок
📖 Исходный код
📖 Theme

B24Switch — переключатель
📖 Исходный код
📖 Theme

B24Form + B24FormField — форма с валидацией (Zod, Valibot, Yup и др.)
📖 Исходный код Form
📖 Исходный код FormField
📖 Theme Form
📖 Theme FormField
📖 Документация

<B24Form :state="state" :schema="schema" @submit="onSubmit">
  <B24FormField name="email" label="Email" required>
    <B24Input v-model="state.email" type="email" />
  </B24FormField>
  
  <B24Button type="submit" color="air-primary" loading-auto>
    Отправить
  </B24Button>
</B24Form>

Оверлеи и уведомления

B24Modal — модальное окно
📖 Исходный код
📖 Theme
📖 Документация

<B24Modal title="Заголовок" description="Описание">
  <B24Button label="Открыть" />
  
  <template #body>
    <p>Содержимое модалки</p>
  </template>
  
  <template #footer="{ close }">
    <B24Button color="air-primary" @click="save">Сохранить</B24Button>
    <B24Button color="air-tertiary" @click="close">Отмена</B24Button>
  </template>
</B24Modal>

B24Slideover — боковая панель
📖 Исходный код
📖 Theme

B24Toast — уведомления (обычно через useToast())
📖 Исходный код
📖 Theme

B24Tooltip — всплывающие подсказки
📖 Исходный код
📖 Theme

B24Popover — всплывающий контейнер
📖 Исходный код
📖 Theme

Навигация и меню

B24NavigationMenu — навигационное меню
📖 Исходный код
📖 Theme

B24DropdownMenu — выпадающее меню
📖 Исходный код
📖 Theme

B24Tabs — вкладки
📖 Исходный код
📖 Theme

B24Breadcrumb — хлебные крошки
📖 Исходный код
📖 Theme

Макеты (Layouts)

B24SidebarLayout — основной layout с боковой панелью
📖 Исходный код
📖 Theme

Этот компонент УЖЕ используется в качестве основы базовой страницы в шаблоне layouts/defeult.vue проекта. Если страница приложения создается на базе этого шаблона, НЕЛЬЗЯ использовать B24SidebarLayout внутри страницы повторно.

Правила размещения контента в B24SidebarLayout

  • Компоненты страницы рендерятся внутри <slot> компонента B24SidebarLayout через активный layout.
  • Размещайте контент непосредственно в slot — без дополнительных обёрток для центрирования (flex items-center justify-center, min-h-screen, min-h-dvh, max-w-* контейнеры).
  • Layout уже обеспечивает корректные отступы, фон и поведение прокрутки.
  • Используйте B24Card (или другие компоненты B24) напрямую как корневой элемент шаблона страницы.
  • Для состояний загрузки используйте B24Skeleton вместо скрытия всей страницы.
  • ❌ Неправильно: <div class="flex items-center justify-center min-h-screen"><B24Card class="max-w-md">…</B24Card></div>
  • ✅ Правильно: <B24Card>…</B24Card> (или <div class="flex flex-col gap-4 p-6"><B24Card>…</B24Card></div> для страниц с несколькими карточками)

Связанные компоненты:

Отображение данных

B24Avatar / B24AvatarGroup — аватары
📖 Avatar: исходный код / theme
📖 AvatarGroup: исходный код / theme

B24Badge — бейджи
📖 Исходный код
📖 Theme

B24Chip — числовые метки
📖 Исходный код
📖 Theme

B24Card — карточка
📖 Исходный код
📖 Theme

B24Alert / B24Advice — предупреждения и советы
📖 Alert: исходный код / theme
📖 Advice: исходный код / theme

B24Table / B24TableWrapper — таблицы
📖 Table: исходный код / theme
📖 TableWrapper: исходный код / theme

B24DescriptionList — список описаний
📖 Исходный код
📖 Theme

B24Skeleton — skeleton loader
📖 Исходный код
📖 Theme

B24Empty — пустое состояние
📖 Исходный код
📖 Theme

Другие компоненты

B24Progress — прогресс-бар
📖 Исходный код
📖 Theme

B24Range — слайдер
📖 Исходный код
📖 Theme

B24Calendar — календарь
📖 Исходный код
📖 Theme

B24Countdown — таймер обратного отсчета
📖 Исходный код
📖 Theme

B24Accordion / B24Collapsible — раскрывающиеся блоки
📖 Accordion: исходный код / theme
📖 Collapsible: исходный код / theme

B24Separator — разделитель
📖 Исходный код
📖 Theme

B24Kbd — клавиша клавиатуры
📖 Исходный код
📖 Theme

Основные Composables

useToast()

Управление уведомлениями.

📖 Исходный код

const toast = useToast()

// Добавить уведомление
toast.add({ 
  title: 'Успех', 
  description: 'Данные сохранены',
  color: 'air-primary-success' 
})

// Обновить
toast.update(id, { title: 'Обновлено' })

// Удалить
toast.remove(id)

// Очистить все
toast.clear()

useOverlay()

Программное управление модальными окнами и slideоvers.

📖 Исходный код

const overlay = useOverlay()

// Создать экземпляр
const modal = overlay.create(MyModalComponent, { 
  props: { title: 'Заголовок' },
  destroyOnClose: true
})

// Открыть и получить результат
const opened = modal.open({ additionalProp: 'value' })
const result = await opened.result // ждет emit('close', payload)

// Закрыть
modal.close(resultValue)

// Обновить props на лету
modal.patch({ title: 'Новый заголовок' })

defineShortcuts()

Регистрация глобальных горячих клавиш.

📖 Исходный код

defineShortcuts({
  'meta_k': () => openCommandPalette(),
  'escape': () => closeAllOverlays(),
  'ctrl_s': (e) => { e.preventDefault(); save() }
})

useLocale() / defineLocale()

Интернационализация.

📖 useLocale: исходный код
📖 defineLocale: исходный код

useConfetti()

Конфетти-анимация.

📖 Исходный код

const confetti = useConfetti()
confetti.fire()

useFormField()

Интеграция с формой для кастомных компонентов.

📖 Исходный код

Что делать при ошибках

1. Проверьте установку и конфигурацию

Убедитесь, что:

  • @bitrix24/b24ui-nuxt установлен
  • Модуль добавлен в nuxt.config.ts
  • CSS импортирован
  • Приложение обернуто в <B24App>

2. Проверьте правильность использования компонента

  1. Найдите исходный код компонента в GitHub:

    • Перейдите в src/runtime/components/
    • Откройте нужный компонент (например, Button.vue)
    • Изучите Props, Slots, Emits
  2. Проверьте theme компонента:

    • Перейдите в src/theme/
    • Откройте файл темы (например, button.ts)
    • Проверьте доступные variants, slots, defaultVariants
  3. Изучите документацию (если есть):

3. Проверьте совместимость версий

{
  "dependencies": {
    "@bitrix24/b24ui-nuxt": "^2.0.0",
    "@bitrix24/b24icons-vue": "^2.0.0",
    "nuxt": "^4.0.0",
    "vue": "^3.0.0"
  }
}

4. Типичные проблемы и решения

Проблема: Компоненты не рендерятся
Решение: Проверьте наличие <B24App> в корне приложения

Проблема: Toast/Tooltip/Modal не работают
Решение: Убедитесь, что используется <B24App> (предоставляет OverlayProvider)

Проблема: Иконки не отображаются
Решение: Проверьте правильность импорта из @bitrix24/b24icons-vue/category/IconName

Проблема: Стили не применяются
Решение: Убедитесь, что CSS импортирован (@import "@bitrix24/b24ui-nuxt")

Проблема: TypeScript ошибки
Решение: Проверьте типы в исходниках компонента или theme файле

5. Ссылки для диагностики

Полезные ресурсы

Принципы работы с UI Kit

  1. Всегда используйте B24 префикс — это компоненты Bitrix24 UI, а не Nuxt UI
  2. Оборачивайте в B24App — обязательно для работы оверлеев и уведомлений
  3. Используйте b24ui prop — для точной кастомизации слотов компонента
  4. Следуйте дизайн-системе — используйте предустановленные цвета (air-*) и размеры
  5. Проверяйте theme — для понимания доступных вариантов и слотов
  6. Изучайте исходники — они хорошо документированы и содержат TypeScript типы

💾 Управление состоянием

1. Pinia Store (рекомендуется для Vue/Nuxt)

В проекте используется Pinia для управления состоянием. Создавайте stores в папке composables/ или stores/ используя Composition API:

// composables/useDeals.ts
export const useDealsStore = defineStore('deals', () => {
  // Состояние
  const deals = ref<Deal[]>([]);
  const currentDeal = ref<Deal | null>(null);
  const isLoading = ref(false);
  const error = ref<string | null>(null);
  
  // Фильтры
  const filters = ref<DealFilters>({
    stage: null,
    search: '',
    dateFrom: null,
    dateTo: null
  });

  // Геттеры
  const filteredDeals = computed(() => {
    let result = deals.value;
    
    if (filters.value.stage) {
      result = result.filter(deal => deal.stageId === filters.value.stage);
    }
    
    if (filters.value.search) {
      const search = filters.value.search.toLowerCase();
      result = result.filter(deal => 
        deal.title.toLowerCase().includes(search)
      );
    }
    
    return result;
  });

  // Действия
  async function fetchDeals() {
    isLoading.value = true;
    error.value = null;
    
    try {
      const { data } = await $fetch<{data: Deal[]}>('/api/deals');
      deals.value = data;
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to fetch deals';
    } finally {
      isLoading.value = false;
    }
  }

  return {
    // State
    deals: readonly(deals),
    currentDeal: readonly(currentDeal),
    isLoading: readonly(isLoading),
    error: readonly(error),
    filters,
    
    // Getters
    filteredDeals,
    
    // Actions
    fetchDeals
  };
});

2. Composables для переиспользования логики

// composables/useApi.ts
export function useApi() {
  const isLoading = ref(false);
  const error = ref<string | null>(null);

  async function apiCall<T>(
    url: string, 
    options?: RequestInit
  ): Promise<T | null> {
    isLoading.value = true;
    error.value = null;
    
    try {
      const response = await $fetch<T>(url, options);
      return response;
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'API call failed';
      return null;
    } finally {
      isLoading.value = false;
    }
  }

  return {
    isLoading: readonly(isLoading),
    error: readonly(error),
    apiCall
  };
}

🎨 Стилизация с Tailwind CSS 4

Проект использует Tailwind CSS 4 через Vite плагин, что отличается от классической конфигурации:

Конфигурация

nuxt.config.ts:

import tailwindcss from '@tailwindcss/vite'

export default defineNuxtConfig({
  vite: {
    plugins: [tailwindcss()]
  }
})

assets/css/main.css:

@import "tailwindcss";
@import "@bitrix24/b24ui-nuxt";

@theme static {
  /* Кастомные утилиты здесь */
}

Расширение тем Tailwind

@theme {
  --color-primary-50: theme(colors.blue.50);
  --color-primary-500: theme(colors.blue.500);
  --color-primary-900: theme(colors.blue.900);
  
  --font-family-brand: ui-serif, serif;
  
  --spacing-18: 4.5rem;
}

📱 Адаптивный дизайн

Breakpoints и сетки

<!-- Адаптивная сетка -->
<template>
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
    <!-- Карточки -->
    <B24Card
      v-for="item in items"
      :key="item.id"
      class="p-4"
    >
      {{ item.title }}
    </B24Card>
  </div>
</template>

Мобильная навигация с B24UI

<!-- components/MobileNavigation.vue -->
<template>
  <div class="lg:hidden">
    <!-- Мобильное меню -->
    <B24Button
      variant="ghost"
      @click="isOpen = !isOpen"
    >
      <B24Icon name="bars-3" />
    </B24Button>

    <!-- Выдвижная панель -->
    <B24Slideover v-model="isOpen" side="left">
      <B24Card class="p-4">
        <nav class="space-y-2">
          <NuxtLink
            v-for="item in navigation"
            :key="item.to"
            :to="item.to"
            class="block px-4 py-2 rounded-lg hover:bg-gray-100"
            @click="isOpen = false"
          >
            {{ item.label }}
          </NuxtLink>
        </nav>
      </B24Card>
    </B24Slideover>
  </div>
</template>

⚡ Производительность

1. Ленивая загрузка компонентов

<script setup>
// Ленивая загрузка тяжелых компонентов
const LazyChart = defineAsyncComponent(() => import('~/components/Chart.vue'));
const LazyDataTable = defineAsyncComponent(() => import('~/components/DataTable.vue'));

const showChart = ref(false);
</script>

<template>
  <div>
    <!-- Основной контент загружается сразу -->
    <B24Card class="mb-4">
      <B24Button @click="showChart = true" v-if="!showChart">
        Показать график
      </B24Button>
    </B24Card>
    
    <!-- Тяжелые компоненты загружаются по требованию -->
    <LazyChart v-if="showChart" :data="chartData" />
  </div>
</template>

2. Паттерны списков с B24UI

<!-- components/DealList.vue -->
<template>
  <B24Container class="py-8">
    <!-- Заголовок и действия -->
    <div class="mb-6 flex items-center justify-between">
      <h1 class="text-2xl font-bold">Сделки</h1>
      <B24Button @click="openCreateModal">
        Создать сделку
      </B24Button>
    </div>

    <!-- Фильтры -->
    <B24Card class="mb-6 p-4">
      <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
        <B24Select
          v-model="filters.stage"
          :options="stageOptions"
          placeholder="Выберите стадию"
        />
        <B24Input
          v-model="filters.search"
          placeholder="Поиск по названию"
        >
          <template #leading>
            <B24Icon name="magnifying-glass" />
          </template>
        </B24Input>
        <B24Button
          variant="outline"
          @click="clearFilters"
        >
          Очистить фильтры
        </B24Button>
      </div>
    </B24Card>

    <!-- Таблица -->
    <B24Card>
      <B24Table
        :columns="columns"
        :rows="filteredDeals"
        :loading="isLoading"
      >
        <template #actions="{ row }">
          <div class="flex gap-2">
            <B24Button size="sm" @click="editDeal(row.id)">
              Редактировать
            </B24Button>
            <B24Button
              size="sm"
              color="red"
              variant="outline"
              @click="deleteDeal(row.id)"
            >
              Удалить
            </B24Button>
          </div>
        </template>
      </B24Table>
    </B24Card>
  </B24Container>
</template>

🔧 Утилиты и помощники

Форматтеры данных

// utils/formatters.ts
export const formatters = {
  // Форматирование валюты
  currency(amount: number, currency: string = 'RUB'): string {
    return new Intl.NumberFormat('ru-RU', {
      style: 'currency',
      currency: currency,
      minimumFractionDigits: 0,
      maximumFractionDigits: 2
    }).format(amount);
  },

  // Форматирование даты
  date(date: string | Date, format: 'short' | 'long' = 'short'): string {
    const d = typeof date === 'string' ? new Date(date) : date;
    
    if (format === 'short') {
      return d.toLocaleDateString('ru-RU');
    }
    
    return d.toLocaleDateString('ru-RU', {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
      hour: '2-digit',
      minute: '2-digit'
    });
  },

  // Относительное время  
  timeAgo(date: string | Date): string {
    const d = typeof date === 'string' ? new Date(date) : date;
    const now = new Date();
    const diff = now.getTime() - d.getTime();
    
    const minutes = Math.floor(diff / 60000);
    const hours = Math.floor(diff / 3600000);
    const days = Math.floor(diff / 86400000);
    
    if (minutes < 1) return 'только что';
    if (minutes < 60) return `${minutes} мин. назад`;
    if (hours < 24) return `${hours} ч. назад`;
    if (days < 7) return `${days} дн. назад`;
    
    return d.toLocaleDateString('ru-RU');
  },

  // Сокращение текста
  truncate(text: string, length: number = 100): string {
    if (text.length <= length) return text;
    return text.slice(0, length) + '...';
  }
};

🎯 Best practices

1. Компонентная архитектура

  • Используйте B24 компоненты вместо нативных HTML элементов
  • Разделяйте презентационные и контейнерные компоненты
  • Создавайте переиспользуемые композиции из B24UI компонентов
  • Документируйте API компонентов через props и emits

2. Управление состоянием

  • Локальное состояние для UI логики компонента
  • Pinia Store для глобального состояния приложения
  • Composables для переиспользуемой логики
  • Избегайте prop drilling, используйте provide/inject

3. Производительность

  • Ленивая загрузка компонентов и маршрутов
  • Виртуализация для больших списков (через B24Table)
  • Мемоизация вычислений через computed
  • Дебаунс для пользовательского ввода

4. Доступность

  • B24UI уже включает ARIA атрибуты
  • Семантические компоненты (B24Card, B24Table)
  • Клавиатурная навигация работает из коробки
  • Контрастность цветов соответствует дизайн-системе

Версия: 2.1.0
Последнее обновление: Ноябрь 2025
Лицензия: MIT