v2.1.8
/
  • 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
  • Content
  • ContentSearch
  • ContentSearchButton
  • ContentSurround
  • ContentToc
  • Color Mode
  • ColorModeAvatar
  • ColorModeButton
  • ColorModeImage
  • ColorModeSelect
  • ColorModeSwitch
  • i18n
  • LocaleSelect
  • b24icons
  • b24jssdk
Use our Nuxt starter
v2.1.8
  • Docs
  • Components
  • Composables
  • Typography

Slideover

A dialog that slides in from any side of the screen.
GitHub
Demo
Nuxt UI
DialogDialog

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.

{
  "wait": "Loading client-side content..."
}

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.

{
  "wait": "Loading client-side content..."
}

Description

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

{
  "wait": "Loading client-side content..."
}

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.

{
  "wait": "Loading client-side content..."
}
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.

{
  "wait": "Loading client-side content..."
}

Side

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

{
  "wait": "Loading client-side content..."
}

Transition

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

{
  "wait": "Loading client-side content..."
}

Overlay

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

{
  "wait": "Loading client-side content..."
}

Overlay blur

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

The overlayBlur prop has 3 options:

  • auto: (default) when the user has not requested reduced motion
  • on: always use blur
  • off: do not use blur
{
  "wait": "Loading client-side content..."
}

Modal

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.
{
  "wait": "Loading client-side content..."
}

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.
{
  "wait": "Loading client-side content..."
}

Examples

Control open state

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

{
  "wait": "Loading client-side content..."
}
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:

{
  "wait": "Loading client-side content..."
}
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:

{
  "wait": "Loading client-side content..."
}
You can close the slideover within the slideover component by emitting emit('close').

Nested slideovers

You can nest slideovers within each other.

{
  "wait": "Loading client-side content..."
}

With footer slot

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

{
  "wait": "Loading client-side content..."
}

Simple list of elements

{
  "wait": "Loading client-side content..."
}
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.

  • disableOutsidePointerEvents?: boolean

    When true, hover/focus/click interactions will be disabled on elements outside the DismissableLayer. Users will need to click twice on outside elements to interact with them: once to close the DismissableLayer, and again to trigger the element.

  • onEscapeKeyDown?: ((event: KeyboardEvent) => void)
  • onPointerDownOutside?: ((event: PointerDownOutsideEvent) => void)
  • onFocusOutside?: ((event: FocusOutsideEvent) => void)
  • onInteractOutside?: ((event: PointerDownOutsideEvent | FocusOutsideEvent) => void)
  • onOpenAutoFocus?: ((event: Event) => void)
  • onCloseAutoFocus?: ((event: Event) => void)
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" | "right" | "left" | "top"

The side of the slideover.

portaltrue string | false | true | HTMLElement

Render the slideover in a portal.

closetrueboolean | Partial<ButtonProps>

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.

useLightContenttrueboolean

The content is placed on a light background.

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; sidebarLayoutRoot?: ClassNameValue; sidebarLayoutHeaderWrapper?: ClassNameValue; sidebarLayoutPageWrapper?: ClassNameValue; sidebarLayoutContainer?: ClassNameValue; sidebarLayoutPageBottomWrapper?: ClassNameValue; sidebarLayoutLoadingWrapper?: ClassNameValue; sidebarLayoutLoadingIcon?: ClassNameValue; header?: ClassNameValue; wrapper?: ClassNameValue; title?: ClassNameValue; description?: ClassNameValue; close?: ClassNameValue; body?: ClassNameValue; footer?: ClassNameValue; safeList?: ClassNameValue; }

Slots

Slot Type
default{ open: boolean; }
content{ close: () => void; }
sidebar{ close: () => void; }
navbar{ 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: 'fixed sm:shadow-lg flex flex-col focus:outline-none h-full',
        sidebarLayoutRoot: 'relative',
        sidebarLayoutHeaderWrapper: 'relative',
        sidebarLayoutPageWrapper: 'min-h-full pb-[calc(53px_+_10px)] px-[20px] ps-[20px] pe-[20px] pb-[20px]',
        sidebarLayoutContainer: 'gap-[22px]',
        sidebarLayoutPageBottomWrapper: 'relative',
        sidebarLayoutLoadingWrapper: '',
        sidebarLayoutLoadingIcon: '',
        header: 'pt-[24px] flex-1 flex items-center gap-x-[12px] gap-y-1.5',
        wrapper: 'min-h-[30px]',
        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',
        body: 'size-full flex-1',
        footer: 'absolute inset-x-0 bottom-0 light bg-(--popup-window-background-color) flex items-center justify-center gap-3 border-t border-t-1 border-t-(--ui-color-divider-less) shadow-top-md py-[9px] px-2 pr-(--scrollbar-width)',
        safeList: 'group-hover:rounded-full group-hover:border-1 group-hover:border-current'
      },
      variants: {
        useFooter: {
          true: {
            sidebarLayoutPageWrapper: 'pb-[calc(53px+20px)]'
          }
        },
        overlayBlur: {
          auto: {
            overlay: 'motion-safe:backdrop-blur-sm'
          },
          on: {
            overlay: 'backdrop-blur-sm'
          },
          off: {
            overlay: ''
          }
        },
        side: {
          right: {
            content: 'right-0 inset-y-0 w-[calc(100%-60px)] sm:w-[calc(100%-150px)] sm:rounded-t-none',
            sidebarLayoutRoot: 'sm:rounded-t-none'
          },
          left: {
            content: 'left-0 inset-y-0 w-[calc(100%-60px)] sm:w-[calc(100%-150px)] sm:rounded-t-none',
            sidebarLayoutRoot: 'sm:rounded-t-none'
          },
          top: {
            content: 'inset-x-0 top-0 max-h-full sm:rounded-t-none',
            sidebarLayoutRoot: 'sm:rounded-t-none'
          },
          bottom: {
            content: 'right-[5px] top-0 sm:top-[18px] bottom-0 w-[calc(100%-60px-5px)] sm:w-[calc(100%-150px-70px)] sm:max-h-[calc(100%-18px)] sm:rounded-t-[18px]',
            sidebarLayoutRoot: 'sm:rounded-t-[18px]'
          }
        },
        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: [
            'right',
            'bottom'
          ],
          class: {
            close: 'pl-1.5 pr-[4px] top-[17px] -translate-x-full left-[1px] rounded-l-full'
          }
        },
        {
          side: 'left',
          class: {
            close: 'pr-1.5 pl-[4px] top-[17px] translate-x-full right-[1px] rounded-r-full [&>div]:flex-row-reverse'
          }
        },
        {
          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: 'fixed sm:shadow-lg flex flex-col focus:outline-none h-full',
            sidebarLayoutRoot: 'relative',
            sidebarLayoutHeaderWrapper: 'relative',
            sidebarLayoutPageWrapper: 'min-h-full pb-[calc(53px_+_10px)] px-[20px] ps-[20px] pe-[20px] pb-[20px]',
            sidebarLayoutContainer: 'gap-[22px]',
            sidebarLayoutPageBottomWrapper: 'relative',
            sidebarLayoutLoadingWrapper: '',
            sidebarLayoutLoadingIcon: '',
            header: 'pt-[24px] flex-1 flex items-center gap-x-[12px] gap-y-1.5',
            wrapper: 'min-h-[30px]',
            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',
            body: 'size-full flex-1',
            footer: 'absolute inset-x-0 bottom-0 light bg-(--popup-window-background-color) flex items-center justify-center gap-3 border-t border-t-1 border-t-(--ui-color-divider-less) shadow-top-md py-[9px] px-2 pr-(--scrollbar-width)',
            safeList: 'group-hover:rounded-full group-hover:border-1 group-hover:border-current'
          },
          variants: {
            useFooter: {
              true: {
                sidebarLayoutPageWrapper: 'pb-[calc(53px+20px)]'
              }
            },
            overlayBlur: {
              auto: {
                overlay: 'motion-safe:backdrop-blur-sm'
              },
              on: {
                overlay: 'backdrop-blur-sm'
              },
              off: {
                overlay: ''
              }
            },
            side: {
              right: {
                content: 'right-0 inset-y-0 w-[calc(100%-60px)] sm:w-[calc(100%-150px)] sm:rounded-t-none',
                sidebarLayoutRoot: 'sm:rounded-t-none'
              },
              left: {
                content: 'left-0 inset-y-0 w-[calc(100%-60px)] sm:w-[calc(100%-150px)] sm:rounded-t-none',
                sidebarLayoutRoot: 'sm:rounded-t-none'
              },
              top: {
                content: 'inset-x-0 top-0 max-h-full sm:rounded-t-none',
                sidebarLayoutRoot: 'sm:rounded-t-none'
              },
              bottom: {
                content: 'right-[5px] top-0 sm:top-[18px] bottom-0 w-[calc(100%-60px-5px)] sm:w-[calc(100%-150px-70px)] sm:max-h-[calc(100%-18px)] sm:rounded-t-[18px]',
                sidebarLayoutRoot: 'sm:rounded-t-[18px]'
              }
            },
            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: [
                'right',
                'bottom'
              ],
              class: {
                close: 'pl-1.5 pr-[4px] top-[17px] -translate-x-full left-[1px] rounded-l-full'
              }
            },
            {
              side: 'left',
              class: {
                close: 'pr-1.5 pl-[4px] top-[17px] translate-x-full right-[1px] rounded-r-full [&>div]:flex-row-reverse'
              }
            },
            {
              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'
          }
        }
      }
    })
  ]
})

Popover

A non-modal popup window for showing messages or gathering user input.

Toast

A short message to offer information or feedback to the user.

On this page

  • Usage
    • Title
    • Description
    • Close
    • Close Icon
    • Side
    • Transition
    • Overlay
    • Overlay blur
    • Modal
    • Dismissible
  • Examples
    • Control open state
    • Programmatic usage
    • Nested slideovers
    • With footer slot
    • Simple list of elements
  • API
    • Props
    • Slots
    • Emits
  • Theme
Releases
Published under MIT License.

Copyright © 2024-present Bitrix24