Sidebar
Komponen sidebar yang bisa dikomposisikan, diberi tema, dan disesuaikan.
<script lang="ts">
export const description
= "A sidebar that collapses to icons."
export const iframeHeight = "800px"
export const containerClass = "w-full h-full"
</script>
<script setup lang="ts">
import AppSidebar from "@/blocks/sidebar-07/components/AppSidebar.vue"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Separator } from "@/components/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/components/ui/sidebar"
</script>
<template>
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header class="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12">
<div class="flex items-center gap-2 px-4">
<SidebarTrigger class="-ml-1" />
<Separator
orientation="vertical"
class="mr-2 data-[orientation=vertical]:h-4"
/>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem class="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator class="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
</header>
<div class="flex flex-1 flex-col gap-4 p-4 pt-0">
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
<div class="bg-muted/50 aspect-video rounded-xl" />
<div class="bg-muted/50 aspect-video rounded-xl" />
<div class="bg-muted/50 aspect-video rounded-xl" />
</div>
<div class="bg-muted/50 min-h-[100vh] flex-1 rounded-xl md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
</template>Sidebar termasuk komponen yang paling rumit dibangun. Ia jadi pusat hampir setiap aplikasi, dan biasanya memuat banyak bagian yang saling bergerak.
Membangun sidebar itu melelahkan. Karena itu upstream membangunnya 30 kali lebih, dalam berbagai konfigurasi, lalu menyaring bagian intinya menjadi Sidebar*.vue.
Hasilnya adalah fondasi yang kokoh untuk Anda kembangkan. Bisa dikomposisikan, diberi tema, dan disesuaikan.
Instalasi
CLI
npx shadcn-vue@latest add sidebarManual
Pasang komponen ini
npx shadcn-vue@latest add sidebarTambahkan warna-warna berikut ke file CSS Anda
Perintah di atas semestinya sudah memasang warnanya untuk Anda. Kalau belum, salin dan tempel isi berikut ke file CSS Anda.
@layer base {
:root {
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}Struktur
Komponen Sidebar tersusun dari bagian-bagian berikut:
SidebarProvider— mengurus state buka-tutup.Sidebar— wadah sidebar-nya.SidebarHeaderdanSidebarFooter— menempel di bagian atas dan bawah sidebar.SidebarContent— isi yang bisa digulir.SidebarGroup— bagian di dalamSidebarContent.SidebarTrigger— pemicu untuk membuka dan menutup sidebar.


Penggunaan
<script setup lang="ts">
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarRail,
SidebarTrigger,
} from '@/components/ui/sidebar'
</script>
<template>
<SidebarProvider>
<Sidebar>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg">
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<GalleryVerticalEnd class="size-4" />
</div>
<div class="grid flex-1 text-left text-sm leading-tight">
<span class="truncate font-semibold">Acme Inc</span>
<span class="truncate text-xs">Enterprise</span>
</div>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Platform</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton as-child>
<a href="#">
<Home />
<span>Home</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter />
<SidebarRail />
</Sidebar>
<SidebarInset>
<header class="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
<div class="flex items-center gap-2 px-4">
<SidebarTrigger class="-ml-1" />
</div>
</header>
<div class="flex flex-1 flex-col gap-4 p-4 pt-0">
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
<div class="aspect-video rounded-xl bg-muted/50" />
<div class="aspect-video rounded-xl bg-muted/50" />
<div class="aspect-video rounded-xl bg-muted/50" />
</div>
<div class="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
</div>
</SidebarInset>
</SidebarProvider>
</template>Sidebar Pertama Anda
Mari mulai dari sidebar paling sederhana: sidebar yang bisa dilipat dan berisi menu.
Tambahkan SidebarProvider dan SidebarTrigger di bagian terluar aplikasi Anda
<script setup lang="ts">
import AppSidebar from '@/components/AppSidebar.vue'
import { SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar'
</script>
<template>
<SidebarProvider>
<AppSidebar />
<main>
<SidebarTrigger />
<slot />
</main>
</SidebarProvider>
</template>Buat komponen sidebar baru di @/components/AppSidebar.vue
<script setup lang="ts">
import { Sidebar, SidebarContent } from '@/components/ui/sidebar'
</script>
<template>
<Sidebar>
<SidebarContent />
</Sidebar>
</template>Sekarang tambahkan SidebarMenu ke dalam sidebar
Komponen SidebarMenu akan kita letakkan di dalam SidebarGroup.
<script setup lang="ts">
import { Calendar, Home, Inbox, Search, Settings } from '@lucide/vue'
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from '@/components/ui/sidebar'
// Menu items.
const items = [
{
title: 'Home',
url: '#',
icon: Home,
},
{
title: 'Inbox',
url: '#',
icon: Inbox,
},
{
title: 'Calendar',
url: '#',
icon: Calendar,
},
{
title: 'Search',
url: '#',
icon: Search,
},
{
title: 'Settings',
url: '#',
icon: Settings,
},
]
</script>
<template>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem v-for="item in items" :key="item.title">
<SidebarMenuButton as-child>
<a :href="item.url">
<component :is="item.icon" />
<span>{{ item.title }}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</template>Sidebar pertama Anda sudah jadi.
Hasilnya kurang lebih seperti ini:
<script setup lang="ts">
import { Calendar, Home, Inbox, Search, Settings } from "@lucide/vue"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarTrigger,
} from "@/components/ui/sidebar"
// Menu items.
const items = [
{
title: "Home",
url: "#",
icon: Home,
},
{
title: "Inbox",
url: "#",
icon: Inbox,
},
{
title: "Calendar",
url: "#",
icon: Calendar,
},
{
title: "Search",
url: "#",
icon: Search,
},
{
title: "Settings",
url: "#",
icon: Settings,
},
]
</script>
<template>
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem v-for="item in items" :key="item.title">
<SidebarMenuButton as-child>
<a :href="item.url">
<component :is="item.icon" />
<span>{{ item.title }}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
<SidebarInset>
<header class="flex items-center justify-between px-4 h-12">
<SidebarTrigger />
</header>
</SidebarInset>
</SidebarProvider>
</template>Komponen di berkas Sidebar*.vue dirancang agar bisa dikomposisikan — Anda menyusun sidebar dengan merangkai komponen yang tersedia. Semuanya juga menyatu baik dengan komponen lain seperti DropdownMenu, Collapsible, Dialog, dan sebagainya.
Kalau Anda perlu mengubah kode di berkas Sidebar*.vue, silakan saja. Kodenya milik Anda. Pakai komponen yang tersedia sebagai titik awal untuk membangun versi Anda sendiri.
SidebarProvider
Komponen SidebarProvider menyediakan konteks sidebar untuk semua komponen di dalamnya.
Props
Komponen SidebarProvider menerima prop berikut:
Lebar
Pakai prop defaultOpen, open, dan onOpenChange untuk mengendalikan keadaan buka-tutup sidebar.
<script setup lang="ts">
import { ref } from 'vue'
const open = ref(false)
</script>
<template>
<SidebarProvider :open="open" @update:open="open = $event">
<!-- ... -->
</SidebarProvider>
</template>Pintasan Keyboard
Komponen SidebarProvider mendukung pintasan keyboard untuk membuka dan menutup sidebar. Pintasan bawaannya cmd+b atau ctrl+b.
<SidebarProvider>
<!-- ... -->
</SidebarProvider>State yang Tersimpan
Untuk menyimpan keadaan sidebar, pakai prop storageKey pada komponen SidebarProvider.
<SidebarProvider storage-key="sidebar">
<!-- ... -->
</SidebarProvider><SidebarProvider
:default-open="false"
storage-key="sidebar"
class="flex min-h-screen"
>
<!-- ... -->
</SidebarProvider>Sidebar
Komponen sidebar utamanya.
<Sidebar>
<SidebarHeader />
<SidebarContent />
<SidebarFooter />
</Sidebar>Props
Komponen Sidebar menerima prop berikut:
side
Pakai prop side untuk menentukan di sisi mana sidebar berada.
<Sidebar side="left">
<!-- ... -->
</Sidebar>variant
Pakai prop variant untuk menentukan varian sidebar.
<!-- Default variant -->
<Sidebar variant="sidebar">
<!-- ... -->
</Sidebar><!-- Floating variant -->
<Sidebar variant="floating">
<!-- ... -->
</Sidebar><!-- Inset variant -->
<Sidebar variant="inset">
<!-- ... -->
</Sidebar>collapsible
Pakai prop collapsible supaya sidebar bisa dilipat.
<Sidebar collapsible="icon">
<!-- ... -->
</Sidebar><Sidebar collapsible="offcanvas">
<!-- ... -->
</Sidebar>useSidebar
Composable useSidebar dipakai untuk mengendalikan sidebar.
<script setup lang="ts">
import { useSidebar } from '@/components/ui/sidebar'
const {
state,
open,
setOpen,
openMobile,
setOpenMobile,
isMobile,
toggleSidebar,
} = useSidebar()
</script>SidebarHeader
Menampilkan bagian header sidebar.
<Sidebar>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg">
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<GalleryVerticalEnd class="size-4" />
</div>
<div class="flex flex-col gap-0.5 leading-none">
<span class="font-semibold">Documentation</span>
<span class="">v1.0.0</span>
</div>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
</Sidebar>SidebarFooter
Menampilkan bagian footer sidebar.
<Sidebar>
<SidebarFooter>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<SidebarMenuButton>
<User2 /> Username
<ChevronUp class="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
side="top"
class="w-(--reka-popper-anchor-width)"
>
<DropdownMenuItem>
<span>Account</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Billing</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Sign out</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>
</Sidebar>SidebarContent
Area isi sidebar yang bisa digulir.
<Sidebar>
<SidebarContent>
<SidebarGroup />
<SidebarGroup />
</SidebarContent>
</Sidebar>SidebarGroup
Mengelompokkan item menu di dalam sidebar.
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupContent>
<!-- SidebarMenu -->
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>SidebarGroup yang Bisa Dilipat
Untuk membuat SidebarGroup bisa dilipat, bungkus dengan komponen Collapsible.
<SidebarGroup as-child>
<Collapsible default-open class="group/collapsible">
<SidebarGroupLabel as-child>
<CollapsibleTrigger class="group/label w-full text-left text-sm text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground [&[data-state=open]>svg]:rotate-90">
Help
<ChevronRight class="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" />
</CollapsibleTrigger>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
<!-- Menu items -->
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</Collapsible>
</SidebarGroup>SidebarGroupAction
Komponen SidebarGroupAction menampilkan tombol aksi di header sebuah grup sidebar.
<SidebarGroup>
<SidebarGroupLabel>
Projects
<SidebarGroupAction>
<Plus /> <span class="sr-only">Add Project</span>
</SidebarGroupAction>
</SidebarGroupLabel>
<SidebarGroupContent></SidebarGroupContent>
</SidebarGroup>SidebarMenu
Komponen SidebarMenu menampilkan menu di dalam sidebar.
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton as-child>
<a href="#">
<Home />
<span>Home</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton as-child>
<a href="#">
<Inbox />
<span>Inbox</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>SidebarMenuButton
Komponen SidebarMenuButton menampilkan tombol menu di dalam sidebar.
Tautan atau Anchor
Pakai prop as-child untuk menampilkan SidebarMenuButton sebagai tautan atau elemen anchor.
<SidebarMenuButton as-child>
<a href="#">
<Home />
<span>Home</span>
</a>
</SidebarMenuButton>Ikon dan Label
Komponen SidebarMenuButton bisa memuat ikon sekaligus label.
<SidebarMenuButton>
<Home />
<span>Home</span>
</SidebarMenuButton>isActive
Pakai prop isActive untuk menandai tombol menu yang sedang aktif.
<SidebarMenuButton :is-active="true">
<Home />
<span>Home</span>
</SidebarMenuButton>SidebarMenuAction
Komponen SidebarMenuAction menampilkan aksi menu di dalam sidebar.
<SidebarMenuItem>
<SidebarMenuButton>
<Home />
<span>Home</span>
</SidebarMenuButton>
<SidebarMenuAction>
<MoreHorizontal />
</SidebarMenuAction>
</SidebarMenuItem>DropdownMenu
Komponen SidebarMenuAction bisa dipadukan dengan DropdownMenu.
<SidebarMenuItem>
<SidebarMenuButton>
<Home />
<span>Home</span>
</SidebarMenuButton>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<SidebarMenuAction>
<MoreHorizontal />
</SidebarMenuAction>
</DropdownMenuTrigger>
<DropdownMenuContent side="right" align="start">
<DropdownMenuItem>
<span>Edit Project</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Delete Project</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>SidebarMenuSub
Komponen SidebarMenuSub menampilkan submenu di dalam sidebar.
<SidebarMenuItem>
<SidebarMenuButton>
<Home />
<span>Home</span>
</SidebarMenuButton>
<SidebarMenuSub>
<SidebarMenuItem>
<SidebarMenuButton>
<span>History</span>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>
<span>Starred</span>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenuSub>
</SidebarMenuItem>SidebarMenu yang Bisa Dilipat
Untuk membuat SidebarMenu bisa dilipat, bungkus dengan komponen Collapsible.
<SidebarMenuItem>
<Collapsible default-open class="group/collapsible">
<CollapsibleTrigger as-child>
<SidebarMenuButton>
<Home />
<span>Home</span>
<ChevronRight class="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" />
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
<SidebarMenuItem>
<SidebarMenuButton>
<span>History</span>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton>
<span>Starred</span>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenuSub>
</CollapsibleContent>
</Collapsible>
</SidebarMenuItem>SidebarMenuBadge
Komponen SidebarMenuBadge menampilkan badge di dalam menu sidebar.
<SidebarMenuButton>
<Home />
<span>Home</span>
<SidebarMenuBadge>24</SidebarMenuBadge>
</SidebarMenuButton>SidebarMenuSkeleton
Komponen SidebarMenuSkeleton bisa Anda pakai untuk menampilkan kerangka pemuatan di dalam menu sidebar.
<SidebarMenu>
<SidebarMenuItem v-for="item in Array.from({ length: 5 })" :key="item">
<SidebarMenuSkeleton />
</SidebarMenuItem>
</SidebarMenu>SidebarSeparator
Komponen SidebarSeparator menampilkan pemisah di dalam sidebar.
<SidebarContent>
<SidebarGroup />
<SidebarSeparator />
<SidebarGroup />
</SidebarContent>SidebarTrigger
Komponen SidebarTrigger menampilkan tombol pemicu untuk sidebar.
<SidebarTrigger />Pemicu Buatan Sendiri
Anda bisa membuat pemicu sendiri memakai composable useSidebar.
<script setup lang="ts">
import { useSidebar } from '@/components/ui/sidebar'
const { toggleSidebar } = useSidebar()
</script>
<template>
<Button @click="toggleSidebar">
Toggle Sidebar
</Button>
</template>SidebarRail
Komponen SidebarRail menampilkan bilah tipis di sisi sidebar. Biasanya dipakai untuk membuka sidebar saat di-hover dalam keadaan terlipat.
<Sidebar collapsible="icon">
<SidebarHeader />
<SidebarContent />
<SidebarFooter />
<SidebarRail />
</Sidebar>Sidebar yang Dikendalikan dari Luar
Pakai prop open dan onOpenChange untuk mengendalikan sidebar dari luar.
<script setup lang="ts">
import { ref } from 'vue'
const open = ref(false)
</script>
<template>
<SidebarProvider :open="open" @update:open="open = $event">
<Sidebar />
</SidebarProvider>
</template>Tema
Tema sidebar bisa Anda atur lewat CSS variable.
@layer base {
:root {
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}Pemberian Style
Beberapa tips untuk men-style sidebar:
- Pakai atribut
data-sidebardandata-stateuntuk men-style sidebar. - Sidebar otomatis mengatur CSS variable
--sidebar-width. Nilai itu bisa Anda pakai untuk menyesuaikan tata letak konten utama.