{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "sidebar-07",
  "title": "Toolbar Action Sidebar",
  "type": "registry:block",
  "description": "App sidebar with a bottom action bar -- workspace pill, ⌘K search, grouped nav with section labels (Dashboard / Management / Content), badge counts, user pill above an icon toolbar (Settings, Help, Notifications, Command, Log out). Built on sidebar-01.",
  "categories": [
    "layout",
    "sidebar"
  ],
  "files": [
    {
      "path": "packages/elements-lit/src/blocks/sidebar-07/sidebar-07.ts",
      "content": "import { LitElement, css, html } from 'lit'\nimport {\n  Bell,\n  ChartBar,\n  ChevronsUpDown,\n  Command,\n  CreditCard,\n  FileText,\n  HelpCircle,\n  LineChart,\n  Mail,\n  Moon,\n  Package,\n  Plus,\n  Search,\n  Settings as SettingsIcon,\n  ShoppingCart,\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/input/input'\nimport type { UipInput } from '../../components/input/input'\nimport '../../components/sidebar/sidebar'\nimport type { UipSidebarProvider } from '../../components/sidebar/sidebar'\n\nfunction isDarkActive(): boolean {\n  return document.documentElement.classList.contains('dark')\n}\n\nfunction setDark(dark: boolean) {\n  document.documentElement.classList.toggle('dark', dark)\n  try {\n    localStorage.setItem('uipkge-theme', dark ? 'dark' : 'light')\n  } catch {\n    // ignore\n  }\n}\n\n// App sidebar with a bottom action bar. Workspace pill + search at the top,\n// three grouped nav sections, user pill above an icon toolbar (Settings,\n// Help, Notifications, Command palette, theme toggle) anchored at the very\n// bottom. Every row is spelled out inline so you can edit in place.\n\n/**\n * <uip-sidebar-07> — the registry Sidebar07 block as a web component.\n *\n * Class strings are React's verbatim. The footer toolbar follows the\n * provider's state (React's useSidebar `state`); the block re-renders when\n * the provider's `open-change` fires. The search field is <uip-input> with\n * `prefix`/`suffix` slots (React's SidebarInput prefix/suffix props). The\n * theme toggle writes the `dark` class on documentElement directly (the\n * `next-themes` dependency is not ported). Deviations: the toolbar's last\n * button is React's SidebarTrigger (collapse toggle) — ported as\n * <uip-sidebar-trigger>, which carries its own trigger styling on top of\n * React's row classes. No props, no events: edit the markup in place.\n */\nexport class UipSidebar07 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    isDark: { state: true },\n    query: { state: true },\n  }\n\n  private isDark = false\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-07')\n    this.isDark = isDarkActive()\n    // Re-render when the provider opens/closes or the viewport crosses the\n    // mobile breakpoint (React's useSidebar re-render).\n    this.addEventListener('open-change', this.rerender)\n    this.media = window.matchMedia('(max-width: 768px)')\n    this.media.addEventListener('change', this.rerender)\n  }\n\n  disconnectedCallback() {\n    super.disconnectedCallback()\n    this.removeEventListener('open-change', this.rerender)\n    this.media?.removeEventListener('change', this.rerender)\n  }\n\n  private rerender = () => this.requestUpdate()\n\n  private toolbarButton(label: string, iconName: string, iconNode: typeof SettingsIcon, onClick?: () => void) {\n    return html`\n      <button\n        type=\"button\"\n        aria-label=${label}\n        class=\"text-muted-foreground hover:bg-sidebar-accent hover:text-foreground flex aspect-square size-8 items-center justify-center rounded-md transition-colors\"\n        @click=${() => onClick?.()}\n      >\n        ${icon(iconNode, iconName, 'size-4')}\n      </button>\n    `\n  }\n\n  render() {\n    const expanded = (this.closest('uip-sidebar-provider') as UipSidebarProvider | null)?.state !== 'collapsed'\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-semibold\">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>K\n              </kbd>\n            </uip-input>\n          </div>\n        </uip-sidebar-header>\n\n        <uip-sidebar-content>\n          <uip-sidebar-group>\n            <uip-sidebar-group-label>Dashboard</uip-sidebar-group-label>\n            <uip-sidebar-group-content>\n              <uip-sidebar-menu>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button\n                    is-active\n                    tooltip=\"Analytics\"\n                    class=\"[&[is-active]::part(base)]:!bg-success/20 [&[is-active]::part(base)]:!text-foreground\"\n                  >\n                    ${icon(ChartBar, 'chart-bar', 'size-4')} <span>Analytics</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Performance\">\n                    ${icon(LineChart, 'chart-line', 'size-4')} <span>Performance</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>Management</uip-sidebar-group-label>\n            <uip-sidebar-group-content>\n              <uip-sidebar-menu>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Products\">\n                    ${icon(Package, 'package', 'size-4')} <span>Products</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Orders\">\n                    ${icon(ShoppingCart, 'shopping-cart', 'size-4')} <span>Orders</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Subscribers\">\n                    ${icon(Users, 'users', 'size-4')} <span>Subscribers</span>\n                  </uip-sidebar-menu-button>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Transactions\">\n                    ${icon(CreditCard, 'credit-card', 'size-4')} <span>Transactions</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>Content</uip-sidebar-group-label>\n            <uip-sidebar-group-action aria-label=\"Add content\">\n              ${icon(Plus, 'plus', 'size-4')}\n            </uip-sidebar-group-action>\n            <uip-sidebar-group-content>\n              <uip-sidebar-menu>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Posts\">\n                    ${icon(FileText, 'file-text', 'size-4')} <span>Posts</span>\n                  </uip-sidebar-menu-button>\n                  <uip-sidebar-menu-badge class=\"[&::part(base)]:bg-destructive [&::part(base)]:text-white\">10</uip-sidebar-menu-badge>\n                </uip-sidebar-menu-item>\n                <uip-sidebar-menu-item>\n                  <uip-sidebar-menu-button tooltip=\"Pages\">\n                    ${icon(Mail, 'mail', 'size-4')} <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        </uip-sidebar-content>\n\n        <uip-sidebar-footer>\n          <uip-sidebar-menu>\n            <uip-sidebar-menu-item>\n              <uip-sidebar-menu-button size=\"lg\" class=\"group-data-[collapsible=icon]:!justify-center\">\n                <uip-avatar class=\"size-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\">SW</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\">Sarah Wilson</span>\n                  <span class=\"text-muted-foreground truncate text-xs\">Admin Account</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-sidebar-menu-item>\n          </uip-sidebar-menu>\n\n          ${expanded\n            ? html`\n                <uip-sidebar-separator class=\"[&::part(base)]:my-1\"></uip-sidebar-separator>\n                <div class=\"flex items-center justify-between px-1 pb-1\">\n                  ${this.toolbarButton('Settings', 'settings', SettingsIcon)}\n                  ${this.toolbarButton('Help', 'circle-question-mark', HelpCircle)}\n                  ${this.toolbarButton('Notifications', 'bell', Bell)}\n                  ${this.toolbarButton('Command palette', 'command', Command)}\n                  <button\n                    type=\"button\"\n                    aria-label=${this.isDark ? 'Switch to light theme' : 'Switch to dark theme'}\n                    class=\"text-muted-foreground hover:bg-sidebar-accent hover:text-foreground flex aspect-square size-8 items-center justify-center rounded-md transition-colors\"\n                    @click=${() => {\n                      this.isDark = !this.isDark\n                      setDark(this.isDark)\n                    }}\n                  >\n                    ${this.isDark ? icon(Sun, 'sun', 'size-4') : icon(Moon, 'moon', 'size-4')}\n                  </button>\n                  <uip-sidebar-trigger class=\"text-muted-foreground hover:bg-sidebar-accent hover:text-foreground size-8 rounded-md\"></uip-sidebar-trigger>\n                </div>\n              `\n            : html`\n                <div class=\"flex items-center justify-center pb-1\">\n                  <uip-sidebar-trigger class=\"text-muted-foreground hover:bg-sidebar-accent hover:text-foreground size-8 rounded-md\"></uip-sidebar-trigger>\n                </div>\n              `}\n        </uip-sidebar-footer>\n\n        <uip-sidebar-rail></uip-sidebar-rail>\n      </uip-sidebar>\n    `\n  }\n}\n\ncustomElements.get('uip-sidebar-07') || customElements.define('uip-sidebar-07', UipSidebar07)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-sidebar-07': UipSidebar07\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/blocks/sidebar-07/sidebar-07.ts"
    }
  ],
  "dependencies": [
    "lit",
    "lucide"
  ],
  "registryDependencies": [
    "https://uipkge.dev/r/lit/avatar.json",
    "https://uipkge.dev/r/lit/input.json",
    "https://uipkge.dev/r/lit/lit-core.json",
    "https://uipkge.dev/r/lit/sidebar.json"
  ]
}
