Menu

Change language

GitHub repo

Floating Inset Sidebar

blocklayout

Floating 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

$npx shadcn@latest add https://uipkge.dev/r/lit/sidebar-04.json
Manifest:https://uipkge.dev/r/lit/sidebar-04.jsonInstalls to:src/uip/blocks/sidebar-04/

Variants

Loading interactive previews…

Schema

Type aliases exported from this item's source. Use these to shape the data you pass in.

NavChild
interface NavChild {
  title: string
  url: string
  isActive?: boolean
}
NavItem
interface NavItem {
  title: string
  url: string
  isActive?: boolean
  items: NavChild[]
}
HTMLElementTagNameMap
interface HTMLElementTagNameMap {
    'uip-sidebar-04': UipSidebar04
  }
}

npm dependencies

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