{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "sidebar-06",
  "title": "Starred Project Sidebar",
  "type": "registry:block",
  "description": "Colorful, customised app sidebar -- branded project tiles with star favorites, badge counts, team avatars with status dots, and a user pill footer. Inline search input with ⌘F shortcut. Modeled on a HRMS workspace shell.",
  "categories": [
    "layout",
    "sidebar"
  ],
  "files": [
    {
      "path": "packages/elements-lit/src/blocks/sidebar-06/sidebar-06.ts",
      "content": "import { LitElement, css, html } from 'lit'\nimport {\n  Briefcase,\n  Calendar,\n  ChartLine,\n  ChevronsUpDown,\n  ClipboardList,\n  Folder,\n  GraduationCap,\n  HeartPulse,\n  HelpCircle,\n  Inbox,\n  LayoutDashboard,\n  Monitor,\n  Moon,\n  Palette,\n  Search,\n  Send,\n  Settings as SettingsIcon,\n  Star,\n  Sun,\n  Users,\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/input/input'\nimport type { UipInput } from '../../components/input/input'\nimport '../../components/sidebar/sidebar'\nimport type { UipSidebarProvider } from '../../components/sidebar/sidebar'\n\ntype ThemeValue = 'light' | 'dark' | 'system'\n\nfunction getTheme(): ThemeValue {\n  try {\n    const stored = localStorage.getItem('uipkge-theme')\n    if (stored === 'light' || stored === 'dark' || stored === 'system') return stored\n  } catch {\n    // ignore\n  }\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\n// Colorful, customised HRMS-style sidebar -- branded project tiles, badges,\n// status dots, and a user pill footer. Every row is spelled out inline so\n// you can swap colors and labels in place.\n\n/**\n * <uip-sidebar-06> — the registry Sidebar06 block as a web component.\n *\n * Class strings are React's verbatim. The footer dropdown's `side` follows\n * the provider's isMobile (React's useSidebar); the theme submenu writes\n * the `dark` class on documentElement directly (the `next-themes`\n * dependency is not ported — same visual result, persisted to\n * localStorage). The search field is <uip-input> with `prefix`/`suffix`\n * slots (React's SidebarInput prefix/suffix props). No props, no events:\n * edit the markup in place.\n */\nexport class UipSidebar06 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    query: { state: true },\n  }\n\n  private theme: ThemeValue = 'light'\n  private query = ''\n  private media?: MediaQueryList\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-06')\n    this.theme = getTheme()\n    // Re-render when the viewport crosses the mobile breakpoint so the\n    // footer dropdown side follows isMobile (React's useSidebar re-render).\n    this.media = window.matchMedia('(max-width: 768px)')\n    this.media.addEventListener('change', this.rerender)\n  }\n\n  disconnectedCallback() {\n    super.disconnectedCallback()\n    this.media?.removeEventListener('change', this.rerender)\n  }\n\n  private rerender = () => this.requestUpdate()\n\n  render() {\n    const isMobile = (this.closest('uip-sidebar-provider') as UipSidebarProvider | null)?.isMobile ?? false\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 shadow-sm 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\n          <div class=\"px-1 pt-1 group-data-[collapsible=icon]:hidden\">\n            <uip-input\n              type=\"text\"\n              placeholder=\"Search...\"\n              allow-clear\n              class=\"[&::part(control)]:bg-background [&::part(control)]:h-8 [&::part(control)]:shadow-none\"\n              .value=${this.query}\n              @input=${(e: Event) => {\n                this.query = (e.target as UipInput).value\n              }}\n            >\n              <span slot=\"prefix\">${icon(Search, 'search', 'size-3.5')}</span>\n              <kbd slot=\"suffix\" class=\"bg-muted text-muted-foreground pointer-events-none inline-flex h-5 items-center gap-0.5 rounded border px-1 font-mono text-xs font-medium select-none\">\n                <span>&#8984;</span>F\n              </kbd>\n            </uip-input>\n          </div>\n        </uip-sidebar-header>\n\n        <uip-sidebar-content>\n          <uip-sidebar-group>\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', 'size-4')} <span>Dashboard</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Employees\">\n                    ${icon(Users, 'users', 'size-4')} <span>Employees</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Clients\">\n                    ${icon(Briefcase, 'briefcase', 'size-4')} <span>Clients</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Projects\">\n                    ${icon(Folder, 'folder', 'size-4')} <span>Projects</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-separator></uip-sidebar-separator>\n\n          <uip-sidebar-group>\n            <uip-sidebar-group-label>Workforce</uip-sidebar-group-label>\n            <uip-sidebar-group-content>\n              <uip-sidebar-menu>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Calendar\">\n                    ${icon(Calendar, 'calendar', 'size-4')} <span>Calendar</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Attendance\">\n                    ${icon(ClipboardList, 'clipboard-list', 'size-4')} <span>Attendance</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Inbox\">\n                    ${icon(Inbox, 'inbox', 'size-4')} <span>Inbox</span>\n                  </uip-sidebar-menu-button>\n                  <uip-sidebar-menu-badge class=\"[&::part(base)]:bg-destructive [&::part(base)]:text-white\">6</uip-sidebar-menu-badge>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Analytics\">\n                    ${icon(ChartLine, 'chart-line', 'size-4')} <span>Analytics</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-separator></uip-sidebar-separator>\n\n          <uip-sidebar-group>\n            <uip-sidebar-group-label>Projects</uip-sidebar-group-label>\n            <uip-sidebar-group-content>\n              <uip-sidebar-menu>\n                ${[\n                  { tile: 'bg-chart-1', icon: Folder, iconName: 'folder', name: 'Shift Planner' },\n                  { tile: 'bg-chart-2', icon: GraduationCap, iconName: 'graduation-cap', name: 'Training Portal' },\n                  { tile: 'bg-chart-3', icon: HeartPulse, iconName: 'heart-pulse', name: 'Performance Hub' },\n                  { tile: 'bg-chart-4', icon: ChartLine, iconName: 'chart-line', name: 'Expense Claims' },\n                ].map(\n                  (p) => html`\n                    <uip-sidebar-menu-item>\n                      <uip-sidebar-menu-button tooltip=${p.name}>\n                        <div class=${`${p.tile} flex aspect-square size-5 shrink-0 items-center justify-center rounded-md text-white`}>\n                          ${icon(p.icon, p.iconName, 'size-3')}\n                        </div>\n                        <span>${p.name}</span>\n                      </uip-sidebar-menu-button>\n                      <uip-sidebar-menu-badge class=\"[&::part(base)]:text-warning\">\n                        ${icon(Star, 'star', 'size-3.5 fill-current')}\n                      </uip-sidebar-menu-badge>\n                    </uip-sidebar-menu-item>\n                  `,\n                )}\n              </uip-sidebar-menu>\n            </uip-sidebar-group-content>\n          </uip-sidebar-group>\n\n          <uip-sidebar-separator></uip-sidebar-separator>\n\n          <uip-sidebar-group>\n            <uip-sidebar-group-label>My team</uip-sidebar-group-label>\n            <uip-sidebar-group-content>\n              <uip-sidebar-menu>\n                ${[\n                  { initials: 'OB', tile: 'bg-chart-1/15', name: 'Olivia Bennett', dot: 'bg-destructive' },\n                  { initials: 'DM', tile: 'bg-chart-2/15', name: 'Daniel Morgan', dot: 'bg-warning' },\n                  { initials: 'ER', tile: 'bg-chart-3/15', name: 'Ethan Reynolds', dot: 'bg-success' },\n                ].map(\n                  (person) => html`\n                    <uip-sidebar-menu-item>\n                      <uip-sidebar-menu-button tooltip=${person.name}>\n                        <uip-avatar class=\"size-5\">\n                          <uip-avatar-fallback class=${`${person.tile} text-foreground text-xs`}>${person.initials}</uip-avatar-fallback>\n                        </uip-avatar>\n                        <span>${person.name}</span>\n                      </uip-sidebar-menu-button>\n                      <uip-sidebar-menu-badge>\n                        <span class=${`${person.dot} size-1.5 rounded-full`}></span>\n                      </uip-sidebar-menu-badge>\n                    </uip-sidebar-menu-item>\n                  `,\n                )}\n              </uip-sidebar-menu>\n            </uip-sidebar-group-content>\n          </uip-sidebar-group>\n\n          <uip-sidebar-separator></uip-sidebar-separator>\n\n          <uip-sidebar-group>\n            <uip-sidebar-group-label>Administration</uip-sidebar-group-label>\n            <uip-sidebar-group-content>\n              <uip-sidebar-menu>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Settings\">\n                    ${icon(SettingsIcon, 'settings', 'size-4')} <span>Settings</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Help center\">\n                    ${icon(HelpCircle, 'circle-question-mark', 'size-4')} <span>Help center</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                  <div class=\"relative shrink-0\">\n                    <uip-avatar class=\"h-8 w-8 rounded-lg group-data-[collapsible=icon]:size-6\">\n                      <uip-avatar-fallback class=\"bg-sidebar-accent text-sidebar-accent-foreground rounded-lg text-xs\">JC</uip-avatar-fallback>\n                    </uip-avatar>\n                    <span class=\"bg-destructive ring-sidebar absolute -right-0.5 -bottom-0.5 size-2.5 rounded-full ring-2\"></span>\n                  </div>\n                  <div class=\"grid flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden\">\n                    <span class=\"truncate font-medium\">James Carter</span>\n                    <span class=\"text-muted-foreground truncate text-xs\">Admin</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=${isMobile ? 'bottom' : 'right'} align=\"end\" side-offset=\"4\">\n                  <uip-dropdown-menu-label>James Carter</uip-dropdown-menu-label>\n                  <uip-dropdown-menu-separator></uip-dropdown-menu-separator>\n                  <uip-dropdown-menu-item>${icon(Send, 'send', 'size-4')} Invite teammates</uip-dropdown-menu-item>\n                  <uip-dropdown-menu-item>${icon(SettingsIcon, 'settings', 'size-4')} Workspace settings</uip-dropdown-menu-item>\n                  <uip-dropdown-menu-separator></uip-dropdown-menu-separator>\n                  <uip-dropdown-menu-sub>\n                    <uip-dropdown-menu-sub-trigger>\n                      ${icon(Palette, 'palette', 'size-4')} 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', 'size-4')} Light</uip-dropdown-menu-radio-item>\n                        <uip-dropdown-menu-radio-item value=\"dark\">${icon(Moon, 'moon', 'size-4')} Dark</uip-dropdown-menu-radio-item>\n                        <uip-dropdown-menu-radio-item value=\"system\">${icon(Monitor, 'monitor', 'size-4')} 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-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-06') || customElements.define('uip-sidebar-06', UipSidebar06)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-sidebar-06': UipSidebar06\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/blocks/sidebar-06/sidebar-06.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/input.json",
    "https://uipkge.dev/r/lit/lit-core.json",
    "https://uipkge.dev/r/lit/sidebar.json"
  ]
}
