{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "sidebar-01",
  "title": "Icon Rail Sidebar",
  "type": "registry:block",
  "description": "Collapsible icon-rail app sidebar with brand block, two grouped nav sections, and a user dropdown footer. Pure markup, no props -- edit Sidebar01.tsx to change routes and NavUser.tsx to wire your auth session. Pair with SidebarProvider + SidebarInset for the full admin shell.",
  "categories": [
    "layout",
    "sidebar"
  ],
  "files": [
    {
      "path": "packages/elements-lit/src/blocks/sidebar-01/sidebar-01.ts",
      "content": "import { LitElement, css, html } from 'lit'\nimport {\n  BadgeCheck,\n  BarChart3,\n  BookOpen,\n  ChevronsUpDown,\n  FileText,\n  Files,\n  History,\n  LayoutDashboard,\n  LogOut,\n  Monitor,\n  Moon,\n  Palette,\n  Settings,\n  Sun,\n  Table as TableIcon,\n} from 'lucide'\nimport { tailwind } from '../../lib/styles'\nimport { ThemeController } from '../../lib/theme'\nimport { icon } from '../../lib/icon'\n// Side-effect imports: register the composed elements for standalone use\n// (consumers who install only this block still get working primitives).\nimport '../../components/avatar/avatar'\nimport '../../components/dropdown-menu/dropdown-menu'\nimport '../../components/sidebar/sidebar'\n\ntype ThemeValue = 'light' | 'dark' | 'system'\n\nfunction getTheme(): ThemeValue {\n  const stored = (() => {\n    try {\n      return localStorage.getItem('uipkge-theme')\n    } catch {\n      return null\n    }\n  })()\n  if (stored === 'light' || stored === 'dark' || stored === 'system') return stored\n  return document.documentElement.classList.contains('dark') ? 'dark' : 'light'\n}\n\nfunction setTheme(value: ThemeValue) {\n  try {\n    localStorage.setItem('uipkge-theme', value)\n  } catch {\n    // ignore\n  }\n  const dark = value === 'dark' || (value === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches)\n  document.documentElement.classList.toggle('dark', dark)\n}\n\nfunction handleLogout() {\n  // TODO: call your /api/auth/logout endpoint, then redirect.\n  console.warn('NavUser: wire handleLogout() to your auth backend')\n}\n\n// Edit the rows below to change brand, navigation, and the user dropdown.\n// Every menu item is spelled out below -- copy, remove, or rename rows directly.\n\n/**\n * <uip-sidebar-01> — the registry Sidebar01 block as a web component\n * (NavUser inlined — one block, one install unit).\n *\n * Class strings are React's Sidebar01 + NavUser verbatim. The user details\n * are inlined (wire them to your auth session in place). The theme submenu\n * writes the `dark` class on documentElement directly (the `next-themes`\n * dependency is not ported — same visual result, persisted to localStorage).\n * No props, no events: edit the markup in place.\n */\nexport class UipSidebar01 extends LitElement {\n  static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }\n  // :host display can't be a utility class (the host has no template of its own).\n  static styles = [tailwind, css`:host { display: block; }`]\n\n  static properties = {\n    theme: { state: true },\n  }\n\n  private theme: ThemeValue = 'light'\n\n  constructor() {\n    super()\n    new ThemeController(this)\n  }\n\n  connectedCallback() {\n    super.connectedCallback()\n    this.setAttribute('data-uipkge', '')\n    this.setAttribute('data-slot', 'sidebar-01')\n    this.theme = getTheme()\n  }\n\n  render() {\n    return html`\n      <uip-sidebar collapsible=\"icon\">\n        <uip-sidebar-header>\n          <uip-sidebar-menu>\n            <uip-sidebar-menu-item>\n              <uip-sidebar-menu-button size=\"lg\" tooltip=\"uipkge\" class=\"group-data-[collapsible=icon]:!justify-center\">\n                <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\">\n                  <svg viewBox=\"0 0 24 24\" class=\"size-4 group-data-[collapsible=icon]:size-3.5\" fill=\"currentColor\" aria-hidden=\"true\">\n                    <rect x=\"2\" y=\"2\" width=\"9\" height=\"9\" rx=\"1.5\" />\n                    <rect x=\"13\" y=\"2\" width=\"9\" height=\"9\" rx=\"1.5\" opacity=\"0.55\" />\n                    <rect x=\"2\" y=\"13\" width=\"9\" height=\"9\" rx=\"1.5\" opacity=\"0.55\" />\n                    <rect x=\"13\" y=\"13\" width=\"9\" height=\"9\" rx=\"1.5\" />\n                  </svg>\n                </div>\n                <div class=\"grid flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden\">\n                  <span class=\"font-display truncate font-bold\">uipkge</span>\n                  <span class=\"text-muted-foreground truncate text-xs\">uipkge.dev</span>\n                </div>\n              </uip-sidebar-menu-button>\n            </uip-sidebar-menu-item>\n          </uip-sidebar-menu>\n        </uip-sidebar-header>\n\n        <uip-sidebar-content>\n          <uip-sidebar-group>\n            <uip-sidebar-group-label>Workspace</uip-sidebar-group-label>\n            <uip-sidebar-group-content>\n              <uip-sidebar-menu>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button is-active tooltip=\"Dashboard\">\n                    ${icon(LayoutDashboard, 'layout-dashboard')} <span>Dashboard</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Data tables\">\n                    ${icon(TableIcon, 'table')} <span>Data tables</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Forms\">\n                    ${icon(FileText, 'file-text')} <span>Forms</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Charts\">\n                    ${icon(BarChart3, 'chart-column')} <span>Charts</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Pages\">\n                    ${icon(Files, 'files')} <span>Pages</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n              </uip-sidebar-menu>\n            </uip-sidebar-group-content>\n          </uip-sidebar-group>\n\n          <uip-sidebar-group>\n            <uip-sidebar-group-label>Resources</uip-sidebar-group-label>\n            <uip-sidebar-group-content>\n              <uip-sidebar-menu>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Docs\">\n                    ${icon(BookOpen, 'book-open')} <span>Docs</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Changelog\">\n                    ${icon(History, 'history')} <span>Changelog</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n              </uip-sidebar-menu>\n            </uip-sidebar-group-content>\n          </uip-sidebar-group>\n        </uip-sidebar-content>\n\n        <uip-sidebar-footer>\n          <uip-sidebar-menu>\n            <uip-sidebar-menu-item>\n              <uip-dropdown-menu class=\"[&::part(content)]:min-w-56 [&::part(content)]:rounded-lg\">\n                <uip-sidebar-menu-button\n                  slot=\"trigger\"\n                  size=\"lg\"\n                  class=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground group-data-[collapsible=icon]:!justify-center\"\n                >\n                  <uip-avatar class=\"h-8 w-8 shrink-0 rounded-lg group-data-[collapsible=icon]:size-6\">\n                    <uip-avatar-fallback class=\"rounded-lg text-xs\">TU</uip-avatar-fallback>\n                  </uip-avatar>\n                  <div class=\"grid flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden\">\n                    <span class=\"truncate font-medium\">Test User</span>\n                    <span class=\"truncate text-xs\">you@example.com</span>\n                  </div>\n                  ${icon(ChevronsUpDown, 'chevrons-up-down', 'ml-auto size-4 group-data-[collapsible=icon]:hidden')}\n                </uip-sidebar-menu-button>\n                <uip-dropdown-menu-content side=\"right\" align=\"end\" side-offset=\"4\">\n                  <uip-dropdown-menu-label>\n                    <div class=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n                      <uip-avatar class=\"h-8 w-8 rounded-lg\">\n                        <uip-avatar-fallback class=\"rounded-lg\">TU</uip-avatar-fallback>\n                      </uip-avatar>\n                      <div class=\"grid flex-1 text-left text-sm leading-tight\">\n                        <span class=\"truncate font-semibold\">Test User</span>\n                        <span class=\"truncate text-xs\">you@example.com</span>\n                      </div>\n                    </div>\n                  </uip-dropdown-menu-label>\n                  <uip-dropdown-menu-separator></uip-dropdown-menu-separator>\n                  <uip-dropdown-menu-group>\n                    <uip-dropdown-menu-item>${icon(BadgeCheck, 'badge-check')} Profile</uip-dropdown-menu-item>\n                    <uip-dropdown-menu-item>${icon(Settings, 'settings')} Settings</uip-dropdown-menu-item>\n                  </uip-dropdown-menu-group>\n                  <uip-dropdown-menu-separator></uip-dropdown-menu-separator>\n                  <uip-dropdown-menu-sub>\n                    <uip-dropdown-menu-sub-trigger>\n                      ${icon(Palette, 'palette')} Theme\n                      <span class=\"text-muted-foreground ml-auto text-xs capitalize\">${this.theme}</span>\n                    </uip-dropdown-menu-sub-trigger>\n                    <uip-dropdown-menu-sub-content>\n                      <uip-dropdown-menu-radio-group\n                        value=${this.theme}\n                        @value-change=${(e: CustomEvent<{ value: string }>) => {\n                          this.theme = e.detail.value as ThemeValue\n                          setTheme(this.theme)\n                        }}\n                      >\n                        <uip-dropdown-menu-radio-item value=\"light\">${icon(Sun, 'sun')} Light</uip-dropdown-menu-radio-item>\n                        <uip-dropdown-menu-radio-item value=\"dark\">${icon(Moon, 'moon')} Dark</uip-dropdown-menu-radio-item>\n                        <uip-dropdown-menu-radio-item value=\"system\">${icon(Monitor, 'monitor')} System</uip-dropdown-menu-radio-item>\n                      </uip-dropdown-menu-radio-group>\n                    </uip-dropdown-menu-sub-content>\n                  </uip-dropdown-menu-sub>\n                  <uip-dropdown-menu-separator></uip-dropdown-menu-separator>\n                  <uip-dropdown-menu-item @select=${handleLogout}>${icon(LogOut, 'log-out')} Log out</uip-dropdown-menu-item>\n                </uip-dropdown-menu-content>\n              </uip-dropdown-menu>\n            </uip-sidebar-menu-item>\n          </uip-sidebar-menu>\n        </uip-sidebar-footer>\n\n        <uip-sidebar-rail></uip-sidebar-rail>\n      </uip-sidebar>\n    `\n  }\n}\n\ncustomElements.get('uip-sidebar-01') || customElements.define('uip-sidebar-01', UipSidebar01)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-sidebar-01': UipSidebar01\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/blocks/sidebar-01/sidebar-01.ts"
    }
  ],
  "dependencies": [
    "lit",
    "lucide"
  ],
  "registryDependencies": [
    "https://uipkge.dev/r/lit/avatar.json",
    "https://uipkge.dev/r/lit/dropdown-menu.json",
    "https://uipkge.dev/r/lit/lit-core.json",
    "https://uipkge.dev/r/lit/sidebar.json"
  ]
}
