Icon Rail Sidebar
blocklayoutCollapsible icon-rail app sidebar with brand block, two grouped nav sections, and a user dropdown footer. Pure template, no props -- edit Sidebar01.svelte to change routes and NavUser.svelte to wire your auth session. Pair with SidebarProvider + SidebarInset for the full admin shell.
Installation
$pnpm dlx shadcn-svelte@latest add https://uipkge.dev/r/svelte/sidebar-01.json$npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/sidebar-01.json$yarn dlx shadcn-svelte@latest add https://uipkge.dev/r/svelte/sidebar-01.json$bunx shadcn-svelte@latest add https://uipkge.dev/r/svelte/sidebar-01.jsonManifest:
https://uipkge.dev/r/svelte/sidebar-01.jsonInstalls to:src/lib/components/blocks/sidebar-01/Variants
Loading interactive previews…
Loading interactive previews…
npm dependencies
Includes
Files installed (3)
src/lib/components/blocks/sidebar-01/Sidebar01.svelte4 kB
<script lang="ts"> // Edit this file to change brand, navigation, and the user dropdown. // Every menu item is spelled out below -- copy, remove, or rename rows directly. import { BarChart3, BookOpen, FileText, Files, History, LayoutDashboard, Table as TableIcon } from '@lucide/svelte' import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarRail, } from '$lib/components/ui/sidebar' import NavUser from './NavUser.svelte' </script> <Sidebar data-slot="sidebar-01" collapsible="icon"> <SidebarHeader> <SidebarMenu> <SidebarMenuItem> <SidebarMenuButton size="lg" tooltip="uipkge" class="group-data-[collapsible=icon]:!justify-center"> <div class="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 shrink-0 items-center justify-center rounded-lg group-data-[collapsible=icon]:size-6" > <svg viewBox="0 0 24 24" class="size-4 group-data-[collapsible=icon]:size-3.5" fill="currentColor" aria-hidden="true" > <rect x="2" y="2" width="9" height="9" rx="1.5" /> <rect x="13" y="2" width="9" height="9" rx="1.5" opacity="0.55" /> <rect x="2" y="13" width="9" height="9" rx="1.5" opacity="0.55" /> <rect x="13" y="13" width="9" height="9" rx="1.5" /> </svg> </div> <div class="grid flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden"> <span class="font-display truncate font-bold">uipkge</span> <span class="text-muted-foreground truncate text-xs">uipkge.dev</span> </div> </SidebarMenuButton> </SidebarMenuItem> </SidebarMenu> </SidebarHeader> <SidebarContent> <SidebarGroup> <SidebarGroupLabel>Workspace</SidebarGroupLabel> <SidebarGroupContent> <SidebarMenu> <SidebarMenuItem> <!-- TODO: wrap in an <a href="..."> and bind isActive to your route --> <SidebarMenuButton isActive tooltip="Dashboard"> <LayoutDashboard class="size-4" /> <span>Dashboard</span> </SidebarMenuButton> </SidebarMenuItem> <SidebarMenuItem> <SidebarMenuButton tooltip="Data tables"> <TableIcon class="size-4" /> <span>Data tables</span> </SidebarMenuButton> </SidebarMenuItem> <SidebarMenuItem> <SidebarMenuButton tooltip="Forms"> <FileText class="size-4" /> <span>Forms</span> </SidebarMenuButton> </SidebarMenuItem> <SidebarMenuItem> <SidebarMenuButton tooltip="Charts"> <BarChart3 class="size-4" /> <span>Charts</span> </SidebarMenuButton> </SidebarMenuItem> <SidebarMenuItem> <SidebarMenuButton tooltip="Pages"> <Files class="size-4" /> <span>Pages</span> </SidebarMenuButton> </SidebarMenuItem> </SidebarMenu> </SidebarGroupContent> </SidebarGroup> <SidebarGroup> <SidebarGroupLabel>Resources</SidebarGroupLabel> <SidebarGroupContent> <SidebarMenu> <SidebarMenuItem> <SidebarMenuButton tooltip="Docs"> <BookOpen class="size-4" /> <span>Docs</span> </SidebarMenuButton> </SidebarMenuItem> <SidebarMenuItem> <SidebarMenuButton tooltip="Changelog"> <History class="size-4" /> <span>Changelog</span> </SidebarMenuButton> </SidebarMenuItem> </SidebarMenu> </SidebarGroupContent> </SidebarGroup> </SidebarContent> <SidebarFooter> <NavUser /> </SidebarFooter> <SidebarRail /> </Sidebar>src/lib/components/blocks/sidebar-01/NavUser.svelte5.2 kB
<script lang="ts"> // Edit this file to change the user dropdown content, avatar, and logout handler. // The user details are inlined below -- wire them to your auth session in place. import { onMount } from 'svelte' import { BadgeCheck, ChevronsUpDown, LogOut, Monitor, Moon, Palette, Settings, Sun } from '@lucide/svelte' import { Avatar, AvatarFallback } from '$lib/components/ui/avatar' import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from '$lib/components/ui/dropdown-menu' import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, useSidebar } from '$lib/components/ui/sidebar' const sidebar = useSidebar() // Replace these with your auth session. const user = { name: 'Test User', email: '[email protected]', initials: 'TU', } // Local theme model: 'system' follows the OS preference, explicit choices // pin the `dark` class and persist to localStorage. Swap this for your // app-wide theme store after installing. type Theme = 'light' | 'dark' | 'system' let theme = $state<Theme>('system') function applyTheme(next: Theme) { theme = next if (typeof document === 'undefined') return const dark = next === 'dark' || (next === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) document.documentElement.classList.toggle('dark', dark) try { window.localStorage.setItem('uipkge:theme', next) } catch { // Blocked storage: the choice holds for this page view only. } } onMount(() => { try { const stored = window.localStorage.getItem('uipkge:theme') as Theme | null if (stored === 'light' || stored === 'dark' || stored === 'system') applyTheme(stored) else applyTheme('system') } catch { applyTheme('system') } }) function handleLogout() { // TODO: call your /api/auth/logout endpoint, then redirect. console.warn('NavUser: wire handleLogout() to your auth backend') } </script> <SidebarMenu data-slot="sidebar-01"> <SidebarMenuItem> <DropdownMenu> <DropdownMenuTrigger> {#snippet child({ props })} <SidebarMenuButton {...props} size="lg" class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground group-data-[collapsible=icon]:!justify-center" > <Avatar class="h-8 w-8 shrink-0 rounded-lg group-data-[collapsible=icon]:size-6"> <AvatarFallback class="rounded-lg text-xs">{user.initials}</AvatarFallback> </Avatar> <div class="grid flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden"> <span class="truncate font-medium">{user.name}</span> <span class="truncate text-xs">{user.email}</span> </div> <ChevronsUpDown class="ml-auto size-4 group-data-[collapsible=icon]:hidden" /> </SidebarMenuButton> {/snippet} </DropdownMenuTrigger> <DropdownMenuContent class="min-w-56 rounded-lg" side={sidebar.isMobile ? 'bottom' : 'right'} align="end" sideOffset={4} > <DropdownMenuLabel class="p-0 font-normal"> <div class="flex items-center gap-2 px-1 py-1.5 text-left text-sm"> <Avatar class="h-8 w-8 rounded-lg"> <AvatarFallback class="rounded-lg">{user.initials}</AvatarFallback> </Avatar> <div class="grid flex-1 text-left text-sm leading-tight"> <span class="truncate font-semibold">{user.name}</span> <span class="truncate text-xs">{user.email}</span> </div> </div> </DropdownMenuLabel> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem><BadgeCheck class="size-4" /> Profile</DropdownMenuItem> <DropdownMenuItem><Settings class="size-4" /> Settings</DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuSub> <DropdownMenuSubTrigger> <Palette class="size-4" /> Theme <span class="text-muted-foreground ml-auto text-xs capitalize">{theme}</span> </DropdownMenuSubTrigger> <DropdownMenuSubContent class="min-w-36"> <DropdownMenuRadioGroup value={theme} onValueChange={(v) => applyTheme(v as Theme)}> <DropdownMenuRadioItem value="light"><Sun class="size-4" /> Light</DropdownMenuRadioItem> <DropdownMenuRadioItem value="dark"><Moon class="size-4" /> Dark</DropdownMenuRadioItem> <DropdownMenuRadioItem value="system"><Monitor class="size-4" /> System</DropdownMenuRadioItem> </DropdownMenuRadioGroup> </DropdownMenuSubContent> </DropdownMenuSub> <DropdownMenuSeparator /> <DropdownMenuItem onSelect={handleLogout}> <LogOut class="size-4" /> Log out </DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> </SidebarMenuItem> </SidebarMenu>src/routes/sidebar-01-demo/+page.svelte1.1 kB
<script lang="ts"> // Demo page wired by `npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/sidebar-01.json`. // Visit /sidebar-01-demo after install to see the block without // editing your own pages. Free to edit or delete me. import Sidebar01 from '$lib/components/blocks/sidebar-01/Sidebar01.svelte' import { SidebarInset, SidebarProvider, SidebarTrigger } from '$lib/components/ui/sidebar' </script> <SidebarProvider> <Sidebar01 /> <SidebarInset> <header class="border-border flex h-14 shrink-0 items-center gap-3 border-b px-4"> <SidebarTrigger class="size-7" /> <h1 class="text-sm font-semibold">sidebar-01 demo</h1> </header> <div class="flex-1 p-6"> <div class="grid auto-rows-min gap-4 md:grid-cols-3"> <div class="bg-muted/50 aspect-video rounded-xl"></div> <div class="bg-muted/50 aspect-video rounded-xl"></div> <div class="bg-muted/50 aspect-video rounded-xl"></div> </div> <div class="bg-muted/50 mt-4 min-h-[60vh] rounded-xl"></div> </div> </SidebarInset> </SidebarProvider>
Raw manifest:https://uipkge.dev/r/svelte/sidebar-01.json