Components
Sidebar New · experimental
shadcn's dashboard Sidebar with goo. A goo highlight glides between items, and the edge sloshes as it collapses.
Customize
GoopSidebar is shadcn-vue's Sidebar with the same parts and API: useSidebar(), the sidebar_state cookie, the Ctrl/Cmd+B shortcut, side, variant, collapsible, and a sheet below 768px. Swap the imports and you're done.
Installation
Nuxt
pnpm add @goopui/nuxt
export default defineNuxtConfig({
modules: ['@goopui/nuxt'],
})
The module auto-imports every GoopSidebar* part, adds goop.css, and points Tailwind at the component classes. It needs Tailwind CSS v4 and shadcn's sidebar tokens (--sidebar, --sidebar-accent, --sidebar-border, ...).
Vue
pnpm add @goopui/vue
@import "tailwindcss";
@import "@goopui/vue/goop.css";
Usage
<script setup lang="ts">
// Nuxt auto-imports these. In plain Vue, import them from '@goopui/vue'.
</script>
<template>
<GoopSidebarProvider>
<GoopSidebar collapsible="icon">
<GoopSidebarHeader>...</GoopSidebarHeader>
<GoopSidebarContent>
<GoopSidebarGroup>
<GoopSidebarGroupLabel>Platform</GoopSidebarGroupLabel>
<GoopSidebarMenu>
<GoopSidebarMenuItem>
<GoopSidebarMenuButton is-active tooltip="Dashboard">
<House /><span>Dashboard</span>
</GoopSidebarMenuButton>
</GoopSidebarMenuItem>
<GoopCollapsible as-child class="group/collapsible">
<GoopSidebarMenuItem>
<GoopCollapsibleTrigger as-child>
<GoopSidebarMenuButton tooltip="Documentation">
<BookOpen /><span>Documentation</span>
</GoopSidebarMenuButton>
</GoopCollapsibleTrigger>
<GoopCollapsibleContent>
<GoopSidebarMenuSub>
<GoopSidebarMenuSubItem>
<GoopSidebarMenuSubButton href="#">Introduction</GoopSidebarMenuSubButton>
</GoopSidebarMenuSubItem>
</GoopSidebarMenuSub>
</GoopCollapsibleContent>
</GoopSidebarMenuItem>
</GoopCollapsible>
</GoopSidebarMenu>
</GoopSidebarGroup>
</GoopSidebarContent>
<GoopSidebarFooter>...</GoopSidebarFooter>
<GoopSidebarRail />
</GoopSidebar>
<GoopSidebarInset>
<header><GoopSidebarTrigger /></header>
<!-- your page -->
</GoopSidebarInset>
</GoopSidebarProvider>
</template>
The parts are GoopSidebarProvider, GoopSidebar, GoopSidebarTrigger, GoopSidebarRail, GoopSidebarInset, GoopSidebarHeader, GoopSidebarFooter, GoopSidebarContent, GoopSidebarGroup (with Label, Action, Content), GoopSidebarMenu (with Item, Button, Action, Badge, Skeleton, Sub, SubItem, SubButton), GoopSidebarSeparator, and GoopSidebarInput. useSidebar() returns state, open, setOpen, isMobile, openMobile, setOpenMobile, and toggleSidebar.
Behavior
- Highlight. Hovering or tabbing through the menu moves one goo blob between the items. It travels with momentum, stretches a little, and its soft swell follows the cursor along the item (
highlight,followPointer). - Active item. The active item is a soft filled pill with a hint of the accent and a faint rim (
pill). - Edge slosh. When the sidebar collapses or expands, its inner edge is goo with inertia. A collapse pushes low, wide mounds out of the edge while it moves and lets them slosh back. An expand lands with a gentle overshoot. The mounds are placed differently every time, and at rest the edge is the sidebar's own (
slosh). - Sub-menus. A
GoopCollapsibleinside the sidebar floods its row from where you clicked and springs the sub-menu open (submenus). - Icon mode. Collapsed to icons, each button's
tooltipis aGoopTooltipthat blooms beside it (tooltips). - Mobile. Below 768px the sidebar is a sheet that blooms from the middle of its screen edge (
bloom). - No layout cost. The goo is drawn on
aria-hiddenlayers behind the real content. It never changes the page's scroll size.
Turning effects off
Every effect is a prop on GoopSidebar:
<GoopSidebar :slosh="false" />
<GoopSidebar :slosh="1.6" preset="wild" />
<GoopSidebar :highlight="false" :pill="false" />
<GoopSidebar :goo="false" />
Props
The other parts take shadcn-vue's props. GoopSidebarMenuButton takes variant (default | outline), size (default | sm | lg), isActive, tooltip, as, and asChild. GoopSidebarProvider takes defaultOpen, open (v-model:open), and class. GoopSidebar takes these:
| Prop | Type | Default | Notes |
|---|---|---|---|
side | 'left' | 'right' | 'left' | The screen side the sidebar sits on. |
variant | 'sidebar' | 'floating' | 'inset' | 'sidebar' | shadcn's three looks: flush with a border, a floating card, or inset beside a rounded main area. |
collapsible | 'offcanvas' | 'icon' | 'none' | 'offcanvas' | How it collapses: slides off screen, shrinks to icons, or never collapses. |
goo | boolean | true | Master switch. false renders a plain shadcn Sidebar. |
highlight | boolean | true | The hover and focus highlight is a goo blob that glides between items, its soft swell under the cursor. |
followPointer | boolean | true | The highlight's swell follows the cursor along the item. false keeps it centred. |
pill | boolean | true | The active item is a soft filled pill with a faint rim. |
slosh | boolean | number | true | Collapsing and expanding slosh the inner edge in low, wide mounds, driven by how fast the edge moves. A number from 0 to 2 sets the strength. |
submenus | boolean | true | GoopCollapsible sub-menus inside flood their row and spring open. |
tooltips | boolean | true | Icon-mode tooltips (GoopSidebarMenuButton tooltip) bloom as goo. |
bloom | boolean | true | On mobile the sheet blooms from its screen edge like GoopSheet. |
speed | number | 1 | Animation speed multiplier. |
preset | 'subtle' | 'playful' | 'wild' | app config, then playful | The overall feel. |
renderer | 'svg' | 'canvas' | app config, then 'svg' | How the goo is drawn. |
Accessibility
Keyboard focus, the Ctrl/Cmd+B shortcut, the mobile sheet's focus trap, and the tooltips come from the same reka-ui primitives as shadcn-vue. Every goo layer is aria-hidden and can't be clicked, and text is never filtered. Under reduced motion the edge doesn't slosh, the highlight snaps between items, and the sheet, tooltips, and sub-menus open plainly. See Accessibility & reduced motion.