{
  "tag": "ed-app",
  "kind": "component",
  "summary": "Application shell with header, navigation, content and footer regions.",
  "status": "experimental",
  "since": "1.0",
  "docs": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/app/",
  "usage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/app/usage/",
  "playwright": "getByTestId('…')",
  "dependencies": [
    "ed-button",
    "ed-icon",
    "ed-drawer",
    "ed-toast-stack"
  ],
  "use": [
    "The outermost layout frame of every full product page",
    "Building a product screen with header, side navigation and content that rearranges between desktop and phone widths",
    "Letting users collapse or reopen the main navigation, and placing it at the start or end of the page"
  ],
  "notFor": [
    {
      "when": "Laying out a sub-region of a page",
      "instead": "[Split Panel](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/split-panel), [Card](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/card), or plain CSS layout"
    },
    {
      "when": "Nesting one application shell inside another",
      "instead": "one ed-app for the whole page"
    }
  ],
  "rules": [
    {
      "id": "app/one-per-page",
      "rule": "Use exactly one app shell per page, as its outermost layout frame — the shell is the page, not a panel. Never nest one app shell inside another: layout needs inside the content area are solved with regular components.",
      "check": "error"
    },
    {
      "id": "app/no-hand-built-scaffold",
      "rule": "Never hand-build the page scaffold from divs when the shell covers it.",
      "why": "You would re-implement responsive navigation, skip links, and sticky behavior by hand."
    },
    {
      "id": "app/main-in-default-slot",
      "rule": "Put the page content into exactly one `<main>`, as a direct child in the default slot.",
      "why": "The shell sets no main landmark of its own, and the slot's padding applies to the `<main>`.",
      "check": "error"
    },
    {
      "id": "app/footer-and-aside-landmarks",
      "rule": "Slot a `<footer>` into `footer` and an `<aside>` into `aside` for their landmarks, the same way as the `<main>`.",
      "check": "error",
      "covered": true
    },
    {
      "id": "app/h1-opens-main",
      "rule": "Open the `<main>` with the page title, the `<h1>`.",
      "why": "A screen-reader user who jumps to the main landmark lands on it; the `main-header` slot lies outside that landmark.",
      "check": "error"
    },
    {
      "id": "app/only-needed-slots",
      "rule": "Populate only the slots you actually need — sections without content are not rendered."
    },
    {
      "id": "app/navigation-slot",
      "rule": "Place the primary navigation ([Side Menu](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/side-menu) or [Rail Menu](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/rail-menu)) in the `navigation` slot, so the desktop collapse and the mobile drawer come for free. Never reach for the `menu` slot casually.",
      "why": "`menu` replaces the entire built-in navigation area, the mobile drawer included, and you take over the responsive behavior yourself.",
      "check": "error"
    },
    {
      "id": "app/desktop-nav-open",
      "rule": "Set `desktop-nav-open` where the desktop navigation should start open — it starts collapsed."
    },
    {
      "id": "app/rail-menu-toggle",
      "rule": "Hide the desktop navigation toggle (`hide-desktop-navigation-toggle`) when using [Rail Menu](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/rail-menu).",
      "why": "The rail brings its own collapse control, so the header hamburger then only serves the mobile drawer.",
      "check": "error",
      "covered": true
    },
    {
      "id": "app/navigation-toggle",
      "rule": "Mark any button of your own that opens the navigation from your UI with `data-toggle-nav` — don't wire your own open/close logic, the shell does it. Never disable the navigation toggle without offering another way to open the navigation on mobile.",
      "check": "warning"
    },
    {
      "id": "app/header-and-main-header",
      "rule": "Put the product header ([Header](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/header)) in the `header` slot, and breadcrumbs — nothing else — in the `main-header` slot.",
      "check": "error"
    },
    {
      "id": "app/aside-secondary",
      "rule": "Reserve the aside for secondary, supporting content — a table of contents ([Scrollspy](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/scrollspy)), contextual help — never for primary actions or a second navigation.",
      "check": "error"
    },
    {
      "id": "app/two-footers",
      "rule": "Keep the two footers apart: `main-footer` belongs to the content column, `footer` to the whole page, and it always sits below the first viewport."
    },
    {
      "id": "app/banner",
      "rule": "Use the banner only for the rare page-wide notice, such as a maintenance or environment warning — never for promotions or permanent content."
    },
    {
      "id": "app/skip-link",
      "rule": "Never remove or visually hide the built-in skip-to-content link; extend it through its slot if the page needs more skip targets.",
      "check": "error"
    },
    {
      "id": "app/toast-region",
      "rule": "Don't add a toast region of your own to change where toasts appear — the shell has one; set its placement with `toast.configure()`.",
      "check": "error"
    },
    {
      "id": "app/known-heights",
      "rule": "Set the height custom properties (`--ed-app-header-height`, `--ed-app-subheader-height`, `--ed-app-banner-height`) when the heights are known, to prevent layout shift on first paint.",
      "check": "warning"
    },
    {
      "id": "app/sticky-offset",
      "rule": "Give a sticky bar of your own the sum of `--ed-app-banner-top`, `--ed-app-header-top` and `--ed-app-subheader-top` as its offset; ed-app measures the header, banner and subheader itself.",
      "why": "`--ed-app-header-top` on its own clears the header, but not a banner above it or a subheader below it.",
      "check": "warning"
    },
    {
      "id": "app/check-breakpoint",
      "rule": "Check the layout on both sides of the mobile breakpoint, and tune `mobile-breakpoint` when the navigation content needs the drawer earlier."
    }
  ],
  "api": {
    "attributes": [
      {
        "name": "view",
        "property": "view",
        "type": "'mobile' | 'desktop'",
        "default": "'desktop'",
        "description": "The view is a reflection of the \"mobileBreakpoint\", when the page is larger than the `mobile-breakpoint` (768px by\ndefault), it is considered to be a \"desktop\" view. The view is merely a way to distinguish when to show/hide the\nnavigation. You can use additional media queries to make other adjustments to content as necessary.\nThe default is \"desktop\" because the \"mobile navigation drawer\" isn't accessible via SSR due to drawer requiring JS."
      },
      {
        "name": "desktop-nav-open",
        "property": "desktopNavOpen",
        "type": "boolean",
        "default": "false",
        "description": "Whether the desktop navigation is open."
      },
      {
        "name": "mobile-nav-open",
        "property": "mobileNavOpen",
        "type": "boolean",
        "default": "false",
        "description": "Whether the mobile navigation drawer is open."
      },
      {
        "name": "mobile-breakpoint",
        "property": "mobileBreakpoint",
        "type": "string",
        "default": "'768px'",
        "description": "At what page width to hide the \"navigation\" slot and collapse into a hamburger button.\nAccepts both numbers (interpreted as px) and CSS lengths (e.g. `50em`), which are resolved based on the root element."
      },
      {
        "name": "navigation-placement",
        "property": "navigationPlacement",
        "type": "'start' | 'end'",
        "default": "'start'",
        "description": "Where to place the navigation when in the mobile viewport."
      },
      {
        "name": "disable-navigation-toggle",
        "property": "disableNavigationToggle",
        "type": "boolean",
        "default": "false",
        "description": "Determines whether to hide the default hamburger button.\nThis will automatically flip to \"true\" if you add an element with `data-toggle-nav` anywhere in the element light DOM,\nand to \"false\" when there is navigation content. Setting it to \"true\" yourself, by attribute or property, stops the\nautomatic detection and hides the button for good — for a toggle it cannot see, such as one inside another\ncomponent's shadow root, and for SSR's initial page load. Setting it back to \"false\" hands the decision to the\ndetection again."
      },
      {
        "name": "hide-desktop-navigation-toggle",
        "property": "hideDesktopNavigationToggle",
        "type": "boolean",
        "default": "false",
        "description": "Hides the header navigation toggle outside the mobile view. Use together with `ed-rail-menu`,\nwhose panel follows the active section on desktop — the header hamburger then only serves the mobile drawer."
      },
      {
        "name": "disable-sticky",
        "property": "disableSticky",
        "type": "string",
        "default": "''",
        "description": "Space-delimited list of the sections that should not stick as the page scrolls: `banner`,\n`header`, `subheader`, `menu`, `aside`. An exempted section also drops out of the sum in\n`--ed-app-scroll-margin-top`. The property and the attribute are interchangeable — the styles\nmatch on the attribute, so assigning the property writes it — and a shell that never sets either\ncarries no `disable-sticky` attribute at all."
      },
      {
        "name": "dir",
        "property": "dir",
        "type": "string"
      },
      {
        "name": "lang",
        "property": "lang",
        "type": "string"
      }
    ],
    "properties": [],
    "methods": [
      {
        "name": "showNavigation",
        "description": "Shows the navigation"
      },
      {
        "name": "hideNavigation",
        "description": "Hides the navigation"
      },
      {
        "name": "toggleNavigation",
        "description": "Toggles the navigation"
      }
    ],
    "events": [],
    "slots": [
      {
        "name": "",
        "description": "The page's main content, in one `<main>`: the shell sets no main landmark of its own."
      },
      {
        "name": "banner",
        "description": "The banner that gets display above the header. The banner will not be shown if no content is provided."
      },
      {
        "name": "header",
        "description": "The header to display at the top of the page. If a banner is present, the header will appear below the banner. The header will not be shown if there is no content."
      },
      {
        "name": "subheader",
        "description": "A subheader to display below the `header`."
      },
      {
        "name": "menu",
        "description": "The left side of the page. If you slot an element in here, you will override the default `navigation` slot and will be handling navigation on your own. This section \"sticks\" to the top as the page scrolls."
      },
      {
        "name": "navigation-header",
        "description": "The header for the navigation area. On desktop this is at the top of the `<nav>`. On mobile it renders as the header of `<ed-drawer>`."
      },
      {
        "name": "navigation",
        "description": "The main content to display in the navigation area. On desktop it is displayed in a `<nav>` on the left side. On mobile it renders inside `<ed-drawer>`."
      },
      {
        "name": "navigation-footer",
        "description": "The footer for the navigation area. On desktop this is at the bottom of the `<nav>`. On mobile it renders as the footer of `<ed-drawer>`."
      },
      {
        "name": "navigation-toggle",
        "description": "Use this slot to slot in your own button + icon for toggling the navigation. By default it is an `<ed-button>` with a menu `<ed-icon>`."
      },
      {
        "name": "navigation-toggle-icon",
        "description": "Use this to slot in your own icon for toggling the navigation. By default it is a menu `<ed-icon>`."
      },
      {
        "name": "main-header",
        "description": "Breadcrumbs above the main content. The page title is not part of it: the `<h1>` opens the `<main>`, inside the main landmark."
      },
      {
        "name": "main-footer",
        "description": "Footer to display inline below the main content."
      },
      {
        "name": "aside",
        "description": "Content to be shown on the right side of the page. Typically contains a table of contents, ads, etc. This section \"sticks\" to the top as the page scrolls."
      },
      {
        "name": "skip-to-content",
        "description": "The \"skip to content\" slot. You can override this if you would like to customize the `Skip to content` button or add additional \"Skip to X\" links."
      },
      {
        "name": "footer",
        "description": "The content to display in the footer. This is always displayed underneath the viewport so will always make the page \"scrollable\"."
      }
    ],
    "cssProperties": [
      {
        "name": "--ed-app-banner-height",
        "default": "0px",
        "description": "The height of the banner. This gets calculated when the page initializes. If the height is known, you can set it here to prevent shifting when the page loads."
      },
      {
        "name": "--ed-app-header-height",
        "default": "0px",
        "description": "The height of the header. This gets calculated when the page initializes. If the height is known, you can set it here to prevent shifting when the page loads."
      },
      {
        "name": "--ed-app-subheader-height",
        "default": "0px",
        "description": "The height of the subheader. This gets calculated when the page initializes. If the height is known, you can set it here to prevent shifting when the page loads."
      },
      {
        "name": "--ed-app-footer-height",
        "default": "0px",
        "description": "The height of the footer. This gets calculated when the page initializes. The shell itself does not read it — it is published for layouts that need the footer's height, and the measurement replaces whatever you set here."
      },
      {
        "name": "--ed-app-banner-top",
        "description": "How much the banner contributes to the sticky stack: its measured height, or `0px` while `disable-sticky` exempts it. It is one term, not a finished offset — to sit clear of everything sticky above your content, add all three together, as the shell's own rules do."
      },
      {
        "name": "--ed-app-header-top",
        "description": "The header's term in that same sum. On its own it clears the header but not the banner above it."
      },
      {
        "name": "--ed-app-subheader-top",
        "description": "The subheader's term in that same sum."
      },
      {
        "name": "--ed-app-scroll-margin-top",
        "description": "The scroll margin that keeps a scrolled-to target clear of the sticky banner, header and subheader, plus a small gap. A section exempted through `disable-sticky` drops out of the sum. The shell computes it; read it as `scroll-margin-top` on your own anchors, or set it on the shell to extend the offset by chrome of your own."
      }
    ],
    "parts": [
      {
        "name": "base",
        "description": "The component's base wrapper."
      },
      {
        "name": "banner",
        "description": "The banner to show above header."
      },
      {
        "name": "header",
        "description": "The header, usually for top level navigation / branding."
      },
      {
        "name": "subheader",
        "description": "Shown below the header."
      },
      {
        "name": "body",
        "description": "The wrapper around menu, main, and aside."
      },
      {
        "name": "menu",
        "description": "The left hand side of the page. Generally intended for navigation."
      },
      {
        "name": "navigation",
        "description": "The `<nav>` that wraps the navigation slots on desktop viewports."
      },
      {
        "name": "navigation-desktop",
        "description": "A second name carried by that same `<nav>`."
      },
      {
        "name": "navigation-header",
        "description": "The slot that projects the navigation header into the mobile `<ed-drawer>`'s label. The desktop `<nav>` has no counterpart."
      },
      {
        "name": "navigation-toggle",
        "description": "The default `<ed-button>` that toggles the navigation."
      },
      {
        "name": "navigation-toggle-icon",
        "description": "The default `<ed-icon>` displayed inside the navigation-toggle button."
      },
      {
        "name": "main",
        "description": "The center column of the body, holding the main header, content and footer."
      },
      {
        "name": "main-header",
        "description": "The header above main content."
      },
      {
        "name": "main-content",
        "description": "The main content."
      },
      {
        "name": "main-footer",
        "description": "The footer below main content."
      },
      {
        "name": "aside",
        "description": "The right hand side of the page. Used for things like table of contents, ads, etc."
      },
      {
        "name": "skip-to-content",
        "description": "The \"skip to main content\" link."
      },
      {
        "name": "footer",
        "description": "The footer of the page. This is always below the initial viewport size."
      },
      {
        "name": "drawer",
        "description": "The mobile navigation `<ed-drawer>`."
      },
      {
        "name": "drawer__panel",
        "description": "The mobile navigation drawer's exported `panel` part, its sliding surface."
      },
      {
        "name": "drawer__header",
        "description": "The mobile navigation drawer's exported `header` part, wrapping the title and header actions."
      },
      {
        "name": "drawer__header-actions",
        "description": "The mobile navigation drawer's exported `header-actions` part."
      },
      {
        "name": "drawer__title",
        "description": "The mobile navigation drawer's exported `title` part, filled from the `mobile-navigation-header` slot."
      },
      {
        "name": "drawer__close-button",
        "description": "The mobile navigation drawer's exported `close-button` part, an `<ed-button>`."
      },
      {
        "name": "drawer__close-button__base",
        "description": "The mobile navigation drawer's exported `close-button__base` part, that button's own `base`."
      },
      {
        "name": "drawer__body",
        "description": "The mobile navigation drawer's exported `body` part, holding the navigation itself."
      },
      {
        "name": "drawer__footer",
        "description": "The mobile navigation drawer's exported `footer` part."
      }
    ],
    "states": []
  },
  "import": "import '@eurodata/eurodata-ui/dist/components/app/app.js';",
  "react": {
    "component": "EdApp",
    "import": "import EdApp from '@eurodata/eurodata-ui/dist/react/app/index.js';"
  }
}
