The Editor component is now implemented! Check it out.
v2.1.16
/
  • Get Started
  • Components
  • Composables
  • Typography
  • GitHub
  • Layout
  • App
  • Container
  • Error
  • SidebarLayout
  • Element
  • Advice
  • Alert
  • Avatar
  • AvatarGroup
  • Badge
  • Banner
  • Button
  • Calendar
  • Card
  • Chip
  • Collapsible
  • Countdown
  • FieldGroup
  • Kbd
  • Progress
  • Separator
  • Skeleton
  • Form
  • Checkbox
  • CheckboxGroup
  • ColorPicker
  • FileUpload
  • Form
  • FormField
  • Input
  • InputDate
  • InputMenu
  • InputNumber
  • InputTags
  • InputTime
  • PinInput
  • RadioGroup
  • Range
  • Select
  • SelectMenu
  • Switch
  • Textarea
  • Data
  • Accordion
  • DescriptionList
  • Empty
  • Table
  • TableWrapper
  • Timeline
  • User
  • Navigation
  • Breadcrumb
  • CommandPalette
  • Link
  • NavigationMenu
  • Pagination
  • Stepper
  • Tabs
  • Overlay
  • ContextMenu
  • DropdownMenu
  • Modal
  • Popover
  • Slideover
  • Toast
  • Tooltip
  • Page
  • PageCard
  • PageColumns
  • PageGrid
  • PageLinks
  • PageList
  • Dashboard
  • DashboardGroup
  • DashboardSearch
  • DashboardSearchButton
  • AI Chat
  • soonChatMessage
  • soonChatMessages
  • soonChatPalette
  • soonChatPrompt
  • soonChatPromptSubmit
  • Editor
  • NewEditor
  • NewEditorDragHandle
  • NewEditorEmojiMenu
  • NewEditorMentionMenu
  • NewEditorSuggestionMenu
  • NewEditorToolbar
  • Content
  • ContentSearch
  • ContentSearchButton
  • ContentSurround
  • ContentToc
  • Color Mode
  • ColorModeAvatar
  • ColorModeButton
  • ColorModeImage
  • ColorModeSelect
  • ColorModeSwitch
  • i18n
  • LocaleSelect
  • b24icons
  • b24jssdk
Use our Nuxt starter
v2.1.16
  • Docs
  • Components
  • Composables
  • Typography

SidebarLayout

You incorporate a sidebar in the slider and CRM entity tab embedding. Overall, it's stylish, trendy, and youthful
GitHub
Demo

Usage

The styling process is described on the page Theme

Layout

The component must be used as a layout.

<script setup lang="ts">
import { ref } from 'vue'
import type { SidebarLayoutProps } from '@bitrix24/b24ui-nuxt'
import RocketIcon from '@bitrix24/b24icons-vue/outline/RocketIcon'
import BusinesProcessStagesIcon from '@bitrix24/b24icons-vue/outline/BusinesProcessStagesIcon'
import MoreMIcon from '@bitrix24/b24icons-vue/outline/MoreMIcon'

const checkedUseLightContent = ref(true)

// Manage loading state
const handleAction = async () => {
  // Performing an asynchronous operation
  await new Promise(resolve => setTimeout(resolve, 2_000))
}

// This is for demonstration purposes only
const customUIForDemo = {
  root: 'h-[400px] min-h-[400px]',
  loadingWrapper: 'h-[400px] min-h-[400px]',
  sidebar: 'relative z-[0]',
  contentWrapper: 'lg:pl-0',
  container: 'min-h-[calc(100vh-var(--topbar-height)-32px)]'
} as SidebarLayoutProps['b24ui']
</script>

<template>
  <B24SidebarLayout
    :use-light-content="checkedUseLightContent"
    :b24ui="customUIForDemo"
  >
    <template #sidebar>
      <!-- Your sidebar -->
      <B24SidebarHeader>
        <!-- Navigation header -->
        <div class="h-full flex items-center relative my-0 ps-[25px] pe-xs rtl:pe-[25px]">
          <ProseH4 class="font-(--ui-font-weight-medium) mb-0">
            SideBar
          </ProseH4>
        </div>
      </B24SidebarHeader>
      <B24SidebarBody>
        <!-- Navigation elements -->
        <B24SidebarSection>
          <B24NavigationMenu
            :items="[{ label: 'Page 1', type: 'trigger', active: true }, { label: 'Page 2', type: 'trigger' }]"
            orientation="vertical"
          />
        </B24SidebarSection>

        <B24SidebarSpacer />
        <B24SidebarSection>
          <B24NavigationMenu
            :items="[{ label: 'Page 3', type: 'trigger' }, { label: 'Page 4', type: 'trigger' }]"
            orientation="vertical"
          />
        </B24SidebarSection>
      </B24SidebarBody>
      <B24SidebarFooter>
        <!-- Navigation footer -->
        <B24SidebarSection>
          <B24PageLinks
            :links="[
              {
                label: 'b24ui',
                to: 'https://bitrix24.github.io/b24ui/',
                target: '_blank'
              }
            ]"
            class="mb-[12px]"
          />
          <B24Button
            block
            label="Docs"
            color="air-boost"
            size="sm"
            loading-auto
            :icon="RocketIcon"
            to="https://bitrix24.github.io/b24ui/"
            target="_blank"
          />
        </B24SidebarSection>
      </B24SidebarFooter>
    </template>

    <template #navbar>
      <!-- Your navigation bar -->
      <B24NavbarSection class="hidden sm:inline-flex">
        <B24NavigationMenu
          :items="[{ label: 'Page 1', type: 'trigger', active: true }, { label: 'Page 2', type: 'trigger' }]"
          orientation="horizontal"
        />
      </B24NavbarSection>
      <B24NavbarSpacer />
      <B24NavbarSection class="flex-row items-center justify-start gap-4">
        <B24DropdownMenu
          arrow
          :items="[{ label: 'Value 1' }, { label: 'Value 2' }]"
        >
          <B24Button
            color="air-secondary-accent"
            size="xs"
            rounded
            use-dropdown
            label="Action"
          />
        </B24DropdownMenu>
        <B24Switch
          v-model="checkedUseLightContent"
          size="xs"
        />
        <B24Button
          label="Reload"
          color="air-secondary-accent"
          rounded
          size="xs"
          loading-auto
          @click="handleAction"
        />
      </B24NavbarSection>
    </template>

    <template #content-top>
      <div class="w-full flex flex-col gap-[20px] lg:mt-[22px]">
        <div class="lg:rounded-(--ui-border-radius-md) lg:border-1 border-(--ui-color-design-tinted-na-stroke) backdrop-blur-md bg-(--ui-color-design-tinted-na-bg) p-[24px] lg:px-[22px] lg:py-[15px] flex flex-col items-start justify-between gap-[14px]">
          <div class="w-full flex flex-row items-center justify-between gap-[20px]">
            <div class="flex-1 flex flex-row items-center justify-end gap-[12px]">
              <B24Avatar
                :icon="BusinesProcessStagesIcon"
                alt="Workflows"
                size="xl"
                :b24ui="{
                  root: 'bg-(--ui-color-primary-alt)',
                  icon: 'size-[36px] text-(--ui-color-palette-white-base)'
                }"
              />
              <div class="flex-1">
                <!-- Page Title -->
                <ProseH1 class="mb-0 text-(--b24ui-typography-label-color) leading-[29px] font-(--ui-font-weight-light)">
                  Some title
                </ProseH1>
              </div>
            </div>
            <div class="flex-1 flex flex-row items-center justify-end gap-[12px]">
              <B24DropdownMenu
                :items="[{ label: 'Value 1' }, { label: 'Value 2' }]"
                :content="{ side: 'bottom', align: 'end' }"
              >
                <B24Button size="sm" :icon="MoreMIcon" color="air-secondary-accent" />
              </B24DropdownMenu>
            </div>
          </div>
        </div>
      </div>
    </template>

    <template #content-actions>
      <!-- Actions on page -->
      <div class="hidden lg:inline-flex">
        <B24Button
          color="air-secondary-accent"
          label="Action"
          loading-auto
          @click="handleAction"
        />
      </div>
    </template>

    <!-- Main content -->
    <div>
      <ProseP>Your main content goes here</ProseP>
    </div>

    <template #content-bottom>
      <!-- Bottom of page -->
      <ProseP small accent="less-more" class="mt-[12px] px-[22px] pb-[2px]">
        Footer or additional information
      </ProseP>
    </template>
  </B24SidebarLayout>
</template>
On mobile devices the sidebar is hidden and accessible via slideover

Inner

If the component needs to be placed inside the content, then the props isInner must be set.

You can control the content area scrollbar using the props offContentScrollbar.

<script setup lang="ts">
import type { SidebarLayoutProps } from '@bitrix24/b24ui-nuxt'
import NotificationIcon from '@bitrix24/b24icons-vue/outline/NotificationIcon'
import SidebarLayoutInnerAction from './SidebarLayoutInnerAction.vue'

// Manage loading state
const handleAction = async () => {
  // Performing an asynchronous operation
  await new Promise(resolve => setTimeout(resolve, 4_000))
}

// This is for demonstration purposes only
const customUIForDemo = {
  root: 'h-[400px] min-h-[400px]',
  loadingWrapper: 'h-[400px] min-h-[400px]',
  sidebar: 'relative z-[0]',
  contentWrapper: 'lg:pl-0',
  container: 'min-h-[calc(100vh-var(--topbar-height)-12px)]'
} as SidebarLayoutProps['b24ui']

// This is for demonstration purposes only
const customUIInnerForDemo = {
  loadingWrapper: 'h-[400px] min-h-[400px]'
} as SidebarLayoutProps['b24ui']
</script>

<template>
  <B24SidebarLayout
    :use-light-content="false"
    :b24ui="customUIForDemo"
  >
    <template #navbar>
      <!-- Your navigation bar -->
      <B24NavbarSection class="hidden sm:inline-flex">
        <B24NavigationMenu
          :items="[{ label: 'Page 1', type: 'trigger', active: true }, { label: 'Page 2', type: 'trigger' }]"
          orientation="horizontal"
        />
      </B24NavbarSection>
      <B24NavbarSpacer />
      <B24NavbarSection>
        <B24Button
          label="Reload"
          color="air-secondary-accent"
          rounded
          size="xs"
          loading-auto
          @click="handleAction"
        />
      </B24NavbarSection>
    </template>

    <!-- Main content -->
    <div class="mt-[12px] relative h-full rounded-t-[12px] overflow-hidden">
      <div class="size-full rounded-t-[12px]">
        <B24SidebarLayout
          :use-light-content="false"
          is-inner
          off-content-scrollbar
          :b24ui="{
            ...customUIInnerForDemo,
            root: [
              'edge-light',
              '[--leftmenu-bg-expanded:#eef2f4!important]',
              '[--air-theme-bg-color:#eef2f4]',
              '[--air-theme-bg-size:240px_240px]',
              '[--air-theme-bg-repeat:repeat]',
              '[--air-theme-bg-position:0_0]',
              '[--air-theme-bg-attachment:fixed]',
              '[--air-theme-bg-image:url(/bg/edge-light-v1.svg)]',
              '[--air-theme-bg-image-blurred:url(/bg/edge-light-v1-blurred.webp)]'
            ].join(' '),
            contentWrapper: [
              'bg-[url(/bg/pattern-1.png)] bg-cover bg-center bg-fixed bg-no-repeat bg-[#799fe1]/10',
              'p-0 px-0 ps-0 pe-0 lg:p-0 lg:px-0 lg:ps-0 lg:pe-0 '
            ].join(' '),
            containerWrapper: 'h-full relative',
            containerWrapperInner: 'flex flex-col items-center justify-center'
          } as SidebarLayoutProps['b24ui']"
        >
          <template #sidebar>
            <B24SidebarHeader>
              <div class="text-[#f8f7f7] h-full flex items-center relative my-0 ps-[25px] pe-xs rtl:pe-[25px]">
                <ProseH6 class="font-(--ui-font-weight-medium) mb-0">
                  Settings
                </ProseH6>
              </div>
            </B24SidebarHeader>
            <B24SidebarBody>
              <div class="space-y-6 px-[25px]">
                <B24Switch label="Expand" class="mt-1" />
                <B24Switch label="isShowProgress" class="mt-1" />
              </div>
            </B24SidebarBody>
          </template>
          <template #navbar>
            <ProseH4 class="font-(--ui-font-weight-medium) mb-0">
              Demo
            </ProseH4>
            <B24NavbarSpacer />
          </template>
          <template #default>
            <div class="mt-[22px] text-(--ui-color-design-filled-market-content) max-w-[550px] mx-(--content-area-shift) px-[60px] py-[20px] rounded-[24px] bg-[#525c69]/20 flex flex-col items-center justify-center gap-[20px]">
              <B24Avatar
                :icon="NotificationIcon"
                alt="Toast"
                size="xl"
                :b24ui="{
                  root: 'bg-transparent ring-2 ring-(--ui-color-design-filled-market-content)/50',
                  icon: 'size-[44px] text-(--ui-color-design-filled-market-content)'
                }"
              />
              <ProseH2 class="text-center text-(--ui-color-design-filled-market-content) leading-[29px] mb-0">
                Some text
              </ProseH2>
              <div class="flex flex-col sm:flex-row items-center justify-center gap-[15px]">
                <SidebarLayoutInnerAction />
              </div>
            </div>
          </template>
        </B24SidebarLayout>
      </div>
    </div>
  </B24SidebarLayout>
</template>

Slideover

It should be understood that the Slideover component displays data using the SidebarLayout component.

<script setup lang="ts">
import { ref } from 'vue'
import TrendUpIcon from '@bitrix24/b24icons-vue/outline/TrendUpIcon'
import TrendDownIcon from '@bitrix24/b24icons-vue/outline/TrendDownIcon'
import BusinesProcessStagesIcon from '@bitrix24/b24icons-vue/outline/BusinesProcessStagesIcon'

const openListItem = ref(false)

// Manage loading state
const handleAction = async () => {
  await new Promise(resolve => setTimeout(resolve, 2_000))
}
</script>

<template>
  <B24Slideover
    ref="currentSlideoverRef"
    title="Some list"
    description="Some description"
    :use-light-content="false"
    :b24ui="{
      content: 'sm:max-w-[970px] sm:top-[275px] sm:max-h-[calc(100%-275px)]',
      sidebarLayoutRoot: [
        'edge-dark',
        'edge-dark:[--air-theme-bg-color:#7c235b]',
        'edge-dark:[--air-theme-bg-size:cover]',
        'edge-dark:[--air-theme-bg-repeat:no-repeat]',
        'edge-dark:[--air-theme-bg-position:0_0]',
        'edge-dark:[--air-theme-bg-attachment:local]',
        'edge-dark:[--air-theme-bg-image:url(/bg/edge-dark-v2.jpg)]',
        'edge-dark:[--air-theme-bg-image-blurred:url(/bg/edge-dark-v2-blurred.webp)]'
      ].join(' '),
      sidebarLayoutLoadingIcon: 'text-(--ui-color-gray-70)'
    }"
  >
    <B24Button label="Some list" color="air-boost" />
    <template #body>
      <div class="light mt-[22px] rounded-(--ui-border-radius-md) bg-(--ui-color-background-primary)">
        <B24TableWrapper
          row-hover
          class="overflow-x-auto w-full"
        >
          <table>
            <!-- head -->
            <thead>
              <tr>
                <th>#</th>
                <th>Company</th>
                <th>Status</th>
                <th>Amount (USD)</th>
              </tr>
            </thead>
            <tbody>
              <!-- row 1 -->
              <tr>
                <th>1</th>
                <td><B24Link @click="openListItem = true">Tech Innovators Inc.</B24Link></td>
                <td><B24Badge label="Proposal Sent" use-link use-close /></td>
                <td>50,000</td>
              </tr>
              <!-- row 2 -->
              <tr>
                <th>2</th>
                <td><B24Link @click="openListItem = true">Global Solutions Ltd.</B24Link></td>
                <td><B24Badge label="Negotiation" use-link inverted use-close /></td>
                <td>120,000</td>
              </tr>
              <!-- row 3 -->
              <tr>
                <th>3</th>
                <td><B24Link @click="openListItem = true">Future Enterprises</B24Link></td>
                <td><B24Chip standalone color="air-primary-warning" text="Contract Signed" size="lg" :trailing-icon="TrendUpIcon" /></td>
                <td>200,000</td>
              </tr>
              <!-- row 4 -->
              <tr>
                <th>4</th>
                <td><B24Link @click="openListItem = true">Bright Ideas Co.</B24Link></td>
                <td>
                  <B24Chip
                    standalone
                    text="Initial Contact"
                    color="air-primary-alert"
                    size="lg"
                    inverted
                    :trailing-icon="TrendDownIcon"
                  />
                </td>
                <td>15,000</td>
              </tr>
              <!-- row 5 -->
              <tr>
                <th>5</th>
                <td><B24Link @click="openListItem = true">NextGen Technologies</B24Link></td>
                <td>
                  <B24Chip
                    standalone
                    text="Important"
                    size="lg"
                    color="air-primary-alert"
                    :b24ui="{ base: 'style-filled-boost' }"
                  />
                </td>
                <td>300,000</td>
              </tr>
            </tbody>
            <tfoot>
              <tr>
                <th colspan="3" class="text-right">
                  Total:
                </th>
                <td>
                  685,000
                </td>
              </tr>
            </tfoot>
          </table>
        </B24TableWrapper>
      </div>
    </template>

    <template #footer>
      <B24Button
        label="Reload"
        color="air-primary"
        loading-auto
        @click="handleAction"
      />
      <B24ModalDialogClose>
        <B24Button label="Cancel" color="air-tertiary" />
      </B24ModalDialogClose>
    </template>
  </B24Slideover>
  <B24Slideover
    v-model:open="openListItem"
    :close="{ label: 'Item' }"
    title="Item"
    description="Some description"
    :use-light-content="false"
    :b24ui="{
      content: 'sm:max-w-[965px] sm:top-[375px] sm:max-h-[calc(100%-375px)]',
      body: 'relative',
      sidebarLayoutRoot: [
        'edge-light',
        'edge-light:[--air-theme-bg-color:#eef2f4]',
        'edge-light:[--air-theme-bg-size:auto]',
        'edge-light:[--air-theme-bg-repeat:no-repeat]',
        'edge-light:[--air-theme-bg-position:0_0]',
        'edge-light:[--air-theme-bg-attachment:local]',
        'edge-light:[--air-theme-bg-image:url(/bg/slider-ring-blurred.webp)]',
        'edge-light:[--air-theme-bg-image-blurred:url(/bg/slider-ring-blurred.webp)]'
      ].join(' ')
    }"
  >
    <template #header>
      <div
        class="w-full pt-(--ui-space-inset-md2) pb-[calc(var(--ui-space-inset-md2)+10px)] px-(--ui-space-inset-lg) rounded-(--ui-border-radius-3xl) bg-(--ui-color-background-primary)/80 flex flex-row items-center justify-between gap-[20px]"
      >
        <B24Avatar
          :icon="BusinesProcessStagesIcon"
          alt="Workflows"
          size="2xl"
          :b24ui="{
            root: 'bg-(--ui-color-primary)',
            icon: 'size-[48px] text-(--ui-color-palette-white-base)'
          }"
        />
        <div class="flex-1">
          <ProseH1 class="text-(--ui-color-text-primary) leading-[29px] font-(--ui-font-weight-light)">
            Workflows
          </ProseH1>
          <ProseP small accent="less">
            Automate your workflows, control every stage and manage workflows from your mobile.
          </ProseP>
        </div>
      </div>
    </template>
    <template #body>
      <Placeholder class="w-full h-[300px]" />
    </template>
    <template #footer>
      <B24ModalDialogClose>
        <B24Button label="Continue" color="air-primary" />
      </B24ModalDialogClose>
      <B24ModalDialogClose>
        <B24Button label="Back" color="air-tertiary" />
      </B24ModalDialogClose>
    </template>
  </B24Slideover>
</template>
Many examples can be found on the playground and also seen in the demo version.

API

Props

Prop Default Type
as'div'any

The element or component this component should render as.

useLightContenttrueboolean

The content is placed on a light background.

isInnerfalseboolean

Set inner mode. Use in slider, modal and etc

offContentScrollbarfalseboolean

Off scrollbar control of the content area in inner mode.

iduseId() string

The id of the SidebarLayout.

b24ui { root?: ClassNameValue; sidebar?: ClassNameValue; sidebarSlideoverContainer?: ClassNameValue; sidebarSlideover?: ClassNameValue; sidebarSlideoverBtnClose?: ClassNameValue; contentWrapper?: ClassNameValue; header?: ClassNameValue; headerMenuIcon?: ClassNameValue; headerWrapper?: ClassNameValue; pageWrapper?: ClassNameValue; container?: ClassNameValue; containerWrapper?: ClassNameValue; pageTopWrapper?: ClassNameValue; pageActionsWrapper?: ClassNameValue; containerWrapperInner?: ClassNameValue; pageRightWrapper?: ClassNameValue; pageBottomWrapper?: ClassNameValue; loadingWrapper?: ClassNameValue; loadingIcon?: ClassNameValue; }

Slots

Slot Type
sidebar{ handleClick: () => void; isLoading: boolean; b24ui: object; }

Left sidebar.

navbar{ handleClick: () => void; isLoading: boolean; b24ui: object; }

Top menu.

content-top{ isLoading: boolean; b24ui: object; }

Content above the page. Used for title, filter, etc.

content-actions{ isLoading: boolean; b24ui: object; }

Content above the page. Use for show actions.

default{ isLoading: boolean; b24ui: object; }

The page content.

content-right{ isLoading: boolean; b24ui: object; }

Right sidebar.

content-bottom{ isLoading: boolean; b24ui: object; }

Content below the page.

loading{ isLoading: boolean; b24ui: object; }

Loading state.

Theme

app.config.ts
export default defineAppConfig({
  b24ui: {
    sidebarLayout: {
      slots: {
        root: 'sidebar-layout text-(--b24ui-typography-label-color) w-full flex',
        sidebar: 'air-sidebar before:absolute before:inset-0 before:z-[-1] before:bg-(--leftmenu-bg-expanded) w-[240px] pe-[3px] rtl:me-[14px] inset-y-0 left-0 max-lg:hidden',
        sidebarSlideoverContainer: 'w-full sm:max-w-80',
        sidebarSlideover: 'h-full overflow-hidden flex flex-col text-(--b24ui-typography-label-color) bg-(--ui-color-base-white-fixed) dark:bg-(--ui-color-bg-content-primary) edge-dark:bg-[#21334cf0] ring-1 ring-(--ui-color-divider-vibrant-less) shadow-xs rounded-none',
        sidebarSlideoverBtnClose: '-mb-3 px-4 pt-3',
        contentWrapper: 'flex-1 flex flex-col',
        header: 'air-header px-(--content-area-shift) min-h-(--topbar-height) flex items-center gap-x-1',
        headerMenuIcon: 'lg:hidden',
        headerWrapper: 'min-w-0 flex-1 h-full',
        pageWrapper: 'flex flex-col lg:grid lg:grid-cols-12 lg:gap-[22px]',
        container: 'lg:col-span-12 lg:min-w-0 flex-1 flex flex-col lg:gap-[22px]',
        containerWrapper: 'grow group/layout-content',
        pageTopWrapper: 'text-(--ui-color-base-1) flex items-center gap-[12px]',
        pageActionsWrapper: 'flex flex-col md:flex-row items-start md:items-center justify-start gap-[12px]',
        containerWrapperInner: 'size-full',
        pageRightWrapper: '',
        pageBottomWrapper: '',
        loadingWrapper: 'cursor-wait w-full h-dvh flex flex-row flex-nowrap items-center justify-center',
        loadingIcon: 'text-(--ui-color-design-plain-content-icon-secondary) size-[110px] animate-spin-slow'
      },
      variants: {
        inner: {
          true: {
            root: '--inner light relative isolate h-full overflow-hidden',
            sidebar: 'relative z-[0]',
            header: 'relative',
            container: 'mt-0',
            containerWrapper: '',
            pageBottomWrapper: 'flex-0'
          },
          false: {
            root: '--app max-lg:flex-col',
            sidebar: 'h-screen lg:sticky',
            header: 'relative',
            container: 'relative',
            containerWrapper: ''
          }
        },
        offContentScrollbar: {
          false: '',
          true: ''
        },
        useSidebar: {
          true: '',
          false: ''
        },
        useLightContent: {
          true: {
            containerWrapper: 'light text-(--ui-color-text-primary) bg-(--ui-color-bg-content-primary)',
            loadingIcon: 'edge-dark:text-(--ui-color-gray-70)'
          },
          false: {
            pageWrapper: 'px-(--content-area-shift)',
            container: ''
          }
        },
        loading: {
          true: ''
        },
        useNavbar: {
          true: '',
          false: ''
        },
        useRightBar: {
          true: {
            pageWrapper: '',
            container: 'lg:col-span-10',
            pageRightWrapper: 'lg:col-span-2 order-first lg:order-last'
          },
          false: {
            container: ''
          }
        }
      },
      compoundVariants: [
        {
          inner: true,
          useLightContent: true,
          class: {
            container: '',
            pageTopWrapper: 'px-0 lg:px-0',
            pageActionsWrapper: 'px-0 lg:px-0',
            containerWrapper: 'p-[20px] rounded-(--ui-border-radius-md)'
          }
        },
        {
          inner: false,
          useLightContent: true,
          class: {
            container: '',
            containerWrapper: 'p-6 lg:px-[22px] lg:py-[15px] lg:rounded-(--ui-border-radius-md)'
          }
        },
        {
          inner: true,
          offContentScrollbar: false,
          class: {}
        },
        {
          inner: true,
          useSidebar: [
            true,
            false
          ],
          class: {
            pageWrapper: 'pb-[20px] lg:pt-0 lg:px-[20px] lg:ps-[20px] lg:pe-[20px]'
          }
        },
        {
          inner: false,
          useSidebar: true,
          class: {
            header: 'ps-[calc(var(--content-area-shift)-10px)] pe-[calc(var(--content-area-shift))] lg:px-(--content-area-shift)',
            pageWrapper: 'lg:px-(--content-area-shift)',
            container: '',
            contentWrapper: ''
          }
        },
        {
          inner: false,
          useSidebar: false,
          class: {
            pageWrapper: 'px-(--content-area-shift)',
            container: '',
            contentWrapper: 'lg:pl-0'
          }
        },
        {
          inner: true,
          useNavbar: [
            true,
            false
          ],
          class: {
            container: 'h-full'
          }
        },
        {
          inner: false,
          useNavbar: true,
          class: {
            container: 'h-auto'
          }
        },
        {
          inner: false,
          useNavbar: false,
          class: {
            container: 'h-full'
          }
        }
      ],
      defaultVariants: {
        inner: false,
        noContentScrollbar: false,
        useLightContent: true
      }
    }
  }
})
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({
      b24ui: {
        sidebarLayout: {
          slots: {
            root: 'sidebar-layout text-(--b24ui-typography-label-color) w-full flex',
            sidebar: 'air-sidebar before:absolute before:inset-0 before:z-[-1] before:bg-(--leftmenu-bg-expanded) w-[240px] pe-[3px] rtl:me-[14px] inset-y-0 left-0 max-lg:hidden',
            sidebarSlideoverContainer: 'w-full sm:max-w-80',
            sidebarSlideover: 'h-full overflow-hidden flex flex-col text-(--b24ui-typography-label-color) bg-(--ui-color-base-white-fixed) dark:bg-(--ui-color-bg-content-primary) edge-dark:bg-[#21334cf0] ring-1 ring-(--ui-color-divider-vibrant-less) shadow-xs rounded-none',
            sidebarSlideoverBtnClose: '-mb-3 px-4 pt-3',
            contentWrapper: 'flex-1 flex flex-col',
            header: 'air-header px-(--content-area-shift) min-h-(--topbar-height) flex items-center gap-x-1',
            headerMenuIcon: 'lg:hidden',
            headerWrapper: 'min-w-0 flex-1 h-full',
            pageWrapper: 'flex flex-col lg:grid lg:grid-cols-12 lg:gap-[22px]',
            container: 'lg:col-span-12 lg:min-w-0 flex-1 flex flex-col lg:gap-[22px]',
            containerWrapper: 'grow group/layout-content',
            pageTopWrapper: 'text-(--ui-color-base-1) flex items-center gap-[12px]',
            pageActionsWrapper: 'flex flex-col md:flex-row items-start md:items-center justify-start gap-[12px]',
            containerWrapperInner: 'size-full',
            pageRightWrapper: '',
            pageBottomWrapper: '',
            loadingWrapper: 'cursor-wait w-full h-dvh flex flex-row flex-nowrap items-center justify-center',
            loadingIcon: 'text-(--ui-color-design-plain-content-icon-secondary) size-[110px] animate-spin-slow'
          },
          variants: {
            inner: {
              true: {
                root: '--inner light relative isolate h-full overflow-hidden',
                sidebar: 'relative z-[0]',
                header: 'relative',
                container: 'mt-0',
                containerWrapper: '',
                pageBottomWrapper: 'flex-0'
              },
              false: {
                root: '--app max-lg:flex-col',
                sidebar: 'h-screen lg:sticky',
                header: 'relative',
                container: 'relative',
                containerWrapper: ''
              }
            },
            offContentScrollbar: {
              false: '',
              true: ''
            },
            useSidebar: {
              true: '',
              false: ''
            },
            useLightContent: {
              true: {
                containerWrapper: 'light text-(--ui-color-text-primary) bg-(--ui-color-bg-content-primary)',
                loadingIcon: 'edge-dark:text-(--ui-color-gray-70)'
              },
              false: {
                pageWrapper: 'px-(--content-area-shift)',
                container: ''
              }
            },
            loading: {
              true: ''
            },
            useNavbar: {
              true: '',
              false: ''
            },
            useRightBar: {
              true: {
                pageWrapper: '',
                container: 'lg:col-span-10',
                pageRightWrapper: 'lg:col-span-2 order-first lg:order-last'
              },
              false: {
                container: ''
              }
            }
          },
          compoundVariants: [
            {
              inner: true,
              useLightContent: true,
              class: {
                container: '',
                pageTopWrapper: 'px-0 lg:px-0',
                pageActionsWrapper: 'px-0 lg:px-0',
                containerWrapper: 'p-[20px] rounded-(--ui-border-radius-md)'
              }
            },
            {
              inner: false,
              useLightContent: true,
              class: {
                container: '',
                containerWrapper: 'p-6 lg:px-[22px] lg:py-[15px] lg:rounded-(--ui-border-radius-md)'
              }
            },
            {
              inner: true,
              offContentScrollbar: false,
              class: {}
            },
            {
              inner: true,
              useSidebar: [
                true,
                false
              ],
              class: {
                pageWrapper: 'pb-[20px] lg:pt-0 lg:px-[20px] lg:ps-[20px] lg:pe-[20px]'
              }
            },
            {
              inner: false,
              useSidebar: true,
              class: {
                header: 'ps-[calc(var(--content-area-shift)-10px)] pe-[calc(var(--content-area-shift))] lg:px-(--content-area-shift)',
                pageWrapper: 'lg:px-(--content-area-shift)',
                container: '',
                contentWrapper: ''
              }
            },
            {
              inner: false,
              useSidebar: false,
              class: {
                pageWrapper: 'px-(--content-area-shift)',
                container: '',
                contentWrapper: 'lg:pl-0'
              }
            },
            {
              inner: true,
              useNavbar: [
                true,
                false
              ],
              class: {
                container: 'h-full'
              }
            },
            {
              inner: false,
              useNavbar: true,
              class: {
                container: 'h-auto'
              }
            },
            {
              inner: false,
              useNavbar: false,
              class: {
                container: 'h-full'
              }
            }
          ],
          defaultVariants: {
            inner: false,
            noContentScrollbar: false,
            useLightContent: true
          }
        }
      }
    })
  ]
})

Error

A pre-built error component with NuxtError support.

Advice

A couple of lines of text and an avatar

On this page

  • Usage
    • Layout
    • Inner
    • Slideover
  • API
    • Props
    • Slots
  • Theme
Releases
Published under MIT License.

Copyright © 2024-present Bitrix24