Sidebar <mv-sidebar>

アプリのサイドバーです。ツールチップ付きのアニメーションするアイコンレール、保存される状態、グループ、折りたたみ可能な入れ子のセクション、カウンター、ワークスペースの切り替え、ユーザーメニュー、コンテナが狭いときにスライドアウトするパネル(dialog)、Ctrl/⌘ + B ショートカットを備えています。

カテゴリーブロック
タイプWeb Component(<mv-sidebar>)
ステータス安定版
同時にインストールされるものdialog, tooltip
Keywordssidebar, navigation, app-shell, drawer, rail, collapsible, layout

When to use

  • An app needs side navigation that collapses to an icon rail and remembers its state
  • Navigation has groups, nested sections, counters, a workspace switcher and a user menu
  • On narrow containers the navigation should slide out as a panel with a keyboard shortcut

Avoid when

  • A whole dashboard layout with header, KPIs and search is needed → use App Shell instead
  • The site is a public marketing site better served by a top bar → use Navbar instead

インストール

node scripts/add.mjs sidebar --out ./src/marvelous

Marvelous UI MCP サーバーを使う AI エージェント:install_components({ slugs: ["sidebar"], target_dir: "<absolute path>/src/marvelous", framework: "react" })。

コピーされるファイル(依存関係を含む):tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/motion.js, components/dialog/dialog.js, components/dialog/dialog.css, core/position.js, components/tooltip/tooltip.js, components/tooltip/tooltip.css, core/observe.js, components/sidebar/sidebar.js, components/sidebar/sidebar.css。

使い方

基本となるマークアップです。ここから属性、data-*、CSS 変数でカスタマイズしてください:

<div class="mv-sidebar-layout" data-variant="inset" id="sb-demo" style="height:640px;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);overflow:hidden">
  <mv-sidebar label="Main navigation" storage-key="mv-demo-sidebar">
    <div class="mv-sidebar-header">
      <mv-menu placement="bottom-start">
        <button class="mv-sidebar-item" data-size="lg" type="button">
          <span class="mv-sidebar-logo" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19V5l8 7 8-7v14"/></svg></span>
          <span class="mv-sidebar-label"><strong>Nova Studio</strong><small>Pro plan · 12 members</small></span>
          <mv-icon class="mv-sidebar-item-end" name="chevrons-up-down"></mv-icon>
        </button>
        <div data-content style="--mv-menu-width:15rem">
          <div class="mv-menu-label">Workspaces</div>
          <div role="group" data-name="workspace">
            <button role="menuitemradio" aria-checked="true" value="nova">Nova Studio <span class="mv-menu-shortcut">⌘1</span></button>
            <button role="menuitemradio" value="lumen">Lumen Labs <span class="mv-menu-shortcut">⌘2</span></button>
            <button role="menuitemradio" value="opal">Opal Coffee <span class="mv-menu-shortcut">⌘3</span></button>
          </div>
          <hr>
          <button role="menuitem" value="new-workspace"><mv-icon name="plus"></mv-icon>New workspace</button>
        </div>
      </mv-menu>
    </div>

    <nav class="mv-sidebar-content" aria-label="Sections">
      <div class="mv-sidebar-group">
        <h2 class="mv-sidebar-group-label">Platform</h2>
        <ul class="mv-sidebar-menu">
          <li><a class="mv-sidebar-item" href="#sb-demo"><mv-icon name="dashboard"></mv-icon><span class="mv-sidebar-label">Dashboard</span></a></li>
          <li><a class="mv-sidebar-item" href="#sb-demo"><mv-icon name="inbox"></mv-icon><span class="mv-sidebar-label">Inbox</span><span class="mv-sidebar-badge" data-variant="accent">4<span class="mv-sr-only"> unread</span></span></a></li>
          <li class="mv-sidebar-sub">
            <button class="mv-sidebar-item"><mv-icon name="folder"></mv-icon><span class="mv-sidebar-label">Projects</span><span class="mv-sidebar-badge">12</span></button>
            <ul class="mv-sidebar-submenu">
              <li><a class="mv-sidebar-subitem" href="#sb-demo" aria-current="page">Customer portal redesign</a></li>
              <li><a class="mv-sidebar-subitem" href="#sb-demo">Mobile app</a></li>
              <li><a class="mv-sidebar-subitem" href="#sb-demo">Opal rebrand</a></li>
              <li><a class="mv-sidebar-subitem" href="#sb-demo">Archived</a></li>
            </ul>
          </li>
          <li><a class="mv-sidebar-item" href="#sb-demo"><mv-icon name="calendar"></mv-icon><span class="mv-sidebar-label">Calendar</span><span class="mv-sidebar-badge" data-variant="danger">2<span class="mv-sr-only"> conflicts</span></span></a></li>
          <li class="mv-sidebar-sub">
            <button class="mv-sidebar-item"><mv-icon name="chart"></mv-icon><span class="mv-sidebar-label">Reports</span></button>
            <ul class="mv-sidebar-submenu">
              <li><a class="mv-sidebar-subitem" href="#sb-demo">Sales</a></li>
              <li><a class="mv-sidebar-subitem" href="#sb-demo">Traffic</a></li>
              <li><a class="mv-sidebar-subitem" href="#sb-demo">Retention</a></li>
            </ul>
          </li>
        </ul>
      </div>

      <div class="mv-sidebar-group">
        <h2 class="mv-sidebar-group-label">Team</h2>
        <ul class="mv-sidebar-menu">
          <li><a class="mv-sidebar-item" href="#sb-demo"><mv-icon name="users"></mv-icon><span class="mv-sidebar-label">Members</span></a></li>
          <li><a class="mv-sidebar-item" href="#sb-demo"><mv-icon name="file"></mv-icon><span class="mv-sidebar-label">Documents</span></a></li>
        </ul>
      </div>

      <div class="mv-sidebar-group" data-push>
        <ul class="mv-sidebar-menu">
          <li><a class="mv-sidebar-item" href="#sb-demo"><mv-icon name="help"></mv-icon><span class="mv-sidebar-label">Help &amp; support</span></a></li>
          <li><a class="mv-sidebar-item" href="#sb-demo"><mv-icon name="settings"></mv-icon><span class="mv-sidebar-label">Settings</span></a></li>
        </ul>
      </div>
    </nav>

    <div class="mv-sidebar-footer">
      <mv-menu placement="top-start">
        <button class="mv-sidebar-item" data-size="lg" type="button">
          <span class="mv-avatar" data-variant="tinted" style="--mv-avatar-hue:200" aria-hidden="true"><span class="mv-avatar-fallback">MP</span></span>
          <span class="mv-sidebar-label"><strong>Maya Patel</strong><small>[email protected]</small></span>
          <mv-icon class="mv-sidebar-item-end" name="chevrons-up-down"></mv-icon>
        </button>
        <div data-content style="--mv-menu-width:15rem">
          <div class="mv-menu-label">My account</div>
          <button role="menuitem" value="profile"><mv-icon name="user"></mv-icon>Profile <span class="mv-menu-shortcut">⇧⌘P</span></button>
          <button role="menuitem" value="billing"><mv-icon name="credit-card"></mv-icon>Billing</button>
          <button role="menuitem" value="notifications"><mv-icon name="bell"></mv-icon>Notifications</button>
          <hr>
          <button role="menuitem" value="sign-out"><mv-icon name="log-out"></mv-icon>Log out</button>
        </div>
      </mv-menu>
    </div>
  </mv-sidebar>

  <main class="mv-sidebar-inset" aria-label="Content">
    <style>@container mv-sidebar-inset (width < 34rem) { #sb-demo .sb-demo-hint { display: none } }</style>
    <header style="display:flex;align-items:center;gap:.5rem;height:3.5rem;padding:0 1rem;border-bottom:1px solid var(--mv-border);flex-shrink:0">
      <button class="mv-button" data-variant="ghost" data-size="icon" data-mv-sidebar-toggle aria-label="Show or hide the sidebar" title="Sidebar (Ctrl B)">
        <mv-icon name="sidebar"></mv-icon>
      </button>
      <div class="mv-separator" role="separator" aria-orientation="vertical" data-orientation="vertical" style="height:1rem;min-height:1rem;align-self:center"></div>
      <nav class="mv-breadcrumb" aria-label="Breadcrumb" data-size="sm" style="min-width:0">
        <ol>
          <li><a href="#sb-demo">Projects</a></li>
          <li><span aria-current="page" class="mv-breadcrumb-truncate">Customer portal redesign</span></li>
        </ol>
      </nav>
      <span style="margin-inline-start:auto;font-size:.75rem;color:var(--mv-fg-muted);white-space:nowrap" class="sb-demo-hint">Collapse: <kbd class="mv-kbd-group"><kbd class="mv-kbd" data-size="sm">Ctrl</kbd><kbd class="mv-kbd" data-size="sm">B</kbd></kbd></span>
    </header>
    <div style="display:grid;gap:1rem;padding:1.25rem;align-content:start">
      <div>
        <h1 style="margin:0;font-size:1.25rem;font-weight:600;letter-spacing:-.01em">Customer portal redesign</h1>
        <p style="margin:.25rem 0 0;color:var(--mv-fg-muted);font-size:.875rem">Launching Oct 14 · 18 of 24 tasks done</p>
      </div>
      <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));gap:.75rem">
        <article class="mv-card" data-size="sm">
          <div class="mv-card-content" style="display:grid;gap:.5rem">
            <span style="font-size:.8125rem;color:var(--mv-fg-muted)">Progress</span>
            <strong style="font-size:1.5rem;font-weight:600">75%</strong>
            <progress class="mv-progress" data-size="sm" max="100" value="75" aria-label="Project progress"></progress>
          </div>
        </article>
        <article class="mv-card" data-size="sm">
          <div class="mv-card-content" style="display:grid;gap:.5rem">
            <span style="font-size:.8125rem;color:var(--mv-fg-muted)">Budget used</span>
            <strong style="font-size:1.5rem;font-weight:600">$31,400</strong>
            <progress class="mv-progress" data-size="sm" data-color="warning" max="100" value="84" aria-label="Budget used"></progress>
          </div>
        </article>
        <article class="mv-card" data-size="sm">
          <div class="mv-card-content" style="display:grid;gap:.5rem">
            <span style="font-size:.8125rem;color:var(--mv-fg-muted)">Reviews to schedule</span>
            <strong style="font-size:1.5rem;font-weight:600">2</strong>
            <span style="font-size:.75rem;color:var(--mv-fg-muted)">Product design · Accessibility</span>
          </div>
        </article>
      </div>
      <div style="min-height:14rem;border:1px dashed var(--mv-border-strong);border-radius:var(--mv-radius-lg);display:grid;place-items:center;color:var(--mv-fg-subtle);font-size:.8125rem;text-align:center;padding:1rem">Page content: the sidebar collapses to an icon rail and becomes a slide-out panel below 768px.</div>
    </div>
  </main>
</div>

API

Attributes

NameタイプDefaultDescription
collapsedbooleanCollapsed state (reflected, persisted when storage-key is set).
collapsibleicon | offcanvas | noneiconicon: icon rail; offcanvas: hides completely; none: fixed.
storage-keystringlocalStorage key used to remember the state between visits.
labelstringSidebarAccessible name of the region and the mobile panel.
breakpointnumber (px)768Width of the .mv-sidebar-layout container below which the sidebar becomes a slide-out panel.
hotkeystringbKey combined with Ctrl/⌘ to toggle; empty to disable. Ignored while typing in a field or when another modal dialog is open.
data-stateexpanded | collapsedSet automatically (also data-sidebar on the layout).
data-mobilebooleanSet automatically in panel mode.

Properties

NameタイプDescription
stringsPartial<Record<string, string>>Overrides for the default text: expand, collapse (edge rail tooltip), close (mobile panel Close button). English defaults. Can be set before the element is defined.

Methods

NameDescription
toggle()Collapses/expands; in mobile mode, opens/closes the panel.
collapse() / expand()Forces the state.

Events

NameDescription
mv-toggledetail: { collapsed }.

Content structure

NameDescription
.mv-sidebar-header / -content / -footerRegions; -content scrolls (use a <nav aria-label>).
.mv-sidebar-group > .mv-sidebar-group-label + ul.mv-sidebar-menuTitled group (the list is named by its title). data-push on a group pushes it to the bottom.
a/button.mv-sidebar-itemItem: icon (<mv-icon name> or an inline <svg>) + .mv-sidebar-label (+ .mv-sidebar-badge). aria-current="page" for the current page. data-size="lg" for a switcher (logo/avatar + <strong>/<small>).
li.mv-sidebar-subCollapsible section: button.mv-sidebar-item + ul.mv-sidebar-submenu of a.mv-sidebar-subitem; data-open to open it (automatic when it contains the current page).
[data-mv-sidebar-toggle]Trigger button (inside the same .mv-sidebar-layout, or value = sidebar selector). aria-expanded, aria-controls and aria-keyshortcuts handled (an aria-keyshortcuts you set is kept).

CSS classes

NameDescription
mv-sidebar-layoutFlex container for sidebar + content; data-variant="inset": content as a floating card.
mv-sidebar-insetContent area (container query named mv-sidebar-inset).
mv-sidebar-logo / -badge / -item-end / -separatorLogo tile, counter (data-variant="accent | danger | warning | success"; the collapsed rail's dot takes the same tone), trailing icon (<mv-icon> or <svg>), divider.
mv-sidebar-hide-collapsedHides an element in rail mode.

CSS variables

NameDefaultDescription
--mv-sidebar-width16remExpanded width.
--mv-sidebar-width-icon3remRail width.
--mv-sidebar-bgvar(--mv-bg-subtle)Background.
--mv-sidebar-highlightHover background.

Accessibility

Named region; lists named by their group title; aria-current="page"; collapsible sections as <button aria-expanded aria-controls> (reported collapsed while the icon rail hides them). In rail mode, labels stay in the DOM (accessible names intact) and a tooltip appears on hover and keyboard focus; Escape dismisses it. Trigger with aria-expanded and aria-keyshortcuts. Mobile mode: modal dialog (focus trap, Escape, inert background, focus returned to the trigger) with a Close button. Ctrl/⌘ + B, never taken from a text field. Forced colors: focus, current page and counters drawn with system colors.

このページは AI で翻訳されています。翻訳の問題を報告