Skip to content

Sidepanel

The Sidepanel component is a versatile UI element that slides in from the edge of the screen to display supplementary content, forms, or detailed information without disrupting the main interface. It provides a contextual and non-intrusive way to present additional content and actions.

Overview

Sidepanels are ideal for presenting:

  • Contextual details for selected items
  • Forms for creating or editing content
  • Filtering and search interfaces
  • Multi-step workflows
  • Supplementary information that doesn't require a full page

Sidepanel Sample

Basic Usage

The basic implementation of a Sidepanel requires:

  1. A control element (like a button) to trigger the panel
  2. The Sidepanel component with content
  3. State management for opening and closing
vue
<template>
  <!-- Trigger button -->
  <spr-button tone="success" @click="isSidepanelOpen = true"> Open Sidepanel </spr-button>

  <!-- Sidepanel component -->
  <spr-sidepanel :is-open="isSidepanelOpen" @close="isSidepanelOpen = false" header-title="Sidepanel Example">
    <!-- Main content -->
    <div class="spr-p-4">Sidepanel Content</div>

    <!-- Footer actions -->
    <template #footer>
      <div class="spr-flex spr-justify-end spr-gap-2 spr-px-4">
        <spr-button @click="isSidepanelOpen = false">Cancel</spr-button>
        <spr-button tone="success">Submit</spr-button>
      </div>
    </template>
  </spr-sidepanel>
</template>

<script setup>
import { ref } from 'vue';

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

TIP

The Sidepanel includes a built-in close button in the header and can also be closed by clicking outside the panel or pressing the ESC key.

Sidepanel Sizes

The Sidepanel component offers three predefined sizes to accommodate different content needs. Use the size prop to specify the width of the panel.

vue
<template>
  <div class="spr-flex spr-space-x-4">
    <spr-button tone="success" @click="isSmallSidepanelOpen = true"> Small (360px) </spr-button>
    <spr-button tone="success" @click="isMediumSidepanelOpen = true"> Medium (420px) </spr-button>
    <spr-button tone="success" @click="isLargeSidepanelOpen = true"> Large (480px) </spr-button>
  </div>

  <!-- Small Sidepanel -->
  <spr-sidepanel
    size="sm"
    :is-open="isSmallSidepanelOpen"
    @close="isSmallSidepanelOpen = false"
    header-title="Small Sidepanel"
  >
    <div class="spr-p-4">Width: 360px</div>
  </spr-sidepanel>

  <!-- Medium Sidepanel -->
  <spr-sidepanel
    size="md"
    :is-open="isMediumSidepanelOpen"
    @close="isMediumSidepanelOpen = false"
    header-title="Medium Sidepanel"
  >
    <div class="spr-p-4">Width: 420px</div>
  </spr-sidepanel>

  <!-- Large Sidepanel -->
  <spr-sidepanel
    size="lg"
    :is-open="isLargeSidepanelOpen"
    @close="isLargeSidepanelOpen = false"
    header-title="Large Sidepanel"
  >
    <div class="spr-p-4">Width: 480px</div>
  </spr-sidepanel>
</template>

<script setup>
import { ref } from 'vue';

const isSmallSidepanelOpen = ref(false);
const isMediumSidepanelOpen = ref(false);
const isLargeSidepanelOpen = ref(false);
</script>

Responsive Behavior

On small screens (mobile devices), sidepanels automatically adjust to take up most of the screen width while maintaining padding for usability.

Use the footer-no-padding prop to remove the default padding from the footer. This is useful when you need to create custom layouts or when using components that provide their own padding.

vue
<template>
  <spr-button tone="success" @click="isNoPaddingModal = true"> Footer Without Padding </spr-button>

  <spr-sidepanel
    size="sm"
    :is-open="isNoPaddingModal"
    header-title="Custom Footer Example"
    footer-no-padding
    @close="isNoPaddingModal = false"
  >
    <div class="spr-p-4">
      <p>The footer below has no default padding, allowing for custom styling.</p>
    </div>
    <template #footer>
      <div class="spr-flex spr-justify-end spr-gap-2 spr-bg-neutral-50 spr-p-3">
        <spr-button variant="secondary" @click="isNoPaddingModal = false">Cancel</spr-button>
        <spr-button tone="success">Confirm</spr-button>
      </div>
    </template>
  </spr-sidepanel>
</template>

<script setup>
import { ref } from 'vue';

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

Custom Header

You can fully customize the header section using the header slot.

vue
<template>
  <spr-sidepanel :is-open="isOpen" @close="isOpen = false">
    <!-- Custom header -->
    <template #header>
      <div class="spr-flex spr-items-center spr-justify-between spr-bg-neutral-50 spr-p-4">
        <div class="spr-flex spr-items-center spr-gap-2">
          <Icon icon="ph:user-circle" class="spr-text-brand-600 spr-size-6" />
          <h3 class="spr-subheading-md">User Profile</h3>
        </div>
        <Icon icon="ph:x" class="spr-text-color-weak spr-cursor-pointer" @click="isOpen = false" />
      </div>
    </template>

    <!-- Panel content -->
    <div class="spr-p-4">Content goes here</div>
  </spr-sidepanel>
</template>

WARNING

When using a custom header with the header slot, you'll need to implement your own close button functionality.

Advanced Features

Custom Height

You can customize the height of the sidepanel using the height prop. This can be specified as a number (interpreted as pixels) or a string with CSS units.

vue
<template>
  <!-- Fixed height in pixels -->
  <spr-sidepanel :is-open="isOpen" @close="isOpen = false" height="500">
    <!-- Content -->
  </spr-sidepanel>

  <!-- Height with CSS units -->
  <spr-sidepanel :is-open="isOpen" @close="isOpen = false" height="80vh">
    <!-- Content -->
  </spr-sidepanel>
</template>

Backdrop Control

You can control whether the sidepanel displays a backdrop using the has-backdrop prop.

vue
<template>
  <!-- Without backdrop -->
  <spr-sidepanel :is-open="isOpen" @close="isOpen = false" :has-backdrop="false">
    <!-- Content -->
  </spr-sidepanel>
</template>

Close Behavior

Control how the sidepanel can be closed using the close-outside and escape-close props.

vue
<template>
  <!-- Prevent closing when clicking outside -->
  <spr-sidepanel :is-open="isOpen" @close="isOpen = false" :close-outside="false">
    <!-- Content -->
  </spr-sidepanel>

  <!-- Prevent closing with ESC key -->
  <spr-sidepanel :is-open="isOpen" @close="isOpen = false" :escape-close="false">
    <!-- Content -->
  </spr-sidepanel>
</template>

Slots

The Sidepanel component provides three slots for customizing different sections of the panel.

NameDescription
defaultThe main content area of the sidepanel. This is where your primary content should be placed.
headerUsed to replace the default header with custom content. When using this slot, you'll need to implement your own close button.
footerUsed to add a footer section at the bottom of the sidepanel. Typically contains action buttons.

API Reference

Props

NameDescriptionTypeDefault
is-openControls whether the sidepanel is open or closedbooleanfalse
header-titleThe title text displayed in the sidepanel's headerstring'Sidepanel Header'
sizeControls the width of the sidepanel'sm' | 'md' | 'lg''sm'
heightSpecifies the height of the sidepanel. Can be a number (in pixels) or a string with CSS unitsstring | number'calc(100vh - 32px)'
hide-headerWhen true, hides the default header sectionbooleanfalse
positionSpecifies which side the panel appears from'right''right'
has-backdropWhen true, displays a semi-transparent backdrop behind the sidepanelbooleantrue
close-outsideWhen true, allows closing the sidepanel by clicking outside of itbooleantrue
escape-closeWhen true, allows closing the sidepanel by pressing the ESC keybooleantrue
is-stackingEnables stacking behavior for the sidepanel (for nested panels)booleanfalse
footer-no-paddingWhen true, removes the default padding from the footer sectionbooleanfalse

Events

NameDescriptionParameters
closeEmitted when the sidepanel should be closed (from close button, outside click, or ESC key)None
on-closeEmitted after the sidepanel has been closedNone

Products Uses

Sprout HR
Sprout HR
Sprout Ecosystem
Sprout Ecosystem
Sprout Sidekick
Sprout Sidekick