v2.5.3

Slideover

A dialog that slides in from any side of the screen.

Usage

Use a Button or any other component in the default slot of the Slideover.

Then, use the #content slot to add the content displayed when the Slideover is open.

<template>
  <B24Slideover
    :b24ui="{
      content: 'sm:top-[300px] sm:max-h-[calc(100%-300px)]'
    }"
  >
    <B24Button label="Open" />

    <template #content>
      <Placeholder class="h-full m-4" />
    </template>
  </B24Slideover>
</template>

You can also use the #header, #body and #footer slots to customize the Slideover's content.

Title

Use the title prop to set the title of the Slideover's header.

<template>
  <B24Slideover title="Slideover with title">
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>
  </B24Slideover>
</template>

Description

Use the description prop to set the description of the Slideover's header.

<template>
  <B24Slideover
    title="Slideover with description"
    description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
  >
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>
  </B24Slideover>
</template>

Close

Use the close prop to customize or hide the close button (with false value) displayed in the Slideover's header.

You can pass any property from the Button component to customize it.

<template>
  <B24Slideover
    title="Slideover with close button"
    :close="{
      color: 'air-secondary-accent-2'
    }"
  >
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>
  </B24Slideover>
</template>
The close button is not displayed if the #content slot is used as it's a part of the header.

Close Icon

Use the close-icon prop to customize the close button Icon.

<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
</script>

<template>
  <B24Slideover title="Slideover with close button" :close-icon="RocketIcon">
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>
  </B24Slideover>
</template>

Side

Use the side prop to set the side of the screen where the Slideover will slide in from. Defaults to bottom.

<template>
  <B24Slideover side="bottom" title="Slideover with side">
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full min-h-48" />
    </template>
  </B24Slideover>
</template>

Inset

Use the inset prop to inset the Slideover from the edges.

<template>
  <B24Slideover side="right" inset title="Slideover with inset">
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="min-w-96 min-h-96 size-full" />
    </template>
  </B24Slideover>
</template>

Transition

Use the transition prop to control whether the Slideover is animated or not. Defaults to true.

<template>
  <B24Slideover :transition="false" title="Slideover without transition">
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>
  </B24Slideover>
</template>

Overlay

Use the overlay prop to control whether the Slideover has an overlay or not. Defaults to true.

<template>
  <B24Slideover :overlay="false" title="Slideover without overlay">
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>
  </B24Slideover>
</template>

Overlay blur

If you want to disable background blur, you should use the overlayBlur prop.

The overlayBlur prop has 3 options:

  • auto: when the user has not requested reduced motion
  • on: always use blur
  • off: (default) do not use blur
<template>
  <B24Slideover overlay-blur="auto" title="Overlay blur">
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>
  </B24Slideover>
</template>

Use the modal prop to control whether the Slideover blocks interaction with outside content. Defaults to true.

When modal is set to false, the overlay is automatically disabled and outside content becomes interactive.
<template>
  <B24Slideover :modal="false" title="Slideover interactive">
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>
  </B24Slideover>
</template>

Dismissible

Use the dismissible prop to control whether the Slideover is dismissible when clicking outside of it or pressing escape. Defaults to true.

A close:prevent event will be emitted when the user tries to close it.
You can combine modal: false with dismissible: false to make the Slideover's background interactive without closing it.
<template>
  <B24Slideover :dismissible="false" title="Slideover non-dismissible">
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>
  </B24Slideover>
</template>

Examples

Control open state

You can control the open state by using the default-open prop or the v-model:open directive.

<script setup lang="ts">
const open = ref(false)

defineShortcuts({
  o: () => open.value = !open.value
})
</script>

<template>
  <B24Slideover v-model:open="open" :b24ui="{ content: 'sm:top-[300px] sm:max-h-[calc(100%-300px)]' }">
    <B24Button label="Open" />

    <template #content>
      <Placeholder class="h-full m-4" />
    </template>
  </B24Slideover>
</template>
In this example, leveraging defineShortcuts, you can toggle the Slideover by pressing O.
This allows you to move the trigger outside of the Slideover or remove it entirely.

Programmatic usage

You can use the useOverlay composable to open a Slideover programmatically.

Make sure to wrap your app with the App component which uses the OverlayProvider component.

First, create a slideover component that will be opened programmatically:

SlideoverExample.vue
<script setup lang="ts">
defineProps<{
  count: number
}>()

const emit = defineEmits<{ close: [boolean] }>()
</script>

<template>
  <B24Slideover
    :close="{ onClick: () => emit('close', false) }"
    :description="`This slideover was opened programmatically ${count} times`"
  >
    <template #body>
      <Placeholder class="h-full" />
    </template>

    <template #footer>
      <B24Button size="lg" color="air-primary" label="Save" @click="emit('close', true)" />
      <B24Button
        size="sm"
        color="air-tertiary"
        label="Cancel"
        :normal-case="false"
        @click="emit('close', false)"
      />
    </template>
  </B24Slideover>
</template>
We are emitting a close event when the slideover is closed or dismissed here. You can emit any data through the close event, however, the event must be emitted in order to capture the return value.

Then, use it in your app:

<script setup lang="ts">
import { LazySlideoverExample } from '#components'

const count = ref(0)

const toast = useToast()
const overlay = useOverlay()

const slideover = overlay.create(LazySlideoverExample)

async function open() {
  const instance = slideover.open({
    count: count.value
  })

  const shouldIncrement = await instance.result

  if (shouldIncrement) {
    count.value++

    toast.add({
      title: `Success: ${shouldIncrement}`,
      color: 'air-primary-success',
      id: 'slideover-success'
    })

    // Update the count
    slideover.patch({
      count: count.value
    })
    return
  }

  toast.add({
    title: `Dismissed: ${shouldIncrement}`,
    color: 'air-primary-alert',
    id: 'slideover-dismiss'
  })
}
</script>

<template>
  <B24Button label="Open" @click="open" />
</template>
You can close the slideover within the slideover component by emitting emit('close').

Nested slideovers

You can nest slideovers within each other.

<script setup lang="ts">
const first = ref(false)
const second = ref(false)
</script>

<template>
  <B24Slideover v-model:open="first" title="First slideover">
    <B24Button variant="subtle" label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>

    <template #footer>
      <B24Slideover v-model:open="second" title="Second slideover">
        <B24Button size="lg" label="Open second" color="air-primary" />

        <template #body>
          <Placeholder class="h-full" />
        </template>

        <template #footer>
          <B24Button size="sm" color="air-tertiary" label="Cancel" :normal-case="false" @click="second = false" />
        </template>
      </B24Slideover>

      <B24Button size="sm" color="air-tertiary" label="Cancel" :normal-case="false" @click="first = false" />
    </template>
  </B24Slideover>
</template>

Use the #footer slot to add content after the Slideover's body.

<script setup lang="ts">
const open = ref(false)
</script>

<template>
  <B24Slideover
    v-model:open="open"
    title="Slideover with footer"
    description="This is useful when you want a form in a Slideover."
    :b24ui="{ footer: 'justify-between' }"
  >
    <B24Button label="Open" />

    <template #body>
      <Placeholder class="h-full" />
    </template>

    <template #footer="{ close }">
      <div class="w-1/5 flex items-center justify-start" />
      <div class="w-full flex flex-row items-center justify-center gap-2.5">
        <B24ModalDialogClose>
          <B24Button size="lg" color="air-primary" label="Save" />
        </B24ModalDialogClose>
        <B24Button size="sm" color="air-tertiary" label="Cancel" :normal-case="false" @click="close" />
      </div>
      <div class="w-1/5 flex items-center justify-end">
        <B24Button label="Full version" size="sm" color="air-tertiary-no-accent" />
      </div>
    </template>
  </B24Slideover>
</template>

Simple list of elements

<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)]',
        'air-custom-bg',
        '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)]',
        'dark:before:absolute',
        'dark:before:inset-0 dark:before:bg-black/50'
      ].join(' '),
      body: 'scrollbar-thin pt-0'
    }"
  >
    <B24Button label="Some list" color="air-boost" />
    <template #body>
      <B24Card class="base-mode" :b24ui="{ body: '!px-0 !py-0' }">
        <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>
              <!-- row 6 -->
              <tr>
                <th>6</th>
                <td>
                  <B24Link @click="openListItem = true">
                    Apex Dynamics
                  </B24Link>
                </td>
                <td><B24Badge label="Discovery Call" use-link use-close /></td>
                <td>35,000</td>
              </tr>
              <!-- row 7 -->
              <tr>
                <th>7</th>
                <td>
                  <B24Link @click="openListItem = true">
                    Vertex Systems
                  </B24Link>
                </td>
                <td><B24Badge label="Proposal Sent" use-link inverted use-close /></td>
                <td>82,000</td>
              </tr>
              <!-- row 8 -->
              <tr>
                <th>8</th>
                <td>
                  <B24Link @click="openListItem = true">
                    NovaSphere LLC
                  </B24Link>
                </td>
                <td><B24Chip standalone color="air-primary-success" text="Closed Won" size="lg" :trailing-icon="TrendUpIcon" /></td>
                <td>450,000</td>
              </tr>
              <!-- row 9 -->
              <tr>
                <th>9</th>
                <td>
                  <B24Link @click="openListItem = true">
                    Stellar Innovations
                  </B24Link>
                </td>
                <td>
                  <B24Chip
                    standalone
                    text="Contract Review"
                    color="air-primary-warning"
                    size="lg"
                    inverted
                    :trailing-icon="TrendUpIcon"
                  />
                </td>
                <td>175,000</td>
              </tr>
              <!-- row 10 -->
              <tr>
                <th>10</th>
                <td>
                  <B24Link @click="openListItem = true">
                    Crestline Partners
                  </B24Link>
                </td>
                <td><B24Badge label="Negotiation" use-link use-close /></td>
                <td>95,000</td>
              </tr>
              <!-- row 11 -->
              <tr>
                <th>11</th>
                <td>
                  <B24Link @click="openListItem = true">
                    OmniCore Solutions
                  </B24Link>
                </td>
                <td>
                  <B24Chip
                    standalone
                    text="Urgent"
                    size="lg"
                    color="air-primary-alert"
                    :b24ui="{ base: 'style-filled-boost' }"
                  />
                </td>
                <td>60,000</td>
              </tr>
              <!-- row 12 -->
              <tr>
                <th>12</th>
                <td>
                  <B24Link @click="openListItem = true">
                    BlueWave Technologies
                  </B24Link>
                </td>
                <td><B24Badge label="Proposal Sent" use-link inverted use-close /></td>
                <td>110,000</td>
              </tr>
              <!-- row 13 -->
              <tr>
                <th>13</th>
                <td>
                  <B24Link @click="openListItem = true">
                    Aspire Group
                  </B24Link>
                </td>
                <td><B24Chip standalone color="air-primary-success" text="Closed Won" size="lg" :trailing-icon="TrendUpIcon" /></td>
                <td>525,000</td>
              </tr>
              <!-- row 14 -->
              <tr>
                <th>14</th>
                <td>
                  <B24Link @click="openListItem = true">
                    Catalyst Partners
                  </B24Link>
                </td>
                <td>
                  <B24Chip
                    standalone
                    text="Initial Contact"
                    color="air-primary-alert"
                    size="lg"
                    inverted
                    :trailing-icon="TrendDownIcon"
                  />
                </td>
                <td>28,000</td>
              </tr>
              <!-- row 15 -->
              <tr>
                <th>15</th>
                <td>
                  <B24Link @click="openListItem = true">
                    Zenith Technologies
                  </B24Link>
                </td>
                <td><B24Badge label="Discovery Call" use-link use-close /></td>
                <td>42,000</td>
              </tr>
            </tbody>
            <tfoot>
              <tr>
                <th colspan="3" class="text-right">
                  Total:
                </th>
                <td>
                  2,387,000
                </td>
              </tr>
            </tfoot>
          </table>
        </B24TableWrapper>
      </B24Card>
    </template>

    <template #footer>
      <B24Button
        size="lg"
        color="air-primary"
        label="Reload"
        loading-auto
        @click="handleAction"
      />
      <B24ModalDialogClose>
        <B24Button
          size="sm"
          color="air-tertiary"
          label="Cancel"
          :normal-case="false"
        />
      </B24ModalDialogClose>
    </template>
  </B24Slideover>
  <B24Slideover
    v-model:open="openListItem"
    :close="{ label: 'Item' }"
    title="Item"
    description="Some description"
    :b24ui="{ content: 'sm:max-w-[965px] sm:top-[375px] sm:max-h-[calc(100%-375px)]' }"
  >
    <template #header>
      <B24Card class="base-mode" :b24ui="{ root: 'w-full', body: '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="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>
      </B24Card>
    </template>
    <template #body>
      <Placeholder class="size-full" />
    </template>
    <template #footer>
      <B24ModalDialogClose>
        <B24Button size="lg" color="air-primary" label="Continue" />
      </B24ModalDialogClose>
      <B24ModalDialogClose>
        <B24Button size="sm" color="air-tertiary" label="Cancel" :normal-case="false" />
      </B24ModalDialogClose>
    </template>
  </B24Slideover>
</template>
Many examples can be found on the playground and also seen in the demo version.

API

Props

Prop Default Type
title string
description string
content DialogContentProps & Partial<EmitsToProps<DialogContentImplEmits>>

The content of the slideover.

overlaytrueboolean

Render an overlay behind the slideover.

overlayBlur'off' "off" | "auto" | "on"

Render an overlay blur behind the slideover. auto use motion-safe.

transitiontrueboolean

Animate the slideover when opening or closing.

side'bottom' "bottom" | "top" | "right" | "left"

The side of the slideover.

insetfalseboolean

Whether to inset the slideover from the edges.

portaltrue string | false | true | HTMLElement

Render the slideover in a portal.

closetrueboolean | Omit<ButtonProps, LinkPropsKeys>

Display a close button to dismiss the slideover. { color: 'air-primary' } for left, right, bottom{ color: 'air-tertiary' } for top

closeIconicons.closeIconComponent

The icon displayed in the close button.

dismissibletrueboolean

When false, the slideover will not close when clicking outside or pressing escape.

openboolean

The controlled open state of the dialog. Can be binded as v-model:open.

defaultOpenboolean

The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.

modaltrueboolean

The modality of the dialog When set to true,
interaction with outside elements will be disabled and only dialog content will be visible to screen readers.

b24ui { overlay?: ClassNameValue; content?: ClassNameValue; header?: ClassNameValue; wrapper?: ClassNameValue; body?: ClassNameValue; footer?: ClassNameValue; title?: ClassNameValue; description?: ClassNameValue; close?: ClassNameValue; safeList?: ClassNameValue; }

Slots

Slot Type
default{ open: boolean; }
content{ close: () => void; }
header{ close: () => void; }
title{}
description{}
actions{}
close{ b24ui: object; }
body{ close: () => void; }
footer{ close: () => void; }

Emits

Event Type
after:leave[]
after:enter[]
close:prevent[]
update:open[value: boolean]

Theme

app.config.ts
export default defineAppConfig({
  b24ui: {
    slideover: {
      slots: {
        overlay: 'fixed inset-0 bg-linear-to-b from-[#00204e]/52 to-[#00204e]',
        content: 'base-mode fixed bg-(--ui-color-gray-05) dark:bg-(--ui-color-base-black-fixed) sm:shadow-lg flex flex-col focus:outline-none h-full',
        header: 'py-[20px] px-[20px] flex items-center gap-x-[12px] gap-y-1.5 overflow-hidden',
        wrapper: 'min-h-[30px]',
        body: 'size-full flex-1 overflow-y-auto pb-2.5 px-[20px]',
        footer: 'absolute inset-x-0 bottom-0 base-mode bg-(--ui-color-bg-content-primary) flex items-center justify-center gap-2.5 border-t border-t-1 border-t-(--ui-color-divider-less) shadow-top-md py-[13px] px-[13px]',
        title: 'font-[family-name:var(--ui-font-family-primary)] text-(--b24ui-typography-label-color) font-(--ui-font-weight-semi-bold) mb-0 text-(length:--ui-font-size-4xl)/[calc(var(--ui-font-size-4xl)+2px)]',
        description: 'mt-1 text-(--b24ui-typography-description-color) text-(length:--ui-font-size-sm)',
        close: 'absolute',
        safeList: 'group-hover:rounded-full group-hover:border-1 group-hover:border-current'
      },
      variants: {
        useFooter: {
          true: {
            body: 'mb-[64px]'
          }
        },
        overlayBlur: {
          auto: {
            overlay: 'motion-safe:backdrop-blur-sm'
          },
          on: {
            overlay: 'backdrop-blur-sm'
          },
          off: {
            overlay: ''
          }
        },
        side: {
          top: {
            content: ''
          },
          right: {
            content: ''
          },
          bottom: {
            content: ''
          },
          left: {
            content: ''
          }
        },
        inset: {
          true: {
            content: 'rounded-4.5'
          }
        },
        transition: {
          true: {
            overlay: 'motion-safe:data-[state=open]:animate-[fade-in_200ms_ease-out] motion-safe:data-[state=closed]:animate-[fade-out_200ms_ease-in]'
          }
        }
      },
      compoundVariants: [
        {
          side: 'top',
          inset: true,
          class: {
            content: 'max-h-[calc(100%-2rem)] inset-x-4 top-4'
          }
        },
        {
          side: 'top',
          inset: true,
          useFooter: true,
          class: {}
        },
        {
          side: 'top',
          inset: false,
          class: {
            content: 'max-h-full inset-x-0 top-0'
          }
        },
        {
          side: 'right',
          inset: true,
          class: {
            content: 'w-[calc(100%-2rem)] max-h-[calc(100%-2rem)] inset-y-4 right-4 '
          }
        },
        {
          side: 'right',
          inset: true,
          useFooter: true,
          class: {}
        },
        {
          side: 'right',
          inset: false,
          class: {
            content: 'w-[calc(100%-60px)] sm:w-[calc(100%-150px)] inset-y-0 right-0'
          }
        },
        {
          side: 'bottom',
          inset: true,
          class: {
            content: 'max-h-[calc(100%-2rem)] w-[calc(100%-2rem)] end-4 bottom-4'
          }
        },
        {
          side: 'bottom',
          inset: true,
          useFooter: true,
          class: {}
        },
        {
          side: 'bottom',
          inset: false,
          class: {
            content: 'max-h-full sm:max-h-[calc(100%-18px)] right-[5px] top-0 sm:top-[18px] bottom-0 w-[calc(100%-60px-5px)] sm:w-[calc(100%-150px-70px)] sm:rounded-t-[18px]'
          }
        },
        {
          side: 'left',
          inset: true,
          class: {
            content: 'w-[calc(100%-2rem)] max-h-[calc(100%-2rem)] inset-y-4 left-4'
          }
        },
        {
          side: 'left',
          inset: true,
          useFooter: true,
          class: {}
        },
        {
          side: 'left',
          inset: false,
          class: {
            content: 'w-[calc(100%-60px)] sm:w-[calc(100%-150px)] inset-y-0 left-0'
          }
        },
        {
          side: 'bottom',
          inset: false,
          useFooter: true,
          class: {}
        },
        {
          side: [
            'right',
            'bottom'
          ],
          inset: false,
          class: {
            close: 'pl-1.5 pr-[4px] top-[17px] -translate-x-full left-0 rounded-l-full'
          }
        },
        {
          side: 'left',
          inset: false,
          class: {
            close: 'pr-1.5 pl-[4px] top-[17px] translate-x-full right-0 rounded-r-full [&>div]:flex-row-reverse'
          }
        },
        {
          inset: true,
          class: {
            close: 'top-4 end-4'
          }
        },
        {
          side: 'top',
          class: {
            close: 'top-4 end-4'
          }
        },
        {
          transition: true,
          side: 'top',
          class: {
            content: 'motion-safe:data-[state=open]:animate-[slide-in-from-top_200ms_ease-in-out] motion-safe:data-[state=closed]:animate-[slide-out-to-top_200ms_ease-in-out]'
          }
        },
        {
          transition: true,
          side: 'right',
          class: {
            content: 'motion-safe:data-[state=open]:animate-[slide-in-from-right_200ms_ease-in-out] motion-safe:data-[state=closed]:animate-[slide-out-to-right_200ms_ease-in-out]'
          }
        },
        {
          transition: true,
          side: 'bottom',
          class: {
            content: 'motion-safe:data-[state=open]:animate-[slide-in-from-bottom_200ms_ease-in-out] motion-safe:data-[state=closed]:animate-[slide-out-to-bottom_200ms_ease-in-out]'
          }
        },
        {
          transition: true,
          side: 'left',
          class: {
            content: 'motion-safe:data-[state=open]:animate-[slide-in-from-left_200ms_ease-in-out] motion-safe:data-[state=closed]:animate-[slide-out-to-left_200ms_ease-in-out]'
          }
        }
      ],
      defaultVariants: {
        side: 'bottom',
        overlayBlur: 'off'
      }
    }
  }
})
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: {
        slideover: {
          slots: {
            overlay: 'fixed inset-0 bg-linear-to-b from-[#00204e]/52 to-[#00204e]',
            content: 'base-mode fixed bg-(--ui-color-gray-05) dark:bg-(--ui-color-base-black-fixed) sm:shadow-lg flex flex-col focus:outline-none h-full',
            header: 'py-[20px] px-[20px] flex items-center gap-x-[12px] gap-y-1.5 overflow-hidden',
            wrapper: 'min-h-[30px]',
            body: 'size-full flex-1 overflow-y-auto pb-2.5 px-[20px]',
            footer: 'absolute inset-x-0 bottom-0 base-mode bg-(--ui-color-bg-content-primary) flex items-center justify-center gap-2.5 border-t border-t-1 border-t-(--ui-color-divider-less) shadow-top-md py-[13px] px-[13px]',
            title: 'font-[family-name:var(--ui-font-family-primary)] text-(--b24ui-typography-label-color) font-(--ui-font-weight-semi-bold) mb-0 text-(length:--ui-font-size-4xl)/[calc(var(--ui-font-size-4xl)+2px)]',
            description: 'mt-1 text-(--b24ui-typography-description-color) text-(length:--ui-font-size-sm)',
            close: 'absolute',
            safeList: 'group-hover:rounded-full group-hover:border-1 group-hover:border-current'
          },
          variants: {
            useFooter: {
              true: {
                body: 'mb-[64px]'
              }
            },
            overlayBlur: {
              auto: {
                overlay: 'motion-safe:backdrop-blur-sm'
              },
              on: {
                overlay: 'backdrop-blur-sm'
              },
              off: {
                overlay: ''
              }
            },
            side: {
              top: {
                content: ''
              },
              right: {
                content: ''
              },
              bottom: {
                content: ''
              },
              left: {
                content: ''
              }
            },
            inset: {
              true: {
                content: 'rounded-4.5'
              }
            },
            transition: {
              true: {
                overlay: 'motion-safe:data-[state=open]:animate-[fade-in_200ms_ease-out] motion-safe:data-[state=closed]:animate-[fade-out_200ms_ease-in]'
              }
            }
          },
          compoundVariants: [
            {
              side: 'top',
              inset: true,
              class: {
                content: 'max-h-[calc(100%-2rem)] inset-x-4 top-4'
              }
            },
            {
              side: 'top',
              inset: true,
              useFooter: true,
              class: {}
            },
            {
              side: 'top',
              inset: false,
              class: {
                content: 'max-h-full inset-x-0 top-0'
              }
            },
            {
              side: 'right',
              inset: true,
              class: {
                content: 'w-[calc(100%-2rem)] max-h-[calc(100%-2rem)] inset-y-4 right-4 '
              }
            },
            {
              side: 'right',
              inset: true,
              useFooter: true,
              class: {}
            },
            {
              side: 'right',
              inset: false,
              class: {
                content: 'w-[calc(100%-60px)] sm:w-[calc(100%-150px)] inset-y-0 right-0'
              }
            },
            {
              side: 'bottom',
              inset: true,
              class: {
                content: 'max-h-[calc(100%-2rem)] w-[calc(100%-2rem)] end-4 bottom-4'
              }
            },
            {
              side: 'bottom',
              inset: true,
              useFooter: true,
              class: {}
            },
            {
              side: 'bottom',
              inset: false,
              class: {
                content: 'max-h-full sm:max-h-[calc(100%-18px)] right-[5px] top-0 sm:top-[18px] bottom-0 w-[calc(100%-60px-5px)] sm:w-[calc(100%-150px-70px)] sm:rounded-t-[18px]'
              }
            },
            {
              side: 'left',
              inset: true,
              class: {
                content: 'w-[calc(100%-2rem)] max-h-[calc(100%-2rem)] inset-y-4 left-4'
              }
            },
            {
              side: 'left',
              inset: true,
              useFooter: true,
              class: {}
            },
            {
              side: 'left',
              inset: false,
              class: {
                content: 'w-[calc(100%-60px)] sm:w-[calc(100%-150px)] inset-y-0 left-0'
              }
            },
            {
              side: 'bottom',
              inset: false,
              useFooter: true,
              class: {}
            },
            {
              side: [
                'right',
                'bottom'
              ],
              inset: false,
              class: {
                close: 'pl-1.5 pr-[4px] top-[17px] -translate-x-full left-0 rounded-l-full'
              }
            },
            {
              side: 'left',
              inset: false,
              class: {
                close: 'pr-1.5 pl-[4px] top-[17px] translate-x-full right-0 rounded-r-full [&>div]:flex-row-reverse'
              }
            },
            {
              inset: true,
              class: {
                close: 'top-4 end-4'
              }
            },
            {
              side: 'top',
              class: {
                close: 'top-4 end-4'
              }
            },
            {
              transition: true,
              side: 'top',
              class: {
                content: 'motion-safe:data-[state=open]:animate-[slide-in-from-top_200ms_ease-in-out] motion-safe:data-[state=closed]:animate-[slide-out-to-top_200ms_ease-in-out]'
              }
            },
            {
              transition: true,
              side: 'right',
              class: {
                content: 'motion-safe:data-[state=open]:animate-[slide-in-from-right_200ms_ease-in-out] motion-safe:data-[state=closed]:animate-[slide-out-to-right_200ms_ease-in-out]'
              }
            },
            {
              transition: true,
              side: 'bottom',
              class: {
                content: 'motion-safe:data-[state=open]:animate-[slide-in-from-bottom_200ms_ease-in-out] motion-safe:data-[state=closed]:animate-[slide-out-to-bottom_200ms_ease-in-out]'
              }
            },
            {
              transition: true,
              side: 'left',
              class: {
                content: 'motion-safe:data-[state=open]:animate-[slide-in-from-left_200ms_ease-in-out] motion-safe:data-[state=closed]:animate-[slide-out-to-left_200ms_ease-in-out]'
              }
            }
          ],
          defaultVariants: {
            side: 'bottom',
            overlayBlur: 'off'
          }
        }
      }
    })
  ]
})