Floating Inset Sidebar
blocklayoutFloating sidebar variant with rounded corners and inset margins. Uses Sidebar variant="floating" and SidebarMenuSub for nested routes. Sample data inlined so consumers edit routes in place.
Installation
$pnpm dlx shadcn@latest add https://uipkge.dev/r/lit/sidebar-04.json$npx shadcn@latest add https://uipkge.dev/r/lit/sidebar-04.json$yarn dlx shadcn@latest add https://uipkge.dev/r/lit/sidebar-04.json$bunx shadcn@latest add https://uipkge.dev/r/lit/sidebar-04.jsonManifest:
https://uipkge.dev/r/lit/sidebar-04.jsonInstalls to:src/uip/blocks/sidebar-04/Variants
Loading interactive previews…
Loading interactive previews…
Schema
Type aliases exported from this item's source. Use these to shape the data you pass in.
NavChildinterface NavChild {
title: string
url: string
isActive?: boolean
}NavIteminterface NavItem {
title: string
url: string
isActive?: boolean
items: NavChild[]
}HTMLElementTagNameMapinterface HTMLElementTagNameMap {
'uip-sidebar-04': UipSidebar04
}
}Files installed (1)
src/uip/blocks/sidebar-04/sidebar-04.ts5.6 kB
import { LitElement, css, html } from 'lit' import { tailwind } from '../../lib/styles' import { ThemeController } from '../../lib/theme' // Side-effect import: registers the composed elements for standalone use // (consumers who install only this block still get working primitives). import '../../components/sidebar/sidebar' interface NavChild { title: string url: string isActive?: boolean } interface NavItem { title: string url: string isActive?: boolean items: NavChild[] } // Sample data (React's `data`, inlined so consumers edit routes in place). const navMain: NavItem[] = [ { title: 'Getting Started', url: '#', items: [ { title: 'Installation', url: '#' }, { title: 'Project Structure', url: '#' }, ], }, { title: 'Building Your Application', url: '#', items: [ { title: 'Routing', url: '#' }, { title: 'Data Fetching', url: '#', isActive: true }, { title: 'Rendering', url: '#' }, { title: 'Caching', url: '#' }, { title: 'Styling', url: '#' }, { title: 'Optimizing', url: '#' }, { title: 'Configuring', url: '#' }, { title: 'Testing', url: '#' }, { title: 'Authentication', url: '#' }, { title: 'Deploying', url: '#' }, { title: 'Upgrading', url: '#' }, { title: 'Examples', url: '#' }, ], }, { title: 'API Reference', url: '#', items: [ { title: 'Components', url: '#' }, { title: 'File Conventions', url: '#' }, { title: 'Functions', url: '#' }, { title: 'next.config.js Options', url: '#' }, { title: 'CLI', url: '#' }, { title: 'Edge Runtime', url: '#' }, ], }, { title: 'Architecture', url: '#', items: [ { title: 'Accessibility', url: '#' }, { title: 'Fast Refresh', url: '#' }, { title: 'Next.js Compiler', url: '#' }, { title: 'Supported Browsers', url: '#' }, { title: 'Turbopack', url: '#' }, ], }, { title: 'Community', url: '#', items: [{ title: 'Contribution Guide', url: '#' }], }, ] /** * <uip-sidebar-04> — the registry Sidebar04 block as a web component. * * Class strings are React's verbatim (`variant="floating"`, nested * SidebarMenuSub route tree). The menu/sub layout classes that React sets on * the parts (`gap-2`, `ml-0 border-l-0 px-1.5`) are scoped to the parts' * `base` (the part hosts are `display: contents`, so plain host classes * would have no box to land on). No props, no events: edit the markup in * place. */ export class UipSidebar04 extends LitElement { static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true } // :host display can't be a utility class (the host has no template of its own). static styles = [tailwind, css`:host { display: block; }`] constructor() { super() new ThemeController(this) } connectedCallback() { super.connectedCallback() this.setAttribute('data-uipkge', '') this.setAttribute('data-slot', 'sidebar-04') } render() { return html` <uip-sidebar variant="floating"> <uip-sidebar-header> <uip-sidebar-menu> <uip-sidebar-menu-item> <uip-sidebar-menu-button size="lg" href="#"> <div class="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg"> <svg viewBox="0 0 24 24" class="size-4" 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="flex flex-col gap-0.5 leading-none"> <span class="font-medium">uipkge</span> <span>v1.0.0</span> </div> </uip-sidebar-menu-button> </uip-sidebar-menu-item> </uip-sidebar-menu> </uip-sidebar-header> <uip-sidebar-content> <uip-sidebar-group> <uip-sidebar-menu class="[&::part(base)]:gap-2"> ${navMain.map( (item) => html` <uip-sidebar-menu-item> <uip-sidebar-menu-button href=${item.url} ?is-active=${!!item.isActive} class="font-medium"> ${item.title} </uip-sidebar-menu-button> ${item.items.length ? html`<uip-sidebar-menu-sub class="[&::part(base)]:ml-0 [&::part(base)]:border-l-0 [&::part(base)]:px-1.5"> ${item.items.map( (childItem) => html` <uip-sidebar-menu-sub-item> <uip-sidebar-menu-sub-button href=${childItem.url} ?is-active=${!!childItem.isActive}> ${childItem.title} </uip-sidebar-menu-sub-button> </uip-sidebar-menu-sub-item> `, )} </uip-sidebar-menu-sub>` : ''} </uip-sidebar-menu-item> `, )} </uip-sidebar-menu> </uip-sidebar-group> </uip-sidebar-content> </uip-sidebar> ` } } customElements.get('uip-sidebar-04') || customElements.define('uip-sidebar-04', UipSidebar04) declare global { interface HTMLElementTagNameMap { 'uip-sidebar-04': UipSidebar04 } }
Raw manifest:https://uipkge.dev/r/lit/sidebar-04.json