{
  "tag": "ed-side-menu",
  "kind": "component",
  "summary": "A preconfigured navigation sidebar that renders [ed-side-menu-item](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/side-menu-item) links as a WAI-ARIA Disclosure Navigation menu, with optional search filtering and super-tabs.",
  "status": "experimental",
  "level": "molecule",
  "since": "1.0",
  "docs": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/side-menu/",
  "usage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/side-menu/usage/",
  "playwright": "getByTestId('…')",
  "dependencies": [
    "ed-input",
    "ed-side-menu-item",
    "ed-side-menu-title"
  ],
  "use": [
    "The primary navigation for an application with several distinct areas or modules — permanently visible on desktop, while the mobile view serves it through the app shell's drawer",
    "Navigation grouped into up to three top-level sections, so navigation points for different workflows can be reached fast"
  ],
  "notFor": [
    {
      "when": "Top-level navigation laid out horizontally across the top of the screen",
      "instead": "[Header](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/header)"
    },
    {
      "when": "Jumping between sections within a single long scrolling page",
      "instead": "[Scrollspy](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/scrollspy)"
    },
    {
      "when": "Browsing or selecting rows of hierarchical data records",
      "instead": "[Tree](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/tree)"
    }
  ],
  "rules": [
    {
      "id": "side-menu/active-item",
      "rule": "Keep the active item unambiguously visible at all times — signaled by color and a geometric cue (a filled background, a left-border accent, or heavier weight), never color alone. Wire the current location so the built-in active indicator, which combines both, can show it, and never restyle it down to color alone.",
      "why": "A menu without its active highlight cannot answer \"Where am I?\". In eurodata's dense, data-heavy products this is the single most important orientation mechanism — described internally as \"survival-critical.\"",
      "check": "warning"
    },
    {
      "id": "side-menu/icon-and-label",
      "rule": "Give every top-level item both an icon and a plain-language text label, and never strip the menu down to an icon-only rail — icon-only navigation is never allowed. The slim variant is the labeled compact form, and [Rail Menu](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/rail-menu) is the step up only when you need its two panes (a rail of sections plus their page lists).",
      "check": "error"
    },
    {
      "id": "side-menu/fixed",
      "rule": "Keep the sidebar fixed on screen in the desktop view, so it stays reachable while the main content scrolls — never let the navigation scroll away with the page content. Inside the app shell, the navigation slot does that on its own.",
      "check": "error"
    },
    {
      "id": "side-menu/scroll-position",
      "rule": "Preserve the menu's scroll position across page loads in a multi-page application (e.g. with turbo.js or a manual restore), so the active item is still in view after every navigation — never let a full page load snap a long menu back to the top.",
      "why": "A user who just clicked deep in the list must find the highlight where they left it."
    },
    {
      "id": "side-menu/super-tabs",
      "rule": "Use the built-in super-tabs to split the navigation into up to 3 top-level sections, each with its own item list. Never push them beyond 3 sections — switch to [Rail Menu](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/rail-menu) instead, only on the UX team's call or when a fourth section is unavoidable.",
      "check": "error"
    },
    {
      "id": "side-menu/shallow-hierarchy",
      "rule": "Keep the hierarchy shallow — two levels is the norm, three at most, and only for genuinely complex products. Never nest deeper than three levels; reconsider the information architecture instead.",
      "check": "error"
    },
    {
      "id": "side-menu/groups",
      "rule": "Group related items under short, non-clickable headings and separate groups with dividers.",
      "check": "error"
    },
    {
      "id": "side-menu/no-hidden-items",
      "rule": "Show every navigation item directly, letting the sidebar scroll when there are many — never hide items behind a \"more\" or expand button. A scrollable sidebar is always preferable.",
      "check": "error"
    },
    {
      "id": "side-menu/search",
      "rule": "Add a search box when the structure is large or unfamiliar to new users."
    },
    {
      "id": "side-menu/pinned-groups",
      "rule": "Keep permanently relevant groups open, so their entry-point links never disappear."
    },
    {
      "id": "side-menu/density",
      "rule": "Pick a denser row height to fit more items, or a more spacious one when navigation is the main activity."
    },
    {
      "id": "side-menu/action-row",
      "rule": "Use a non-navigating action row for an in-sidebar action, such as opening a search dialog."
    },
    {
      "id": "side-menu/favorites",
      "rule": "Consider per-user favorites when different roles rely on very different parts of the product."
    },
    {
      "id": "side-menu/short-labels",
      "rule": "Keep labels short, concrete, and free of jargon.",
      "why": "A label that outgrows two lines is clamped with an ellipsis and readable in full only through the tooltip the item shows on hover or focus.",
      "check": "warning"
    },
    {
      "id": "side-menu/no-hover-only",
      "rule": "Never reveal labels or clickable areas only on hover.",
      "check": "warning"
    },
    {
      "id": "side-menu/way-back",
      "rule": "Never strand users in a detail view with no visible way back to the parent context."
    }
  ],
  "api": {
    "attributes": [
      {
        "name": "filter",
        "property": "filter",
        "type": "boolean",
        "default": "false",
        "description": "Shows a search input that filters items by label and description text."
      },
      {
        "name": "filter-placeholder",
        "property": "filterPlaceholder",
        "type": "string",
        "default": "''",
        "description": "Placeholder text for the search input. Defaults to a localized \"Search\"."
      },
      {
        "name": "hide-indent-guides",
        "property": "hideIndentGuides",
        "type": "boolean",
        "default": "false",
        "description": "Hides the indent guide lines between nested items. Reflected so the styling hook matches whether set via attribute or property."
      },
      {
        "name": "current",
        "property": "current",
        "type": "string",
        "default": "''",
        "description": "The `value` of the currently active item (values fall back to the item's `href`). Matched\nexactly — no URL normalization. Updated automatically when the user activates an item;\nset it (or call `setCurrent()`) to follow external navigation, e.g. after a route change."
      },
      {
        "name": "active-tab",
        "property": "activeTab",
        "type": "string",
        "default": "''",
        "description": "The currently active super-tab value. Defaults to the first tab."
      },
      {
        "name": "density",
        "property": "density",
        "type": "'compact' | 'default' | 'spacious'",
        "default": "'default'",
        "description": "Density of nav items.\n- `spacious` — relaxed rows (~52px), 24px start/end icons.\n- `default` — condensed rows (~40px), 16px start/end icons.\n- `compact` — minimal rows (`--ed-form-control-height`, ~32px), 16px start/end icons."
      },
      {
        "name": "variant",
        "property": "variant",
        "type": "'default' | 'slim'",
        "default": "'default'",
        "description": "Layout variant. `slim` renders an 80px-wide rail where each item stacks\nits icon above a centered label. In slim, the filter input, super-tab\nbar, description slots, end-slot badges, and nested children are\nsuppressed. The variant is orthogonal to `density` — when slim is\nactive, density is still propagated to items but slim CSS overrides\ndensity-specific row metrics."
      },
      {
        "name": "dir",
        "property": "dir",
        "type": "string"
      },
      {
        "name": "lang",
        "property": "lang",
        "type": "string"
      }
    ],
    "properties": [],
    "methods": [
      {
        "name": "setCurrent",
        "parameters": [
          {
            "name": "value",
            "type": "string"
          }
        ],
        "description": "Update `current` and synchronously reflect the active-state on items. Prefer this over\nassigning `current` directly when the highlight must move in the same frame as a route\nchange — direct assignment defers through Lit's async update cycle and will flash for one\npaint. Typical consumer: a Turbo/SPA `visit` hook. Programmatic writes never emit events."
      },
      {
        "name": "getPropertyDescriptor",
        "static": true,
        "parameters": [
          {
            "name": "name",
            "type": "PropertyKey"
          },
          {
            "name": "key",
            "type": "string | symbol"
          },
          {
            "name": "options",
            "type": "PropertyDeclaration"
          }
        ],
        "returns": "PropertyDescriptor | undefined",
        "description": "Wraps the accessor of reflected properties so they always hold a valid value, as a native\nreflected IDL attribute does (`button.type = undefined` reads `submit`):\n\n- A property that declares `useDefault` takes the first value set on an element for its\n  default. That value is its field initializer's: the constructor has finished before markup,\n  a framework or any other code can set anything. Every later `null` or `undefined` means what\n  a dropped prop means on a native element — the attribute is removed: with the attribute\n  there, it is removed and Lit's `useDefault` restores the default without writing it; without\n  one, the property is set to the default. A value set and cleared again before the element\n  updates still writes the default once, from the pending reflection.\n- A Boolean is coerced with `Boolean()`, so `undefined` is `false`.\n\nLit's `useDefault` keeps the initial default out of the DOM. Setting the default explicitly\nwrites it, as `button.type = 'submit'` writes `type`."
      }
    ],
    "events": [
      {
        "name": "ed-filter",
        "react": "onEdFilter",
        "type": "{ query: string }",
        "description": "Emitted when the search filter value changes."
      },
      {
        "name": "ed-super-tab-change",
        "react": "onEdSuperTabChange",
        "type": "{ tab: string }",
        "description": "Emitted when the active super-tab changes. Detail contains `{ tab: string }`."
      }
    ],
    "slots": [
      {
        "name": "",
        "description": "The default slot for `ed-side-menu-item` elements."
      },
      {
        "name": "footer",
        "description": "`ed-side-menu-item` elements pinned to the bottom edge, below the scrolling list. They take part in `current`, the filter, `density` and `variant` like the items in the default slot, and come last in the Tab order."
      },
      {
        "name": "super-tab",
        "description": "Tab definitions for the super-tab bar. Use plain elements with a `value` attribute, an icon element as first element child, and the label as text, e.g. `<span slot=\"super-tab\" value=\"reports\"><ed-icon name=\"bar_chart\"></ed-icon>Reports</span>`."
      }
    ],
    "cssProperties": [
      {
        "name": "--ed-side-menu-width",
        "default": "16.875rem",
        "description": "The width of the menu. `ed-app` also reads it as the fallback width of its navigation column when nothing measurable is slotted in."
      },
      {
        "name": "--ed-side-menu-background",
        "default": "var(--ed-color-surface-raised)",
        "description": "Side-menu background color."
      }
    ],
    "parts": [
      {
        "name": "base",
        "description": "The component's base wrapper."
      },
      {
        "name": "super-tabs",
        "description": "Container for the super-tab bar."
      },
      {
        "name": "super-tab",
        "description": "An individual super-tab button."
      },
      {
        "name": "filter",
        "description": "Container for the search input."
      },
      {
        "name": "filter-input",
        "description": "The search input element."
      },
      {
        "name": "tree-wrapper",
        "description": "Scrollable container around the navigation items."
      },
      {
        "name": "footer",
        "description": "Container around the footer slot, below the scrollable container."
      }
    ],
    "states": []
  },
  "import": "import '@eurodata/eurodata-ui/dist/components/side-menu/side-menu.js';",
  "react": {
    "component": "EdSideMenu",
    "import": "import EdSideMenu from '@eurodata/eurodata-ui/dist/react/side-menu/index.js';"
  }
}
