Skip to content
  1. Navigation
  2. Sidebar

Sidebar

Vertical navigation for apps with more sections than a top bar can hold.

import { Avatar } from '@/components/avatar'
import {
  Dropdown,
  DropdownButton,
  DropdownDivider,
  DropdownItem,
  DropdownLabel,
  DropdownMenu,
} from '@/components/dropdown'
import {
  Sidebar,
  SidebarBody,
  SidebarFooter,
  SidebarHeader,
  SidebarHeading,
  SidebarItem,
  SidebarLabel,
  SidebarSection,
  SidebarSpacer,
} from '@/components/sidebar'
import {
  ArrowRightStartOnRectangleIcon,
  Cog6ToothIcon,
  LockClosedIcon,
  PlusIcon,
  UserCircleIcon,
} from '@heroicons/react/16/solid'
import {
  ArrowsRightLeftIcon,
  BookOpenIcon,
  BuildingLibraryIcon,
  ChevronDownIcon,
  ChevronUpIcon,
  CodeBracketIcon,
  CreditCardIcon,
  DocumentTextIcon,
  KeyIcon,
  SignalIcon,
  Squares2X2Icon,
  UsersIcon,
} from '@heroicons/react/20/solid'

export default function Example() {
  return (
    <Sidebar>
      <SidebarHeader>
        <Dropdown>
          <DropdownButton as={SidebarItem}>
            <Avatar initials="NW" className="bg-teal-600 text-white" />
            <SidebarLabel>Northwind</SidebarLabel>
            <ChevronDownIcon />
          </DropdownButton>
          <DropdownMenu className="min-w-64" anchor="bottom start">
            <DropdownItem href="/settings/workspace">
              <Cog6ToothIcon />
              <DropdownLabel>Workspace settings</DropdownLabel>
            </DropdownItem>
            <DropdownDivider />
            <DropdownItem href="/w/northwind">
              <Avatar initials="NW" className="bg-teal-600 text-white" />
              <DropdownLabel>Northwind</DropdownLabel>
            </DropdownItem>
            <DropdownItem href="/w/sahel-logistics">
              <Avatar initials="SL" className="bg-indigo-500 text-white" />
              <DropdownLabel>Sahel Logistics</DropdownLabel>
            </DropdownItem>
            <DropdownDivider />
            <DropdownItem href="/workspaces/new">
              <PlusIcon />
              <DropdownLabel>Create workspace</DropdownLabel>
            </DropdownItem>
          </DropdownMenu>
        </Dropdown>
      </SidebarHeader>
      <SidebarBody>
        <SidebarSection>
          <SidebarItem href="/overview" current>
            <Squares2X2Icon />
            <SidebarLabel>Overview</SidebarLabel>
          </SidebarItem>
          <SidebarItem href="/payments">
            <CreditCardIcon />
            <SidebarLabel>Payments</SidebarLabel>
          </SidebarItem>
          <SidebarItem href="/invoices">
            <DocumentTextIcon />
            <SidebarLabel>Invoices</SidebarLabel>
          </SidebarItem>
          <SidebarItem href="/customers">
            <UsersIcon />
            <SidebarLabel>Customers</SidebarLabel>
          </SidebarItem>
          <SidebarItem href="/payouts">
            <BuildingLibraryIcon />
            <SidebarLabel>Payouts</SidebarLabel>
          </SidebarItem>
        </SidebarSection>
        <SidebarSection>
          <SidebarHeading>Developers</SidebarHeading>
          <SidebarItem href="/developers/api-keys">
            <KeyIcon />
            <SidebarLabel>API keys</SidebarLabel>
          </SidebarItem>
          <SidebarItem href="/developers/webhooks">
            <ArrowsRightLeftIcon />
            <SidebarLabel>Webhooks</SidebarLabel>
          </SidebarItem>
          <SidebarItem href="/developers/logs">
            <CodeBracketIcon />
            <SidebarLabel>Logs</SidebarLabel>
          </SidebarItem>
        </SidebarSection>
        <SidebarSpacer />
        <SidebarSection>
          <SidebarItem href="/docs">
            <BookOpenIcon />
            <SidebarLabel>Documentation</SidebarLabel>
          </SidebarItem>
          <SidebarItem href="/status">
            <SignalIcon />
            <SidebarLabel>System status</SidebarLabel>
          </SidebarItem>
        </SidebarSection>
      </SidebarBody>
      <SidebarFooter>
        <Dropdown>
          <DropdownButton as={SidebarItem}>
            <span className="flex min-w-0 items-center gap-3">
              <Avatar src="/avatars/papac.jpg" className="size-10" square alt="" />
              <span className="min-w-0">
                <span className="block truncate text-sm/5 font-medium text-zinc-950 dark:text-white">Franck Dakia</span>
                <span className="block truncate text-xs/5 font-normal text-zinc-500 dark:text-zinc-400">
                  franck@northwind.io
                </span>
              </span>
            </span>
            <ChevronUpIcon />
          </DropdownButton>
          <DropdownMenu className="min-w-64" anchor="top start">
            <DropdownItem href="/profile">
              <UserCircleIcon />
              <DropdownLabel>Your profile</DropdownLabel>
            </DropdownItem>
            <DropdownItem href="/profile/security">
              <LockClosedIcon />
              <DropdownLabel>Security</DropdownLabel>
            </DropdownItem>
            <DropdownDivider />
            <DropdownItem href="/logout">
              <ArrowRightStartOnRectangleIcon />
              <DropdownLabel>Sign out</DropdownLabel>
            </DropdownItem>
          </DropdownMenu>
        </Dropdown>
      </SidebarFooter>
    </Sidebar>
  )
}
<script setup lang="ts">
import Avatar from '@/components/avatar.vue'
import Dropdown from '@/components/dropdown.vue'
import DropdownButton from '@/components/dropdown-button.vue'
import DropdownDivider from '@/components/dropdown-divider.vue'
import DropdownItem from '@/components/dropdown-item.vue'
import DropdownLabel from '@/components/dropdown-label.vue'
import DropdownMenu from '@/components/dropdown-menu.vue'
import Sidebar from '@/components/sidebar.vue'
import SidebarBody from '@/components/sidebar-body.vue'
import SidebarFooter from '@/components/sidebar-footer.vue'
import SidebarHeader from '@/components/sidebar-header.vue'
import SidebarHeading from '@/components/sidebar-heading.vue'
import SidebarItem from '@/components/sidebar-item.vue'
import SidebarLabel from '@/components/sidebar-label.vue'
import SidebarSection from '@/components/sidebar-section.vue'
import SidebarSpacer from '@/components/sidebar-spacer.vue'
import {
  ArrowRightStartOnRectangleIcon,
  Cog6ToothIcon,
  LockClosedIcon,
  PlusIcon,
  UserCircleIcon,
} from '@heroicons/vue/16/solid'
import {
  ArrowsRightLeftIcon,
  BookOpenIcon,
  BuildingLibraryIcon,
  ChevronDownIcon,
  ChevronUpIcon,
  CodeBracketIcon,
  CreditCardIcon,
  DocumentTextIcon,
  KeyIcon,
  SignalIcon,
  Squares2X2Icon,
  UsersIcon,
} from '@heroicons/vue/20/solid'
</script>

<template>
  <Sidebar>
    <SidebarHeader>
      <Dropdown>
        <DropdownButton :as="SidebarItem">
          <Avatar initials="NW" class="bg-teal-600 text-white" />
          <SidebarLabel>Northwind</SidebarLabel>
          <ChevronDownIcon />
        </DropdownButton>
        <DropdownMenu class="min-w-64" anchor="bottom start">
          <DropdownItem href="/settings/workspace">
            <Cog6ToothIcon />
            <DropdownLabel>Workspace settings</DropdownLabel>
          </DropdownItem>
          <DropdownDivider />
          <DropdownItem href="/w/northwind">
            <Avatar initials="NW" class="bg-teal-600 text-white" />
            <DropdownLabel>Northwind</DropdownLabel>
          </DropdownItem>
          <DropdownItem href="/w/sahel-logistics">
            <Avatar initials="SL" class="bg-indigo-500 text-white" />
            <DropdownLabel>Sahel Logistics</DropdownLabel>
          </DropdownItem>
          <DropdownDivider />
          <DropdownItem href="/workspaces/new">
            <PlusIcon />
            <DropdownLabel>Create workspace</DropdownLabel>
          </DropdownItem>
        </DropdownMenu>
      </Dropdown>
    </SidebarHeader>
    <SidebarBody>
      <SidebarSection>
        <SidebarItem href="/overview" current>
          <Squares2X2Icon />
          <SidebarLabel>Overview</SidebarLabel>
        </SidebarItem>
        <SidebarItem href="/payments">
          <CreditCardIcon />
          <SidebarLabel>Payments</SidebarLabel>
        </SidebarItem>
        <SidebarItem href="/invoices">
          <DocumentTextIcon />
          <SidebarLabel>Invoices</SidebarLabel>
        </SidebarItem>
        <SidebarItem href="/customers">
          <UsersIcon />
          <SidebarLabel>Customers</SidebarLabel>
        </SidebarItem>
        <SidebarItem href="/payouts">
          <BuildingLibraryIcon />
          <SidebarLabel>Payouts</SidebarLabel>
        </SidebarItem>
      </SidebarSection>
      <SidebarSection>
        <SidebarHeading>Developers</SidebarHeading>
        <SidebarItem href="/developers/api-keys">
          <KeyIcon />
          <SidebarLabel>API keys</SidebarLabel>
        </SidebarItem>
        <SidebarItem href="/developers/webhooks">
          <ArrowsRightLeftIcon />
          <SidebarLabel>Webhooks</SidebarLabel>
        </SidebarItem>
        <SidebarItem href="/developers/logs">
          <CodeBracketIcon />
          <SidebarLabel>Logs</SidebarLabel>
        </SidebarItem>
      </SidebarSection>
      <SidebarSpacer />
      <SidebarSection>
        <SidebarItem href="/docs">
          <BookOpenIcon />
          <SidebarLabel>Documentation</SidebarLabel>
        </SidebarItem>
        <SidebarItem href="/status">
          <SignalIcon />
          <SidebarLabel>System status</SidebarLabel>
        </SidebarItem>
      </SidebarSection>
    </SidebarBody>
    <SidebarFooter>
      <Dropdown>
        <DropdownButton :as="SidebarItem">
          <span class="flex min-w-0 items-center gap-3">
            <Avatar src="/avatars/papac.jpg" class="size-10" square alt="" />
            <span class="min-w-0">
              <span class="block truncate text-sm/5 font-medium text-zinc-950 dark:text-white">Franck Dakia</span>
              <span class="block truncate text-xs/5 font-normal text-zinc-500 dark:text-zinc-400">
                franck@northwind.io
              </span>
            </span>
          </span>
          <ChevronUpIcon />
        </DropdownButton>
        <DropdownMenu class="min-w-64" anchor="top start">
          <DropdownItem href="/profile">
            <UserCircleIcon />
            <DropdownLabel>Your profile</DropdownLabel>
          </DropdownItem>
          <DropdownItem href="/profile/security">
            <LockClosedIcon />
            <DropdownLabel>Security</DropdownLabel>
          </DropdownItem>
          <DropdownDivider />
          <DropdownItem href="/logout">
            <ArrowRightStartOnRectangleIcon />
            <DropdownLabel>Sign out</DropdownLabel>
          </DropdownItem>
        </DropdownMenu>
      </Dropdown>
    </SidebarFooter>
  </Sidebar>
</template>

Installation

Copy these files into the folder where you keep your components. They import each other with relative paths, so the folder can live anywhere. The packages they rely on are listed on the Installation page.

'use client'

import * as Headless from '@headlessui/react'
import clsx from 'clsx'
import { LayoutGroup, motion } from 'motion/react'
import React, { forwardRef, useId } from 'react'
import { TouchTarget } from './button'
import { Link } from './link'

type DivProps = React.ComponentPropsWithoutRef<'div'>

const divider = 'border-zinc-950/5 dark:border-white/5'

const headerFooter = clsx('flex flex-col p-4 [&>[data-slot=section]+[data-slot=section]]:mt-2.5', divider)

export function Sidebar({ className, ...props }: React.ComponentPropsWithoutRef<'nav'>) {
  return <nav aria-label="Sidebar" {...props} className={clsx(className, 'flex h-full min-h-0 flex-col')} />
}

export function SidebarHeader({ className, ...props }: DivProps) {
  return <div {...props} className={clsx(className, headerFooter)} />
}

export function SidebarBody({ className, ...props }: DivProps) {
  return (
    <div
      {...props}
      className={clsx(className, 'flex flex-1 flex-col p-4 overflow-y-auto', '[&>[data-slot=section]+[data-slot=section]]:mt-8')}
    />
  )
}

export function SidebarFooter({ className, ...props }: DivProps) {
  return <div {...props} className={clsx(className, headerFooter)} />
}

export function SidebarSection({ className, ...props }: DivProps) {
  let id = useId()

  return (
    <LayoutGroup id={id}>
      <div {...props} data-slot="section" className={clsx(className, 'flex flex-col gap-0.5')} />
    </LayoutGroup>
  )
}

export function SidebarDivider({ className, ...props }: React.ComponentPropsWithoutRef<'hr'>) {
  return <hr {...props} className={clsx(className, 'my-4 border-t lg:-mx-4', divider)} />
}

export function SidebarSpacer({ className, ...props }: DivProps) {
  return <div aria-hidden="true" {...props} className={clsx(className, 'mt-8 flex-1')} />
}

export function SidebarHeading({ className, ...props }: React.ComponentPropsWithoutRef<'h3'>) {
  return <h3 {...props} className={clsx(className, 'px-2 mb-1 text-xs/6 font-medium text-zinc-500 dark:text-zinc-400')} />
}

const item = {
  layout: 'relative flex w-full items-center gap-3 px-2 py-2.5 sm:py-2 rounded-lg',
  text: 'text-left text-base/6 sm:text-sm/5 font-medium',
  background: [
    'not-data-current:data-hover:bg-zinc-950/5 dark:not-data-current:data-hover:bg-white/5',
    'not-data-current:data-active:bg-zinc-950/5 dark:not-data-current:data-active:bg-white/5',
  ],
  avatar: '*:data-[slot=avatar]:size-7 sm:*:data-[slot=avatar]:size-6 *:data-[slot=avatar]:-m-0.5',
}

const itemIcon = {
  size: '*:data-[slot=icon]:shrink-0 *:data-[slot=icon]:size-6 sm:*:data-[slot=icon]:size-5',
  trailing: '*:last:data-[slot=icon]:size-5 sm:*:last:data-[slot=icon]:size-4 *:last:data-[slot=icon]:ml-auto',
  fill: [
    '*:data-[slot=icon]:fill-zinc-500 dark:*:data-[slot=icon]:fill-zinc-400',
    'data-hover:*:data-[slot=icon]:fill-zinc-950 dark:data-hover:*:data-[slot=icon]:fill-white',
    'data-active:*:data-[slot=icon]:fill-zinc-950 dark:data-active:*:data-[slot=icon]:fill-white',
    'data-current:*:data-[slot=icon]:fill-zinc-950 dark:data-current:*:data-[slot=icon]:fill-white',
  ],
}

const itemClasses = clsx(Object.values(item), Object.values(itemIcon))

const strongText = 'text-zinc-950 dark:text-white'

const mutedText = clsx(
  'text-zinc-500 dark:text-zinc-400',
  'data-hover:text-zinc-950 dark:data-hover:text-white data-active:text-zinc-950 dark:data-active:text-white',
  'data-current:text-zinc-950 dark:data-current:text-white'
)

const currentBackground = 'absolute inset-0 rounded-lg bg-zinc-950/5 dark:bg-white/5'

type SidebarItemProps = { current?: boolean; className?: string; children: React.ReactNode } & (
  | ({ href?: never } & Omit<Headless.ButtonProps, 'as' | 'className'>)
  | ({ href: string } & Omit<Headless.ButtonProps<typeof Link>, 'as' | 'className'>)
)

export const SidebarItem = forwardRef(function SidebarItem(
  { current, className, children, ...props }: SidebarItemProps,
  ref: React.ForwardedRef<HTMLAnchorElement | HTMLButtonElement>
) {
  let dataCurrent = current ? 'true' : undefined
  let opensPopup = props['aria-haspopup'] !== undefined || props['aria-expanded'] !== undefined
  let ItemButton = opensPopup ? Headless.Button : Headless.CloseButton

  return (
    <span className={clsx(className, 'relative')}>
      {current && (
        <motion.span layoutId="current-indicator" className={currentBackground} />
      )}
      {typeof props.href === 'string' ? (
        <Headless.CloseButton
          as={Link}
          {...props}
          className={clsx(itemClasses, mutedText)}
          data-current={dataCurrent}
          aria-current={current ? 'page' : undefined}
          ref={ref}
        >
          <TouchTarget>{children}</TouchTarget>
        </Headless.CloseButton>
      ) : (
        <ItemButton
          {...props}
          className={clsx('cursor-default', itemClasses, opensPopup ? strongText : mutedText)}
          data-current={dataCurrent}
          aria-current={current ? 'true' : undefined}
          ref={ref}
        >
          <TouchTarget>{children}</TouchTarget>
        </ItemButton>
      )}
    </span>
  )
})

export function SidebarLabel({ className, ...props }: React.ComponentPropsWithoutRef<'span'>) {
  return <span {...props} className={clsx(className, 'truncate')} />
}

Also copy Button.

<template>
  <nav aria-label="Sidebar" class="flex h-full min-h-0 flex-col">
    <slot />
  </nav>
</template>

Also copy Navbar.

Component API

PropDefaultDescription
Sidebarrenders a <nav> element
aria-labelSidebarName of the navigation landmark, so it stands apart from the navbar's `Main` in a screen reader's landmark list.
SidebarHeaderrenders a <div> element
This component does not expose any component-specific props.
SidebarBodyrenders a <div> element
This component does not expose any component-specific props.
SidebarFooterrenders a <div> element
This component does not expose any component-specific props.
SidebarSectionrenders a <div> element
This component does not expose any component-specific props.
SidebarItemrenders a <button> element
href-Turns the item into a link rendered by your router. Without it, the item is a button.
currentfalseMarks the page the user is on and fills it with a soft background.
disabledfalseBlocks a button item.
SidebarLabelrenders a <span> element
This component does not expose any component-specific props.
SidebarHeadingrenders a <h3> element
This component does not expose any component-specific props.
SidebarDividerrenders a <hr> element
This component does not expose any component-specific props.
SidebarSpacerrenders a <div> element
This component does not expose any component-specific props.
PropDefaultDescription
Sidebarrenders a <nav> element
aria-labelSidebarName of the navigation landmark, so it stands apart from the navbar's `Main` in a screen reader's landmark list.
SidebarHeaderrenders a <div> element
This component does not expose any component-specific props.
SidebarBodyrenders a <div> element
This component does not expose any component-specific props.
SidebarFooterrenders a <div> element
This component does not expose any component-specific props.
SidebarSectionrenders a <div> element
This component does not expose any component-specific props.
SidebarItemrenders a <button> element
href-Turns the item into a link rendered by your router. Without it, the item is a button.
currentfalseMarks the page the user is on and fills it with a soft background.
disabledfalseBlocks a button item.
SidebarLabelrenders a <span> element
This component does not expose any component-specific props.
SidebarHeadingrenders a <h3> element
This component does not expose any component-specific props.
SidebarDividerrenders a <hr> element
This component does not expose any component-specific props.
SidebarSpacerrenders a <div> element
This component does not expose any component-specific props.

Usage

Order the items by how often people need them. Daily work goes at the top, configuration and developer tools further down, and help links at the very bottom where they stay out of the way.

List the main areas

SidebarItem elements go in a SidebarSection, inside a SidebarBody. Plain text works as a first pass before you pick icons:

import { Sidebar, SidebarBody, SidebarItem, SidebarSection } from '@/components/sidebar'

export default function Example() {
  return (
    <Sidebar>
      <SidebarBody>
        <SidebarSection>
          <SidebarItem href="/overview">Overview</SidebarItem>
          <SidebarItem href="/payments">Payments</SidebarItem>
          <SidebarItem href="/invoices">Invoices</SidebarItem>
          <SidebarItem href="/customers">Customers</SidebarItem>
          <SidebarItem href="/payouts">Payouts</SidebarItem>
        </SidebarSection>
      </SidebarBody>
    </Sidebar>
  )
}
<script setup lang="ts">
import Sidebar from '@/components/sidebar.vue'
import SidebarBody from '@/components/sidebar-body.vue'
import SidebarItem from '@/components/sidebar-item.vue'
import SidebarSection from '@/components/sidebar-section.vue'
</script>

<template>
  <Sidebar>
    <SidebarBody>
      <SidebarSection>
        <SidebarItem href="/overview">Overview</SidebarItem>
        <SidebarItem href="/payments">Payments</SidebarItem>
        <SidebarItem href="/invoices">Invoices</SidebarItem>
        <SidebarItem href="/customers">Customers</SidebarItem>
        <SidebarItem href="/payouts">Payouts</SidebarItem>
      </SidebarSection>
    </SidebarBody>
  </Sidebar>
</template>

Add an icon to each item

Place the icon before a SidebarLabel. Icons help people find an item without reading the list, so pick shapes that are easy to tell apart. An icon you draw yourself needs data-slot="icon" to match the size and color of Heroicons:

<SidebarSection>
  <SidebarItem href="/overview">
    <Squares2X2Icon />
    <SidebarLabel>Overview</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/payments">
    <CreditCardIcon />
    <SidebarLabel>Payments</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/invoices">
    <DocumentTextIcon />
    <SidebarLabel>Invoices</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/customers">
    <UsersIcon />
    <SidebarLabel>Customers</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/payouts">
    <BuildingLibraryIcon />
    <SidebarLabel>Payouts</SidebarLabel>
  </SidebarItem>
</SidebarSection>
<SidebarSection>
  <SidebarItem href="/overview">
    <Squares2X2Icon />
    <SidebarLabel>Overview</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/payments">
    <CreditCardIcon />
    <SidebarLabel>Payments</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/invoices">
    <DocumentTextIcon />
    <SidebarLabel>Invoices</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/customers">
    <UsersIcon />
    <SidebarLabel>Customers</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/payouts">
    <BuildingLibraryIcon />
    <SidebarLabel>Payouts</SidebarLabel>
  </SidebarItem>
</SidebarSection>

Highlight the current page

Pass current to the item of the open page. It gets a soft background and full-strength text, the other items stay muted, and the background slides to the new item when current moves within the same section:

<SidebarSection>
  <SidebarItem href="/overview">
    <Squares2X2Icon />
    <SidebarLabel>Overview</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/payments" current>
    <CreditCardIcon />
    <SidebarLabel>Payments</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/invoices">
    <DocumentTextIcon />
    <SidebarLabel>Invoices</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/customers">
    <UsersIcon />
    <SidebarLabel>Customers</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/payouts">
    <BuildingLibraryIcon />
    <SidebarLabel>Payouts</SidebarLabel>
  </SidebarItem>
</SidebarSection>
<SidebarSection>
  <SidebarItem href="/overview">
    <Squares2X2Icon />
    <SidebarLabel>Overview</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/payments" current>
    <CreditCardIcon />
    <SidebarLabel>Payments</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/invoices">
    <DocumentTextIcon />
    <SidebarLabel>Invoices</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/customers">
    <UsersIcon />
    <SidebarLabel>Customers</SidebarLabel>
  </SidebarItem>
  <SidebarItem href="/payouts">
    <BuildingLibraryIcon />
    <SidebarLabel>Payouts</SidebarLabel>
  </SidebarItem>
</SidebarSection>

Structure

A sidebar has up to three zones. SidebarHeader and SidebarFooter hold their content in place, and SidebarBody takes the remaining height and scrolls on its own when the list is longer than the screen.

Pin a workspace switcher to the top

Put the switcher in SidebarHeader so it stays in reach however far the body scrolls. Rendering the DropdownButton as a SidebarItem gives it the same look as the links:

<Sidebar>
  <SidebarHeader>
    <Dropdown>
      <DropdownButton as={SidebarItem}>
        <Avatar initials="NW" className="bg-teal-600 text-white" />
        <SidebarLabel>Northwind</SidebarLabel>
        <ChevronDownIcon />
      </DropdownButton>
      <DropdownMenu className="min-w-64" anchor="bottom start">
        {/* ... */}
      </DropdownMenu>
    </Dropdown>
  </SidebarHeader>
  <SidebarBody>{/* ... */}</SidebarBody>
</Sidebar>
<Sidebar>
  <SidebarHeader>
    <Dropdown>
      <DropdownButton :as="SidebarItem">
        <Avatar initials="NW" class="bg-teal-600 text-white" />
        <SidebarLabel>Northwind</SidebarLabel>
        <ChevronDownIcon />
      </DropdownButton>
      <DropdownMenu class="min-w-64" anchor="bottom start">
        <!-- ... -->
      </DropdownMenu>
    </Dropdown>
  </SidebarHeader>
  <SidebarBody><!-- ... --></SidebarBody>
</Sidebar>

The Dropdown page lists what the menu can contain.

Keep the account at the bottom

SidebarFooter goes after the body. Open its menu with the top start anchor so it grows upward, into the sidebar:

<Sidebar>
  <SidebarBody>{/* ... */}</SidebarBody>
  <SidebarFooter>
    <Dropdown>
      <DropdownButton as={SidebarItem}>
        <span className="flex min-w-0 items-center gap-3">
          <Avatar src="/avatars/papac.jpg" className="size-10" square alt="" />
          <span className="min-w-0">
            <span className="block truncate text-sm/5 font-medium text-zinc-950 dark:text-white">Franck Dakia</span>
            <span className="block truncate text-xs/5 font-normal text-zinc-500 dark:text-zinc-400">
              franck@northwind.io
            </span>
          </span>
        </span>
        <ChevronUpIcon />
      </DropdownButton>
      <DropdownMenu className="min-w-64" anchor="top start">
        {/* ... */}
      </DropdownMenu>
    </Dropdown>
  </SidebarFooter>
</Sidebar>
<Sidebar>
  <SidebarBody><!-- ... --></SidebarBody>
  <SidebarFooter>
    <Dropdown>
      <DropdownButton :as="SidebarItem">
        <span class="flex min-w-0 items-center gap-3">
          <Avatar src="/avatars/papac.jpg" class="size-10" square alt="" />
          <span class="min-w-0">
            <span class="block truncate text-sm/5 font-medium text-zinc-950 dark:text-white">Franck Dakia</span>
            <span class="block truncate text-xs/5 font-normal text-zinc-500 dark:text-zinc-400">
              franck@northwind.io
            </span>
          </span>
        </span>
        <ChevronUpIcon />
      </DropdownButton>
      <DropdownMenu class="min-w-64" anchor="top start">
        <!-- ... -->
      </DropdownMenu>
    </Dropdown>
  </SidebarFooter>
</Sidebar>

Name a group of items

Start a section with SidebarHeading when its items share a purpose the icons alone do not explain:

<SidebarBody>
  <SidebarSection>{/* ... */}</SidebarSection>
  <SidebarSection>
    <SidebarHeading>Developers</SidebarHeading>
    <SidebarItem href="/developers/api-keys">
      <KeyIcon />
      <SidebarLabel>API keys</SidebarLabel>
    </SidebarItem>
    <SidebarItem href="/developers/webhooks">
      <ArrowsRightLeftIcon />
      <SidebarLabel>Webhooks</SidebarLabel>
    </SidebarItem>
    <SidebarItem href="/developers/logs">
      <CodeBracketIcon />
      <SidebarLabel>Logs</SidebarLabel>
    </SidebarItem>
  </SidebarSection>
</SidebarBody>
<SidebarBody>
  <SidebarSection><!-- ... --></SidebarSection>
  <SidebarSection>
    <SidebarHeading>Developers</SidebarHeading>
    <SidebarItem href="/developers/api-keys">
      <KeyIcon />
      <SidebarLabel>API keys</SidebarLabel>
    </SidebarItem>
    <SidebarItem href="/developers/webhooks">
      <ArrowsRightLeftIcon />
      <SidebarLabel>Webhooks</SidebarLabel>
    </SidebarItem>
    <SidebarItem href="/developers/logs">
      <CodeBracketIcon />
      <SidebarLabel>Logs</SidebarLabel>
    </SidebarItem>
  </SidebarSection>
</SidebarBody>

A SidebarSpacer fills the free height of the body, so the sections after it rest at the bottom edge:

<SidebarBody>
  <SidebarSection>{/* ... */}</SidebarSection>
  <SidebarSpacer />
  <SidebarSection>
    <SidebarItem href="/docs">
      <BookOpenIcon />
      <SidebarLabel>Documentation</SidebarLabel>
    </SidebarItem>
    <SidebarItem href="/status">
      <SignalIcon />
      <SidebarLabel>System status</SidebarLabel>
    </SidebarItem>
  </SidebarSection>
</SidebarBody>
<SidebarBody>
  <SidebarSection><!-- ... --></SidebarSection>
  <SidebarSpacer />
  <SidebarSection>
    <SidebarItem href="/docs">
      <BookOpenIcon />
      <SidebarLabel>Documentation</SidebarLabel>
    </SidebarItem>
    <SidebarItem href="/status">
      <SignalIcon />
      <SidebarLabel>System status</SidebarLabel>
    </SidebarItem>
  </SidebarSection>
</SidebarBody>

Separate groups with a rule

SidebarDivider draws a horizontal line. Reach for it instead of a heading when the split is obvious and a title would only repeat it:

<SidebarBody>
  <SidebarSection>{/* ... */}</SidebarSection>
  <SidebarDivider />
  <SidebarSection>
    <SidebarItem href="/developers/api-keys">
      <KeyIcon />
      <SidebarLabel>API keys</SidebarLabel>
    </SidebarItem>
    <SidebarItem href="/developers/webhooks">
      <ArrowsRightLeftIcon />
      <SidebarLabel>Webhooks</SidebarLabel>
    </SidebarItem>
    <SidebarItem href="/developers/logs">
      <CodeBracketIcon />
      <SidebarLabel>Logs</SidebarLabel>
    </SidebarItem>
  </SidebarSection>
</SidebarBody>
<SidebarBody>
  <SidebarSection><!-- ... --></SidebarSection>
  <SidebarDivider />
  <SidebarSection>
    <SidebarItem href="/developers/api-keys">
      <KeyIcon />
      <SidebarLabel>API keys</SidebarLabel>
    </SidebarItem>
    <SidebarItem href="/developers/webhooks">
      <ArrowsRightLeftIcon />
      <SidebarLabel>Webhooks</SidebarLabel>
    </SidebarItem>
    <SidebarItem href="/developers/logs">
      <CodeBracketIcon />
      <SidebarLabel>Logs</SidebarLabel>
    </SidebarItem>
  </SidebarSection>
</SidebarBody>

Customization

Any element can sit in the body next to the sections. A logo link above the first section, with a little bottom margin, is enough:

<SidebarBody>
  <Link href="/overview" aria-label="Overview" className="mb-2 flex">
    <Logo className="size-11 sm:size-10" />
  </Link>
  <SidebarSection>{/* ... */}</SidebarSection>
</SidebarBody>
<SidebarBody>
  <Link href="/overview" aria-label="Overview" class="mb-2 flex">
    <Logo class="size-11 sm:size-10" />
  </Link>
  <SidebarSection><!-- ... --></SidebarSection>
</SidebarBody>

Accessibility

The sidebar renders a nav landmark named Sidebar, and SidebarHeading an h3, so screen reader users can jump between groups. A current link carries aria-current="page". Inside the mobile drawer of SidebarLayout, choosing an item closes the drawer, whether it is a link or a button. An item that opens a menu, such as a team switcher, leaves it open.