{
  "_ai": "Component index for the UNDRR Mangrove library. Most components work as vanilla HTML with CSS classes (vanillaHtml: true). Some require React (requiresReact: true). Every entry states its lifecycle outright, so you never have to probe /js/ for a 404: vanillaModule is true when a plain ES module under /js/ drives the behaviour — the entry's vanillaScripts then lists the files to load, each one the `file` of an entry in library.vanillaScripts, and the detail file carries the full contract — and false when there is none, either because the component is static presentation (the detail file says why in vanillaModuleNote) or because its behaviour needs React (hydration: true). An `import` line, where present, is the exact line to use and names the package subpath (@undrr/undrr-mangrove/components/Name.js); the package root is not an entry point and resolves on no published version. No `import` line means the component ships in no bundle. importRequiresDom: true means that line reads `document` as it loads: correct in a browser or through a bundler, and it throws in Node and in server-side rendering — the detail file says what to do instead. Each entry has a detailsUrl with full props, rendered HTML examples, and code snippets.",
  "library": {
    "name": "@undrr/undrr-mangrove",
    "version": "2.0.0",
    "description": "Mangrove design System for UNDRR",
    "documentation": "https://mangrove.undrr.org/",
    "repository": "https://github.com/unisdr/undrr-mangrove",
    "npm": "https://www.npmjs.com/package/@undrr/undrr-mangrove",
    "cssPrefix": "mg-",
    "namingConvention": "BEM (e.g., mg-card__title, mg-card__icon--bordered). Buttons are the exception: mg-button-primary, mg-button-secondary and mg-button-outline are single-dash, not BEM modifiers.",
    "themes": [
      "undrr",
      "preventionweb",
      "irp",
      "mcr2030",
      "delta"
    ],
    "locales": [
      "en",
      "ar",
      "my",
      "ja"
    ],
    "rtlSupport": true,
    "semanticHtml": true,
    "breakpoints": {
      "mobile": "480px",
      "tablet": "900px",
      "desktop": "1164px",
      "wide": "1440px"
    },
    "utilitiesUrl": "https://mangrove.undrr.org/ai-components/utilities.json",
    "iconsUrl": "https://mangrove.undrr.org/ai-components/components-icons.json",
    "tokensUrl": "https://mangrove.undrr.org/tokens.json",
    "customProperties": {
      "_note": "113 component-scoped CSS custom properties across 22 components. They are a component's theming API and are NOT in tokens.json, which documents theme tokens only. Each component that has them lists a count here and the full set, with defaults and descriptions, in its detail JSON.",
      "field": "customProperties"
    },
    "releasesUrl": "https://mangrove.undrr.org/releases.json",
    "changelogUrl": "https://github.com/unisdr/undrr-mangrove/blob/main/CHANGELOG.md",
    "quickstart": {
      "css": "<link rel=\"stylesheet\" href=\"https://assets.undrr.org/mangrove/2.0.0/css/style.css\" />",
      "cssThemes": {
        "undrr": "https://assets.undrr.org/mangrove/2.0.0/css/style.css",
        "preventionweb": "https://assets.undrr.org/mangrove/2.0.0/css/style-preventionweb.css",
        "mcr2030": "https://assets.undrr.org/mangrove/2.0.0/css/style-mcr.css",
        "irp": "https://assets.undrr.org/mangrove/2.0.0/css/style-irp.css",
        "delta": "https://assets.undrr.org/mangrove/2.0.0/css/style-delta.css",
        "all": "https://assets.undrr.org/mangrove/2.0.0/css/style-all.css"
      }
    },
    "requiredAssets": {
      "_note": "Every UNDRR-branded page should include these assets. Order matters.",
      "stylesheets": [
        {
          "name": "Mangrove theme CSS",
          "url": "https://assets.undrr.org/mangrove/2.0.0/css/style.css",
          "placement": "head",
          "note": "Choose one theme. See THEME_CSS for alternatives."
        },
        {
          "name": "Cookie consent CSS",
          "url": "https://assets.undrr.org/static/cookie-banner/v1/cookieconsent.css",
          "placement": "head",
          "note": "Required if using the UNDRR cookie consent banner."
        }
      ],
      "scripts": [
        {
          "name": "UNDRR analytics (GA4)",
          "url": "https://assets.undrr.org/static/analytics/v1.0.0/google_analytics_enhancements.js",
          "placement": "before closing </body>",
          "attributes": "defer",
          "note": "Google Analytics 4 bootstrap and enhancements for UNDRR sites."
        },
        {
          "name": "UNDRR critical messaging",
          "url": "https://messaging.undrr.org/src/undrr-messaging.js",
          "placement": "before closing </body>",
          "attributes": "defer",
          "note": "Emergency broadcasts. Injects messages at top of body or into .mg-critical-messaging container."
        },
        {
          "name": "Cookie consent JS (UMD)",
          "url": "https://assets.undrr.org/static/cookie-banner/v1/cookieconsent.umd.js",
          "placement": "before closing </body>, after analytics",
          "attributes": "none (synchronous)",
          "note": "Cookie consent library. Must load before the UNDRR config script."
        },
        {
          "name": "Cookie consent UNDRR config",
          "url": "https://assets.undrr.org/static/cookie-banner/v1/cookieconsent-undrr.js",
          "placement": "immediately after cookieconsent.umd.js",
          "attributes": "none (synchronous)",
          "note": "UNDRR-specific cookie consent configuration."
        }
      ],
      "logos": {
        "horizontal": "https://assets.undrr.org/static/logos/undrr/undrr-logo-horizontal.svg",
        "vertical": "https://assets.undrr.org/static/logos/undrr/undrr-logo-vertical.svg",
        "squareBlue": "https://assets.undrr.org/static/logos/undrr/undrr-logo-square-blue.svg"
      }
    },
    "vanillaScripts": [
      {
        "name": "Tabs",
        "file": "js/tabs.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/tabs.js",
        "selector": "[data-mg-js-tabs]",
        "initFunction": "mgTabs(scope, activateDeepLinkOnLoad)",
        "description": "Initializes accessible horizontal tabs and stacked disclosure accordions. In SPAs or dynamically loaded DOM, call mgTabs(containerElement) to re-initialize."
      },
      {
        "name": "Show More",
        "file": "js/show-more.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/show-more.js",
        "selector": "[data-mg-show-more]",
        "initFunction": "mgShowMore(scope)",
        "description": "Initializes progressive content truncation toggle buttons. Call mgShowMore(containerElement) for dynamic content."
      },
      {
        "name": "Table of Contents",
        "file": "js/table-of-contents.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/table-of-contents.js",
        "selector": "[data-mg-table-of-contents]",
        "initFunction": "mgTableOfContents(scope)",
        "description": "Generates an in-page table of contents and scrollspy highlighting from headings in the article."
      },
      {
        "name": "On This Page Nav",
        "file": "js/on-this-page-nav.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/on-this-page-nav.js",
        "selector": "[data-mg-on-this-page-nav]",
        "initFunction": "mgOnThisPageNav(scope)",
        "description": "In-page jump navigation bar with horizontal scroll controls and active section indicator."
      },
      {
        "name": "Switch pending",
        "file": "js/switch-pending.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/switch-pending.js",
        "selector": "[data-mg-switch-pending]",
        "initFunction": "mgSwitchPendingInit(scope, { save, labels, timeout, signal })",
        "description": "Pending state for .mg-switch while a change saves: announces progress, ignores presses, times out and reverts on failure. Load as type=\"module\". Call mgSwitchPending(input, { save }) per switch, or mark switches with data-mg-switch-pending (auto-initialised on load) and answer the cancelable mg-switch:save event with event.detail.respondWith(promise). Call mgSwitchPendingDestroy(scope) or abort { signal } before removing switches."
      },
      {
        "name": "Drawer",
        "file": "js/drawer.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/drawer.js",
        "selector": "[data-mg-js-drawer]",
        "initFunction": "mgDrawer(scope)",
        "description": "Open and close, Escape, focus management and a modal focus trap for a drawer or floating panel you rendered yourself. It never builds markup, so the close label, title and body stay in your HTML. Triggers are [data-mg-drawer-trigger=\"<container id>\"]; scripts can dispatch mg-drawer:open, mg-drawer:close and mg-drawer:toggle on the container and listen for mg-drawer:opened and mg-drawer:closed. A floating panel (the mg-floating-panel class) is non-modal: no backdrop and no Tab trap. Call mgDrawer(scope) again for drawers added later, and mgDrawerDestroy(scope) before removing them."
      },
      {
        "name": "Hub header",
        "file": "js/hub-header.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/hub-header.js",
        "selector": "[data-mg-js-hub-header]",
        "initFunction": "mgHubHeader(scope)",
        "description": "Keeps the marked section of a static HubHeader in view and drives its edge fades. With data-mg-hub-header-detect-current it marks the current section from the URL, so the same markup can be copied to every page of a hub. Call mgHubHeader(scope) for headers added later; the returned function undoes the call."
      },
      {
        "name": "Cite this",
        "file": "js/cite-this.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/cite-this.js",
        "selector": "[data-mg-cite-this]",
        "initFunction": "mgCiteThis(scope)",
        "description": "Enhances a server-rendered citation disclosure into a button and native dialog with metadata resolution, copy feedback and analytics events."
      },
      {
        "name": "Copy button",
        "file": "js/copy-button.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/copy-button.js",
        "selector": "[data-mg-copy-button]",
        "initFunction": "mgCopyButton(scope)",
        "description": "Zero-dependency copy-to-clipboard button with a transient tooltip and an aria-live announcement. Call mgCopyButton(scope) for buttons added later."
      },
      {
        "name": "Preview Access",
        "file": "js/preview-access.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/preview-access.js",
        "selector": "[data-mg-preview-access]",
        "initFunction": "mgPreviewAccess(scope)",
        "description": "Password gate and preview notice bar for staging and pre-publication review."
      },
      {
        "name": "UNDRR shared constants",
        "file": "js/undrr.js",
        "url": "https://assets.undrr.org/mangrove/2.0.0/js/undrr.js",
        "description": "Shared constants (key codes, breakpoints) on the window.UNDRR namespace. It does not include the other modules."
      }
    ]
  },
  "components": [
    {
      "id": "design-decisions-container",
      "name": "Container",
      "summary": "Centered responsive container with breakpoint-driven max-widths (480/900/1164/1440px). Variants for padding and vertical spacing.",
      "description": "Centered responsive container with breakpoint-driven max-widths (480/900/1164/1440px). Variants for padding and vertical spacing.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/design-decisions-container--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/design-decisions-container.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "design-decisions-grid-layout",
      "name": "Grid",
      "summary": "Responsive CSS grid system: 1-12 equal-fraction column layouts with spanning, an auto-fit fallback for card grids, and the asymmetric mg-grid--article split.",
      "description": "Responsive CSS grid system. 1-12 equal-fraction column layouts with column and row spanning, plus a single-row auto-fit fallback, for card-style grids. mg-grid--article is a different shape: an asymmetric flexible-column-plus-fixed-rail split (used by the mg-reading--with-contents reading grid), not an equal-fraction layout. Flexbox fallback for older browsers.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/design-decisions-grid-layout--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/design-decisions-grid-layout.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "design-decisions-language-boundaries",
      "name": "Languageboundaries",
      "summary": "Storybook integration demo measuring rendered font families across nested Arabic and Latin language boundaries.",
      "description": "Storybook integration demo measuring rendered font families across nested Arabic and Latin language boundaries. Requires React and browser layout APIs for live measurements; this is a documentation specimen, not a reusable production component.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/design-decisions-language-boundaries--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/design-decisions-language-boundaries.json",
      "requiresReact": true,
      "vanillaModule": false
    },
    {
      "id": "components-buttons-buttons",
      "name": "CtaButton",
      "summary": "Primary and secondary CTA buttons with a disabled variant, plus two icon button shapes that are not interchangeable: the variant-coloured .mg-button--icon and the standalone .mg-icon-button.",
      "description": "Primary and secondary CTA buttons with disabled variant. Themed via design tokens. WCAG AA contrast on both light and dark backgrounds. Icon-only buttons come in two shapes that are not interchangeable: .mg-button.mg-button-{variant}.mg-button--icon is the variant-coloured one (.mg-button--icon is a shape modifier; the foreground, typography and focus ring still come from .mg-button), and .mg-icon-button is a standalone borderless ghost primitive for dismiss, close and copy controls on an existing surface. .mg-icon-button carries no variant colours and takes no .mg-button-* class: .mg-button-primary and .mg-button-secondary only set a background, so the pairing is redundant markup, and .mg-button-outline draws no border on it.",
      "import": "import { CtaButton } from \"@undrr/undrr-mangrove/components/CtaButton.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-buttons-buttons--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-buttons-buttons.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 1
    },
    {
      "id": "components-buttons-chips",
      "name": "Chips",
      "summary": "Compact pill-shaped controls for categories and active filters. The default variant is a link; the dismissible variant is a button with a visible X and a localisable accessible name.",
      "description": "Compact pill-shaped controls for categories and active filters. The default variant is a link; the dismissible variant is a button with a visible X and a localisable accessible name.",
      "import": "import { Chips } from \"@undrr/undrr-mangrove/components/Chips.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-buttons-chips--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-buttons-chips.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-buttons-copybutton",
      "name": "CopyButton",
      "summary": "One-click copy button with micro-feedback tooltip and aria-live announcements. Supports zero-dependency vanilla JS (js/copy-button.js), Layer 2 React hydration via createHydrator, and React JSX.",
      "description": "One-click copy button with micro-feedback tooltip and aria-live announcements. Supports zero-dependency vanilla JS (js/copy-button.js), Layer 2 React hydration via createHydrator, and React JSX.",
      "import": "import { CopyButton } from \"@undrr/undrr-mangrove/components/CopyButton.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-buttons-copybutton--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-buttons-copybutton.json",
      "vanillaHtml": true,
      "hydration": true,
      "vanillaModule": true,
      "vanillaScripts": [
        "js/copy-button.js"
      ]
    },
    {
      "id": "components-buttons-sharebuttons",
      "name": "ShareButtons",
      "summary": "Row of share controls for the current page: social networks, email, a native QR code dialog and a copy-link button with confirmation.",
      "description": "Row of share controls for the current page: social networks, email, a native QR code dialog and a copy-link button with confirmation. The dialog has labelled copy, download, and close actions. Labels and the email subject and body come from props or data attributes, so every string can be translated.",
      "import": "import ShareButtons from \"@undrr/undrr-mangrove/components/ShareButtons.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-buttons-sharebuttons--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-buttons-sharebuttons.json",
      "requiresReact": true,
      "hydration": true,
      "vanillaModule": false
    },
    {
      "id": "components-cards-book-card",
      "name": "BookCard",
      "summary": "Minimal card for publications: cover image and title only.",
      "description": "Minimal card for publications: cover image and title only.",
      "import": "import { BookCard } from \"@undrr/undrr-mangrove/components/BookCard.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-cards-book-card--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-cards-book-card.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-cards-horizontal-book-card",
      "name": "HorizontalBookCard",
      "summary": "Horizontal card for publications: cover image left, title and summary right.",
      "description": "Horizontal card for publications: cover image left, title and summary right.",
      "import": "import { HorizontalBookCard } from \"@undrr/undrr-mangrove/components/HorizontalBookCard.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-cards-horizontal-book-card--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-cards-horizontal-book-card.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-cards-horizontal-card",
      "name": "HorizontalCard",
      "summary": "Side-by-side card with image left and content right. Labels, title, summary, and CTA button.",
      "description": "Side-by-side card with image left and content right. Labels, title, summary, and CTA button.",
      "import": "import { HorizontalCard } from \"@undrr/undrr-mangrove/components/HorizontalCard.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-cards-horizontal-card--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-cards-horizontal-card.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-cards-icon-card",
      "name": "IconCard",
      "summary": "Card with icon or image, title, summary and optional CTA. Vertical or horizontal orientation, in default, centered or negative (dark) variants.",
      "description": "Card with icon or image, title, summary, and optional CTA. Variants: default, centered, negative (dark background). Orientation: vertical (icon above the content) or horizontal (icon beside it, for route rows); horizontal sizes the visual itself, so imageScale does not apply. Image scale options: small, medium, large, full. Supports custom icon background/foreground colors (iconColor, iconFgColor), border color, and label position (top or content area).",
      "import": "import { IconCard } from \"@undrr/undrr-mangrove/components/IconCard.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-cards-icon-card--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-cards-icon-card.json",
      "vanillaHtml": true,
      "hydration": true,
      "vanillaModule": false,
      "customProperties": 4
    },
    {
      "id": "components-cards-stats-card",
      "name": "StatsCard",
      "summary": "Grid of numeric statistics with optional icons, dual labels (label above the value, bottomLabel below it), descriptions, and call-to-action links. Variants: default, compact, highlighted, negative.",
      "description": "Grid of numeric statistics with optional icons, dual labels (label above the value, bottomLabel below it), descriptions, and call-to-action links. Variants: default, compact, highlighted, negative.",
      "import": "import { StatsCard } from \"@undrr/undrr-mangrove/components/StatsCard.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-cards-stats-card--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-cards-stats-card.json",
      "vanillaHtml": true,
      "hydration": true,
      "vanillaModule": false
    },
    {
      "id": "components-cards-vertical-card",
      "name": "VerticalCard",
      "summary": "Card with stacked image, labels, title, summary, and optional CTA button. Four color variants.",
      "description": "Card with stacked image, labels, title, summary, and optional CTA button. Four color variants.",
      "import": "import { VerticalCard } from \"@undrr/undrr-mangrove/components/VerticalCard.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-cards-vertical-card--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-cards-vertical-card.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-cite-this",
      "name": "CitationExample",
      "summary": "Vanilla citation dialog with editorial, structured-data and page fallbacks, copy feedback, and analytics events.",
      "description": "Vanilla citation button and native dialog for detail pages. An empty data-mg-cite-this element uses the page title and URL; server-rendered disclosure markup preserves a no-JavaScript fallback. Prefer an approved citation, then configured metadata, a matching JSON-LD CreativeWork, or a page-title fallback. The script supplies copy feedback and bubbling analytics events; the host owns GA4 and consent.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-cite-this--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-cite-this.json",
      "vanillaHtml": true,
      "vanillaModule": true,
      "vanillaScripts": [
        "js/cite-this.js"
      ]
    },
    {
      "id": "components-codeblock",
      "name": "CodeBlock",
      "summary": "Formatted source code display. Plain pre and code on vanilla pages, the CodeBlock component in React, both coloured by the same Prism token classes.",
      "description": "Formatted source code display. Two rendering paths share the same CSS:\n\nVANILLA HTML (Drupal pages): Use `<pre><code>` directly. Prism.js (loaded globally) tokenises the code and emits `.token.*` span elements — Mangrove's `code.scss` styles those classes. Add a `data-language=\"Bash\"` attribute on `<pre>` for a language badge. Wrap in `<figure class=\"mg-code-block\"><figcaption>filename</figcaption>…</figure>` for a filename header bar.\n\nREACT (Storybook / JS apps): Use the `CodeBlock` component. Props: `code` (required string), `language` (\"bash\" | \"javascript\" | \"jsx\" — enables react-syntax-highlighter/PrismLight which emits the same `.token.*` classes), `filename` (string — adds the figure/figcaption wrapper), `lineNumbers` (boolean — gutter line numbers, requires `language`).\n\nIMPORTANT — token classes: `.token.keyword`, `.token.string`, `.token.tag` etc. are NOT Mangrove BEM classes. They are emitted by Prism.js (and react-syntax-highlighter under the hood). Mangrove owns the `code.scss` rules that colour them; the class names themselves are Prism's API. Do not rename or prefix them with `mg-`.\n\nFor inline `<code>` snippets in prose, use the bare HTML element — the global `code.scss` styles it automatically. The CodeBlock component is only for block-level code display.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-codeblock--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-codeblock.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-cta",
      "name": "TextCta",
      "summary": "Call-to-action banner with heading, rich text body, action buttons and optional image. Four color variants, centered or side-by-side layout.",
      "description": "Call-to-action banner with heading, rich text body, action buttons, and optional image. Four color variants (primary, secondary, tertiary, quaternary), strong or soft accent tone, and custom backgroundColor override. Supports centered and side-by-side (with image) layouts.",
      "import": "import { TextCta } from \"@undrr/undrr-mangrove/components/TextCta.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-cta--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-cta.json",
      "vanillaHtml": true,
      "hydration": true,
      "vanillaModule": false,
      "customProperties": 2
    },
    {
      "id": "components-dataviz-legend",
      "name": "Legend",
      "summary": "Prototype. Map and chart data visualization legend supporting continuous ramps, stepped intervals, and categorical swatches. Rendered as a group named by its title.",
      "description": "Prototype. Map and chart data visualization legend supporting continuous ramps, stepped intervals, and categorical swatches. Rendered as a group named by its title.",
      "import": "import { Legend } from \"@undrr/undrr-mangrove/components/Legend.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-dataviz-legend--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-dataviz-legend.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 1
    },
    {
      "id": "components-embedcontainer",
      "name": "EmbedContainer",
      "summary": "Responsive aspect-ratio wrapper for iframes and embeds. Default 16:9 with 4:3, 1:1, and 21:9 variants.",
      "description": "Responsive aspect-ratio wrapper for iframes and embeds. Default 16:9 with 4:3, 1:1, and 21:9 variants.",
      "import": "import { EmbedContainer } from \"@undrr/undrr-mangrove/components/EmbedContainer.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-embedcontainer--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-embedcontainer.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-empty-state",
      "name": "Empty state",
      "summary": "Message shown where a collection, table or panel has no content: optional glyph, title, description and actions. Variants: panel, compact, start-aligned.",
      "description": "Message shown where a collection, table or panel has no content. Optional media slot for a glyph, a title, a description and an optional actions slot. Variants: panel, compact, start-aligned. mg-empty-state__title is a class, not a tag: choose the element to fit the surrounding outline, one level below the heading of the section or card that contains it (h3 in a section headed h2, even after an h3 subsection; h4 inside a card titled h3) and never skipping levels; use a p where a heading would be out of place, such as a table cell or dashboard tile. Examples use h2 only because they stand alone. Inside a table, place it in a single td with colspan so the row structure and column headers survive for screen readers.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-empty-state--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-empty-state.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 15
    },
    {
      "id": "components-error-pages",
      "name": "ErrorPage",
      "summary": "Branded full-page error templates for the common 4xx and 5xx codes and for Cloudflare challenges, with a brand stripe, the status code, a search field, diagnostic details and action buttons.",
      "description": "Branded full-page error templates for the common 4xx and 5xx codes (401, 403, 404, 429, 500, 502, 503, 504) and for Cloudflare challenges, with a brand decoration stripe, the status code as a heading, search field, diagnostic details, and action buttons. Default copy ships for each of those status codes, and title, description and actions can each be overridden. Request details (Ray ID, IP, location) are optional, for debugging. For Cloudflare, static HTML versions with the Cloudflare tokens already in place live in the component's static/ directory.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-error-pages--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-error-pages.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-font-size-utilities",
      "name": "Fontsizeutilities",
      "summary": "Font size utility classes (mg-font-size-*) for overriding typography scale.",
      "description": "Font size utility classes (mg-font-size-*) for overriding typography scale.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-font-size-utilities--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-font-size-utilities.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-footer",
      "name": "Footer",
      "summary": "Site footer with optional UNDRR syndication. Loads global footer content from PreventionWeb via a widget script. Works with or without React.",
      "description": "Site footer with optional UNDRR syndication. Loads global footer content from PreventionWeb via a widget script. Works with or without React.",
      "import": "import { Footer } from \"@undrr/undrr-mangrove/components/Footer.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-footer--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-footer.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-forms-checkbox",
      "name": "Checkbox",
      "summary": "Styled checkbox with label, plus the CSS-only .mg-switch toggle. Error, disabled and pending states, and a vanilla helper for switches that save a setting.",
      "description": "Styled checkbox with label. Error and disabled states available. Also documents the CSS-only .mg-switch toggle (role=\"switch\"), including a pending state set with aria-busy=\"true\" on the input or .mg-switch--pending on the label. The switch has an error state, set the same way as on any other control: aria-invalid=\"true\" on the input (preferred, and the only form assistive technology sees), or mg-switch__input--error on the input, or mg-switch--error on the label, each giving the track a red boundary; put the message in a sibling p.mg-form-error with role=\"alert\" OUTSIDE the label (inside it would join the switch's accessible name) and join the two with aria-describedby, exactly as with a text input, so FormErrorSummary can link to the switch by id. The error state does not move the thumb: use it for \"the thing this switch controls failed\", and the pending helper when the save itself failed and the switch must revert. The switch is sized and coloured with the --mg-switch-* custom properties in this entry, set on the switch or any ancestor, and never by overriding the thumb transform, which also breaks RTL. The thumb travel, its RTL counterpart and the pending ring all derive from the size properties, so setting those is enough in both directions. .mg-switch--small sets --mg-switch-size: 1.125rem and a tighter row gap, and re-declares no length inside the switch; prefer it to a size of your own for a toolbar, table row or panel header. Do not paint a switch state with box-shadow or outline on the track: the focus ring owns both, and a consumer rule of equal specificity replaces its separator band. For a switch that saves a setting, load the dependency-free js/switch-pending.js module (no React): it announces \"Saving…\", \"Still saving…\" and the outcome in a role=\"status\" region, ignores presses while saving, sets aria-busy a frame after the change, honours only the latest request, and times out (10s) and reverts on failure. Use mgSwitchPending(input, { save }) where save(checked, signal) returns a Promise, or mark switches with data-mg-switch-pending and answer one document-level mg-switch:save listener. Both defaults can be switched off: revert: false keeps the position the user asked for and sets aria-invalid=\"true\" instead (which also turns on the error state above, so supply the .mg-form-error message too), and timeout: 0 or Infinity removes the deadline. mgSwitchAnnouncer(element, { status, labels }) exports the announcements on their own, for apps that run their own save.",
      "import": "import { Checkbox } from \"@undrr/undrr-mangrove/components/Checkbox.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-forms-checkbox--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-forms-checkbox.json",
      "vanillaHtml": true,
      "vanillaModule": true,
      "vanillaScripts": [
        "js/switch-pending.js"
      ],
      "customProperties": 13
    },
    {
      "id": "components-forms-form-action",
      "name": "FormAction",
      "summary": "Joins one form field to one high-priority action as a continuous control, for search, subscribe, apply and other compact submission flows.",
      "description": "Joins one form field to one high-priority action as a continuous control for search, subscribe, apply, check, redeem, or compact submission flows. Keep the field and button as separate semantic controls. Do not use for unrelated actions, destructive actions, multi-step forms, or multiple fields sharing one submit button. Add mg-form-action--stack-mobile when a long or translated action needs the full mobile width.",
      "import": "import { FormAction } from \"@undrr/undrr-mangrove/components/FormAction.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-forms-form-action--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-forms-form-action.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-forms-formerrorsummary",
      "name": "FormErrorSummary",
      "summary": "Persistent error summary box placed at the top of a form, listing all validation errors with an anchor link to each field so the user can jump straight to the problem.",
      "description": "Persistent error summary box placed at the top of a form, listing all validation errors with an anchor link to each field so the user can jump straight to the problem.",
      "import": "import { FormErrorSummary } from \"@undrr/undrr-mangrove/components/FormErrorSummary.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-forms-formerrorsummary--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-forms-formerrorsummary.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-forms-formgroup",
      "name": "FormGroup",
      "summary": "Fieldset wrapper for grouping related form controls with a legend. Error and disabled states.",
      "description": "Fieldset wrapper for grouping related form controls with a legend. Error and disabled states.",
      "import": "import { FormGroup } from \"@undrr/undrr-mangrove/components/FormGroup.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-forms-formgroup--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-forms-formgroup.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-forms-radio",
      "name": "Radio",
      "summary": "Styled radio button with label. Error and disabled states available.",
      "description": "Styled radio button with label. Error and disabled states available.",
      "import": "import { Radio } from \"@undrr/undrr-mangrove/components/Radio.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-forms-radio--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-forms-radio.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-forms-range",
      "name": "Range",
      "summary": "Prototype. Range slider supporting continuous and stepped intervals with labelled tick marks; stepped sliders announce the tick label via aria-valuetext.",
      "description": "Prototype. Range slider supporting continuous and stepped intervals with labelled tick marks; stepped sliders announce the tick label via aria-valuetext.",
      "import": "import { Range } from \"@undrr/undrr-mangrove/components/Range.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-forms-range--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-forms-range.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-forms-segmented-control",
      "name": "SegmentedControl",
      "summary": "Compact segmented presentation of a radio group, for a small mutually exclusive choice that changes what one view shows. CSS only, no JavaScript, no ARIA.",
      "description": "Compact segmented presentation of a radio group: a small, mutually exclusive choice drawn as one row of adjoining segments, for switching what a single view shows (a map data source, a chart unit, a list sort order). CSS only: no JavaScript and no ARIA. The markup is a fieldset, a legend and one input[type=radio] per segment, each followed immediately by its own label; the CSS clips the inputs out of sight and draws the labels. Keep every label as the immediate next sibling of its input, because the whole presentation hangs off that adjacency, and give every input the same name. Because it is a real radio group, arrow-key navigation, the checked state, the \"N of M\" announcement, form submission and RTL traversal are the browser's and need no code from the consuming app. Do not reach for role=\"tablist\" for this: the ARIA tabs pattern expects a tabpanel per tab, and a view switcher has none. The legend is the group's accessible name and is announced before the segment the user lands on; where the page has no room for a visible one, add mg-u-sr-only to the legend rather than replacing it with aria-label on the fieldset. Use Chips for filters that combine, Select for more than about five options or long labels, .mg-switch for on/off, and an ordinary Radio group in a FormGroup for a vertical list, options needing help text, or a choice that has to show a validation error — this control has no error or invalid state. Read the choice with one change listener on the fieldset. In React, pass value plus onChange for a controlled group, or defaultValue to leave the selection to the DOM. On the default layout the row wraps to a second line at narrow widths and keeps every label whole; mg-segmented-control--full-width always shares the width equally instead, so it shrinks rather than wrapping and breaks long labels mid-word — use it only with short ones.",
      "import": "import { SegmentedControl } from \"@undrr/undrr-mangrove/components/SegmentedControl.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-forms-segmented-control--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-forms-segmented-control.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 2
    },
    {
      "id": "components-forms-select",
      "name": "Select",
      "summary": "Dropdown select field with label, placeholder, help text, and error state.",
      "description": "Dropdown select field with label, placeholder, help text, and error state.",
      "import": "import { Select } from \"@undrr/undrr-mangrove/components/Select.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-forms-select--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-forms-select.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-forms-text-input",
      "name": "TextInput",
      "summary": "Text input field with label, help text, required indicator, and error state.",
      "description": "Text input field with label, help text, required indicator, and error state.",
      "import": "import { TextInput } from \"@undrr/undrr-mangrove/components/TextInput.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-forms-text-input--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-forms-text-input.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-forms-textarea",
      "name": "Textarea",
      "summary": "Multi-line text input with label, help text, and error state.",
      "description": "Multi-line text input with label, help text, and error state.",
      "import": "import { Textarea } from \"@undrr/undrr-mangrove/components/Textarea.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-forms-textarea--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-forms-textarea.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-fullwidth",
      "name": "FullWidth",
      "summary": "Makes content break out of its container to span the full viewport width. RTL-safe.",
      "description": "Makes content break out of its container to span the full viewport width. RTL-safe.",
      "import": "import { FullWidth } from \"@undrr/undrr-mangrove/components/FullWidth.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-fullwidth--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-fullwidth.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-gallery",
      "name": "Gallery",
      "summary": "Media gallery with a main stage, optional thumbnail rail, navigation arrows, captions and keyboard support. Handles images, videos and embedded players.",
      "description": "Media gallery with a main stage, optional thumbnail rail, navigation arrows, captions and keyboard support. Handles images, videos and embedded players.",
      "import": "import { Gallery } from \"@undrr/undrr-mangrove/components/Gallery.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-gallery--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-gallery.json",
      "requiresReact": true,
      "hydration": true,
      "vanillaModule": false
    },
    {
      "id": "components-hero-hero",
      "name": "Hero",
      "summary": "Full-width hero banner with title, summary and CTA buttons. Four color variants, and two layouts: a full-bleed background image or a split content-and-media band.",
      "description": "Full-width hero banner with title, summary, and CTA buttons. Four color variants. Two layouts: `background` (full-bleed image with overlay, default) and `split` (solid theme-colour background with a content column plus a media column). Split layout supports 2/3, 1/2, and 1/3 content-to-media ratios, a configurable heading level (h1–h3), and three media types: `image` (default), `video` (iframe embed — provide the provider embed URL and a `title` for accessibility), or `html` (pre-sanitized HTML string for custom embeds; consumer must sanitize).",
      "import": "import { Hero } from \"@undrr/undrr-mangrove/components/Hero.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-hero-hero--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-hero-hero.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 10
    },
    {
      "id": "components-hero-hero-child",
      "name": "ChildHero",
      "summary": "Deprecated. Smaller hero banner for child and section pages, planned for removal by end of 2026. Migrate to the main Hero component.",
      "description": "DEPRECATED — planned for removal by end of 2026. Never adopted in production across UNDRR sites; do not use in new work. Migrate to the main Hero component (`headingLevel=\"h2\"`/`\"h3\"` or `layout=\"split\"`), which covers the same use cases. Kept available for reference only. Smaller hero banner for child/section pages. Single CTA button, linked label.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-hero-hero-child--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-hero-hero-child.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-highlightbox",
      "name": "HighlightBox",
      "summary": "Highlighted content box. Tones: default, primary, secondary. Layouts: centered, float-start, float-end. Supports embedded video.",
      "description": "Highlighted content box. Tones: default, primary, secondary. Layouts: centered, float-start, float-end. Supports embedded video.",
      "import": "import { HighlightBox } from \"@undrr/undrr-mangrove/components/HighlightBox.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-highlightbox--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-highlightbox.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-icons",
      "name": "Icon",
      "summary": "Mangrove icon set. Use span elements with mg-icon and mg-icon-{name} classes; icons render from SVG data URIs via CSS mask-image.",
      "description": "Mangrove icon set. Use span elements with mg-icon and mg-icon-{name} classes. Icons render from SVG data URIs via CSS mask-image; the icon font is retained only as a fallback for legacy fa-* selectors. The React Icon component accepts five name formats: a bare name (\"globe\") and a legacy mg- prefixed name (\"mg-globe\") both resolve to \"mg-icon mg-icon-globe\"; an already-qualified \"mg-icon-globe\" resolves to the same pair; a legacy \"fa-globe\" resolves to \"mg-icon fa-globe\", keeping the FontAwesome class rather than renaming it; and any name containing a space is treated as a full class string and passed through unchanged. A size prop appends mg-icon--{size}.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-icons--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-icons.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 1
    },
    {
      "id": "components-images-author-image",
      "name": "AuthorImage",
      "summary": "Circular author portrait with optional hover color accent (yellow, green, red, blue) and size variant.",
      "description": "Circular author portrait with optional hover color accent (yellow, green, red, blue) and size variant.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-images-author-image--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-images-author-image.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 3
    },
    {
      "id": "components-images-image-with-credit-caption",
      "name": "Images",
      "summary": "Figure element with image, caption, and photo credit.",
      "description": "Figure element with image, caption, and photo credit.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-images-image-with-credit-caption--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-images-image-with-credit-caption.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-loader",
      "name": "Loader",
      "summary": "Animated loading spinner, 40px on mobile and 96px on desktop, named for assistive technology by an aria-label.",
      "description": "Animated loading spinner. 40px on mobile, 96px on desktop. The element is empty — there is no visible and no visually hidden label text. It carries role=\"status\", aria-live=\"polite\" and aria-busy=\"true\", and the label prop becomes its accessible name through aria-label, so the wait is not silent for a screen reader.",
      "import": "import { Loader } from \"@undrr/undrr-mangrove/components/Loader.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-loader--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-loader.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-logos",
      "name": "Logo",
      "summary": "Logo images for UNDRR, PreventionWeb, IRP, and partner organizations.",
      "description": "Logo images for UNDRR, PreventionWeb, IRP, and partner organizations. The crop=\"autocrop\" variant crops to a fixed box on mobile and tablet instead of shrinking the whole image, so the logo stays legible at small sizes — the page header (\"black bar\") uses it. It is tuned to the proportions of the default English horizontal wordmark only: on the translated assets (assets.undrr.org/logos/undrr/) it cuts the bottom off the subtitle line, since those are roughly square (~2.3-2.9:1) rather than the ~6.6:1 the crop box assumes. Do not pair crop=\"autocrop\" with a translated or otherwise differently proportioned asset.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-logos--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-logos.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-navigation-breadcrumbs",
      "name": "Breadcrumbcomponent",
      "summary": "Breadcrumb navigation trail. White variant available for dark backgrounds.",
      "description": "Breadcrumb navigation trail. White variant available for dark backgrounds.",
      "import": "import { Breadcrumbcomponent } from \"@undrr/undrr-mangrove/components/Breadcrumbs.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-navigation-breadcrumbs--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-navigation-breadcrumbs.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-navigation-drawer",
      "name": "Drawer",
      "summary": "Prototype. Slide-over off-canvas drawer and floating panel for secondary navigation, filters or details, with focus management, backdrop and Escape dismissal.",
      "description": "Prototype. Slide-over off-canvas drawer and floating panel for secondary navigation, filters, or details. Modal dialog with focus management, backdrop and Escape dismissal; string content renders as text. Two lifecycles, either of which makes the markup work: the dependency-free js/drawer.js module, which enhances your own markup on data-mg-js-drawer (mgDrawer / mgDrawerDestroy), or React hydration via createHydrator on data-mg-drawer, which renders the drawer and sanitises server-rendered body markup. Both need the container to have an id and use data-mg-drawer-trigger buttons. Use one or the other, not both.",
      "import": "import { Drawer } from \"@undrr/undrr-mangrove/components/Drawer.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-navigation-drawer--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-navigation-drawer.json",
      "vanillaHtml": true,
      "hydration": true,
      "vanillaModule": true,
      "vanillaScripts": [
        "js/drawer.js"
      ],
      "customProperties": 2
    },
    {
      "id": "components-navigation-megamenu",
      "name": "MegaMenu",
      "summary": "Site-wide mega menu: a desktop navigation strip with multi-column panels, and a bounded progressive overlay below 900px.",
      "description": "Site-wide mega menu: a desktop nav strip with multi-column panels and a bounded progressive mobile overlay below 900px. The menu structure comes from a sections array, normally built server-side or fetched from an API. Below 900px the overlay is bounded (minimum 400px where space permits, maximum min(700px, 90dvh)) with Back above the title, a separate Close control and outside-click dismissal, nested groups, and section headings linked to their landing pages. Optional label props are menuLabel, backLabel, allSectionsLabel, closeLabel, overviewLabel and toggleMobileNavLabel. mg-mega-wrapper--js-active is added on mount, so pointer-events restrictions apply only once the sidebar is available; plain HTML nav markup and failed-hydration states stay clickable on mobile.",
      "import": "import MegaMenu from \"@undrr/undrr-mangrove/components/MegaMenu.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-navigation-megamenu--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-navigation-megamenu.json",
      "requiresReact": true,
      "hydration": true,
      "vanillaModule": false,
      "customProperties": 2
    },
    {
      "id": "components-navigation-on-this-page-nav",
      "name": "OnThisPageNav",
      "summary": "Sticky horizontal \"On this page\" navigation bar with scroll-spy. Auto-detects headings or takes author-provided links. Vanilla JS.",
      "description": "Sticky horizontal \"On this page\" navigation bar with IntersectionObserver scroll-spy. Two modes: auto-detect (scans h2/h3/h4 headings) or explicit (author-provided links). Optional CTA button. Vanilla JS — requires on-this-page-nav.js. The React export renders the markup and calls mgOnThisPageNav() for Storybook; it is not meant as a production React component.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-navigation-on-this-page-nav--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-navigation-on-this-page-nav.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 1
    },
    {
      "id": "components-navigation-pager",
      "name": "Pager",
      "summary": "Pagination for a result list: previous and next controls, numbered pages with ellipses, an optional result-range line and jump-to-page field, and a mini-pager when the total page count is unknown.",
      "description": "Pagination for a result list: previous and next controls, numbered pages with ellipses, an optional result-range line and jump-to-page field, and a mini-pager when the total page count is unknown.",
      "import": "import { Pager } from \"@undrr/undrr-mangrove/components/Pager.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-navigation-pager--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-navigation-pager.json",
      "requiresReact": true,
      "hydration": true,
      "vanillaModule": false
    },
    {
      "id": "components-navigation-skip-link",
      "name": "SkipLink",
      "summary": "Bypass block: an anchor that stays hidden until it takes keyboard focus, then appears above the header, pointing at the page's main element.",
      "description": "Bypass block: an anchor that stays visually hidden until it receives keyboard focus, then appears in normal flow above the header. Points at the page's <main>, which must carry both an id and tabindex=\"-1\" so focus lands there rather than only the scroll position. The label is a prop, and the stylesheet uses logical properties, so it works translated and in right-to-left. Place it as the first focusable element in the page wrapper, before the brand bar. Not built on mg-u-sr-only, which has no focus reveal.",
      "import": "import { SkipLink } from \"@undrr/undrr-mangrove/components/SkipLink.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-navigation-skip-link--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-navigation-skip-link.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-navigation-table-of-contents",
      "name": "TableOfContents",
      "summary": "Renders an in-page table of contents with smooth-scroll anchor links.",
      "description": "Renders an in-page table of contents with smooth-scroll anchor links.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-navigation-table-of-contents--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-navigation-table-of-contents.json",
      "requiresReact": true,
      "vanillaModule": false
    },
    {
      "id": "components-navigation-tree",
      "name": "Tree",
      "summary": "Prototype. Accessible tree view for a nested hierarchy, following the ARIA treeview pattern: roving tabindex, full keyboard navigation and collapsible parents.",
      "description": "Prototype. Accessible tree and nested hierarchy view conforming to the ARIA Treeview pattern. Supports roving tabindex, full keyboard navigation (arrows, Home, End, Enter, Space), guides, controlled/uncontrolled state, a configurable toggle icon (toggleIcon), and separate toggle buttons for linked parent sections. Requires React or hydration via createHydrator with data-mg-tree around a nested list; see the hydration field.",
      "import": "import { Tree } from \"@undrr/undrr-mangrove/components/Tree.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-navigation-tree--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-navigation-tree.json",
      "requiresReact": true,
      "hydration": true,
      "vanillaModule": false,
      "customProperties": 5
    },
    {
      "id": "components-normalize",
      "name": "Normalize",
      "summary": "CSS normalize/reset layer applied globally before component styles.",
      "description": "CSS normalize/reset layer applied globally before component styles.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-normalize--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-normalize.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-notice-cookieconsentbanner",
      "name": "CookieConsentBanner",
      "summary": "Cookie Consent Banner Component",
      "description": "Cookie Consent Banner Component",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-notice-cookieconsentbanner--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-notice-cookieconsentbanner.json",
      "requiresReact": true,
      "vanillaModule": false
    },
    {
      "id": "components-notice-notice",
      "name": "Notice",
      "summary": "Universal in-page notice and alert banner container for informational callouts, contextual warnings, and error alerts. Combine negative with the prominent modifier for emergency banners.",
      "description": "Universal in-page notice and alert banner container for informational callouts, contextual warnings, and error alerts. Combine negative with the prominent modifier for emergency banners.",
      "import": "import { Notice } from \"@undrr/undrr-mangrove/components/Notice.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-notice-notice--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-notice-notice.json",
      "vanillaHtml": true,
      "hydration": true,
      "vanillaModule": false,
      "customProperties": 4
    },
    {
      "id": "components-notice-service-notice",
      "name": "ServiceNotice",
      "summary": "In-page degraded state or partial outage notice for live feeds, interactive maps, or remote APIs with status link, optional retry action, and capped automatic retries with backoff.",
      "description": "In-page degraded state or partial outage notice for live feeds, interactive maps, or remote APIs with status link, optional retry action, and capped automatic retries with backoff.",
      "import": "import { ServiceNotice } from \"@undrr/undrr-mangrove/components/ServiceNotice.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-notice-service-notice--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-notice-service-notice.json",
      "vanillaHtml": true,
      "hydration": true,
      "vanillaModule": false
    },
    {
      "id": "components-notice-snackbar",
      "name": "ShowOffSnackbar",
      "summary": "Snackbar manages auto-dismiss timing and state. Requires React.",
      "description": "Snackbar manages auto-dismiss timing and state. Requires React.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-notice-snackbar--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-notice-snackbar.json",
      "requiresReact": true,
      "vanillaModule": false
    },
    {
      "id": "components-pageheader",
      "name": "PageHeader",
      "summary": "UNDRR page header with coloured decoration stripe, logo, user account link and language selector, plus a decoration-only variant that renders the stripe alone.",
      "description": "UNDRR page header with colored decoration stripe, logo, user account link, and language selector dropdown. The variant prop also takes \"decoration-only\", which renders just the coloured stripe without the header row.",
      "import": "import { PageHeader } from \"@undrr/undrr-mangrove/components/PageHeader.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-pageheader--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-pageheader.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-preview-access",
      "name": "PreviewAccess",
      "summary": "Page-level gate that hides an unfinished page behind a PIN prompt until a reviewer enters the code. Editorial signalling, not a security mechanism.",
      "description": "Page-level gate that hides an unfinished page behind a PIN-prompt modal until a reviewer enters the right code. Drop <div data-mg-preview-access> into a page and load js/preview-access.js. Unlock persists in sessionStorage for the browser session. CSS-first anti-flash via :has(). Editorial signalling only — not a security mechanism, since the PIN sits in the DOM. The React export renders a static preview of the modal for docs; pass `live` to run the real body-level gate, which appends the overlay to document.body and restores the body siblings on unmount.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-preview-access--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-preview-access.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-quotehighlight",
      "name": "QuoteHighlight",
      "summary": "Testimonial or pull quote with attribution, portrait, and optional large image. Background: light, dark, bright. Variants: line separator or image. Alignment: full, left, right.",
      "description": "Testimonial or pull quote with attribution, portrait, and optional large image. Background: light, dark, bright. Variants: line separator or image. Alignment: full, left, right.",
      "import": "import QuoteHighlight from \"@undrr/undrr-mangrove/components/QuoteHighlight.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-quotehighlight--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-quotehighlight.json",
      "vanillaHtml": true,
      "hydration": true,
      "vanillaModule": false
    },
    {
      "id": "components-reading-column",
      "name": "Readingcolumn",
      "summary": "Reading column for a long page: constrains the article to a readable measure, with an optional sticky table of contents beside it from 48rem up.",
      "description": "Reading column for a long page: constrains the article to a readable measure, and with mg-reading--with-contents places a table of contents in a sticky sidebar from 48rem up, stacking it above the article below that. The sidebar split itself is mg-grid's --article variant (see design-decisions-grid-layout) — pair mg-reading--with-contents with mg-grid mg-grid--article in markup.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-reading-column--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-reading-column.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 1
    },
    {
      "id": "components-scrollcontainer",
      "name": "ScrollContainer",
      "summary": "Horizontally scrolling rail for a row of cards or media, with optional arrow controls, drag scrolling, scroll snapping and equal-height items.",
      "description": "Horizontally scrolling rail for a row of cards or media, with optional arrow controls, drag scrolling, scroll snapping and equal-height items.",
      "import": "import ScrollContainer from \"@undrr/undrr-mangrove/components/ScrollContainer.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-scrollcontainer--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-scrollcontainer.json",
      "requiresReact": true,
      "hydration": true,
      "vanillaModule": false
    },
    {
      "id": "components-showmore",
      "name": "ShowMore",
      "summary": "Collapse long content behind a gradient fade with a toggle button, driven by the mgShowMore vanilla JS utility. Height customizable via CSS variable.",
      "description": "Collapse long content behind a gradient fade with a toggle button. Height customizable via CSS variable. The mgShowMore vanilla JS utility reads data-mg-show-more attributes and returns optional lifecycle cleanup. The React wrapper enhances each item independently, supports items added after mount, and accepts translated labelOpen and labelCollapsed props.",
      "import": "import { ShowMore } from \"@undrr/undrr-mangrove/components/ShowMore.js\";",
      "importRequiresDom": true,
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-showmore--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-showmore.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 1
    },
    {
      "id": "components-status-label",
      "name": "Status label",
      "summary": "Status of a record or event, as a coloured shape plus the status name in text. Workflow variants (draft to published) and service health variants (warning, negative).",
      "description": "Status of a record or event, as a coloured indicator plus the status name in text. Workflow variants: draft (rounded square), waiting-information (capsule), waiting-validation (rounded diamond), published (circle). Service health variants: warning/degraded (triangle) and negative/offline (octagon), also used by ServiceNotice. Without a modifier the indicator is a neutral circle. Each status has its own shape as well as its own colour, from CSS alone, so the markup is the same for every variant, and every mark carries the same uniform ring. The indicator is decorative: the status name is always present as text, so meaning never depends on colour. Wrap several in mg-status-label-group, which keeps list semantics without showing a bullet, so no role=\"list\" is needed on the ul. Theme it with the custom properties in this entry, set on the label or any ancestor, not by overriding rules. The shapes are built on those properties: the square, the capsule and the diamond are border-radius and transform overrides that keep a real CSS border, and the triangle and the octagon are clip-path shapes whose ring is the element background and whose fill is a ::before clipped to a matching inner polygon. Do not set background-color, border, border-radius, width, height or transform on mg-status-label__indicator directly — a border is cut through by the clip path, a fill on the element hides the ring, and a transform replaces the diamond.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-status-label--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-status-label.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 15
    },
    {
      "id": "components-syndicated-search",
      "name": "SyndicationSearchWidget",
      "summary": "Search interface over the UNDRR syndication API: query box, facets, active filters, result list or cards, pager and search metrics.",
      "description": "Search interface over the UNDRR syndication API: query box, facets, active filters, result list or cards, pager and search metrics. UI strings are translatable through the labels prop; most of them can also be set from a data-labels JSON attribute, but function-valued plural forms cannot be serialized to JSON and need the prop. The widget renders the search response as unsanitised HTML so Elasticsearch highlight markup survives, which puts the configured searchEndpoint inside its trust boundary: point it only at a service trusted to return safe HTML.",
      "import": "import { SyndicationSearchWidget } from \"@undrr/undrr-mangrove/components/SyndicationSearchWidget.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-syndicated-search--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-syndicated-search.json",
      "requiresReact": true,
      "hydration": true,
      "vanillaModule": false,
      "customProperties": 2
    },
    {
      "id": "components-syndicated-search-display-modes",
      "name": "SyndicationSearchWidget",
      "summary": "SyndicationSearchWidget component.\nMain entry point for the UNDRR Syndication Search Widget.",
      "description": "SyndicationSearchWidget component.\nMain entry point for the UNDRR Syndication Search Widget.",
      "import": "import { SyndicationSearchWidget } from \"@undrr/undrr-mangrove/components/SyndicationSearchWidget.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-syndicated-search-display-modes--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-syndicated-search-display-modes.json",
      "requiresReact": true,
      "vanillaModule": false
    },
    {
      "id": "components-syndicated-search-filters",
      "name": "SyndicationSearchWidget",
      "summary": "SyndicationSearchWidget component.\nMain entry point for the UNDRR Syndication Search Widget.",
      "description": "SyndicationSearchWidget component.\nMain entry point for the UNDRR Syndication Search Widget.",
      "import": "import { SyndicationSearchWidget } from \"@undrr/undrr-mangrove/components/SyndicationSearchWidget.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-syndicated-search-filters--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-syndicated-search-filters.json",
      "requiresReact": true,
      "vanillaModule": false
    },
    {
      "id": "components-syndicated-search-integrations",
      "name": "SyndicationSearchWidget",
      "summary": "SyndicationSearchWidget component.\nMain entry point for the UNDRR Syndication Search Widget.",
      "description": "SyndicationSearchWidget component.\nMain entry point for the UNDRR Syndication Search Widget.",
      "import": "import { SyndicationSearchWidget } from \"@undrr/undrr-mangrove/components/SyndicationSearchWidget.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-syndicated-search-integrations--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-syndicated-search-integrations.json",
      "requiresReact": true,
      "vanillaModule": false
    },
    {
      "id": "components-syndicated-search-layouts",
      "name": "SyndicationSearchWidget",
      "summary": "SyndicationSearchWidget component.\nMain entry point for the UNDRR Syndication Search Widget.",
      "description": "SyndicationSearchWidget component.\nMain entry point for the UNDRR Syndication Search Widget.",
      "import": "import { SyndicationSearchWidget } from \"@undrr/undrr-mangrove/components/SyndicationSearchWidget.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-syndicated-search-layouts--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-syndicated-search-layouts.json",
      "requiresReact": true,
      "vanillaModule": false
    },
    {
      "id": "components-syndicated-search-toggles",
      "name": "SyndicationSearchWidget",
      "summary": "SyndicationSearchWidget component.\nMain entry point for the UNDRR Syndication Search Widget.",
      "description": "SyndicationSearchWidget component.\nMain entry point for the UNDRR Syndication Search Widget.",
      "import": "import { SyndicationSearchWidget } from \"@undrr/undrr-mangrove/components/SyndicationSearchWidget.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-syndicated-search-toggles--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-syndicated-search-toggles.json",
      "requiresReact": true,
      "vanillaModule": false
    },
    {
      "id": "components-table",
      "name": "TableTag",
      "summary": "Styled HTML table with compact size, striped and bordered variants, and stacked or horizontally scrolling responsive options.",
      "description": "Styled HTML table with compact size, striped/border variants and stacked/scroll options. For wide plain HTML tables, wrap the native table in .mg-table-scroll-region with role=region, a translated aria-label and tabindex=0. React responsive=scroll generates this wrapper; scrollLabel supplies its accessible name.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-table--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-table.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-tabs",
      "name": "Tab",
      "summary": "Tabbed content: centred horizontal tabs that scroll at every width, with opt-in stacked disclosures below 480px. Requires tabs.js for ARIA semantics, keyboard navigation and selection.",
      "description": "Tabbed content with centred, softly filled horizontal tabs that scroll at every viewport width, or explicit stacked disclosures. Opt into disclosures below 480px with stackOnMobile (React) or the presence-based data-mg-js-tabs-stack-on-mobile attribute (HTML); horizontal scrolling remains the default. Only the horizontal rail scrolls; panels sit outside the tablist. Requires tabs.js as an ES module for ARIA semantics, keyboard navigation, selection and overflow indicators. Without JavaScript, panel content remains visible. Set labels.tabListLabel (React) or data-mg-js-tabs-label (HTML) to name the tablist. Existing interleaved HTML is enhanced at runtime. Before removing dynamically initialised markup, call mgTabsDestroy(scope), or pass { signal } as the third argument to mgTabs or mgTabsRuntime and abort it. A tab set removed without either is suspended, not destroyed: once a rail resize observer notification (horizontal sets, usually within a frame in Chromium), a window resize or hash change (the runtime keeps one listener for each while any set is initialised), an orientation change or font load, or a later mgTabs/mgTabsRuntime call finds it detached, its window, document.fonts and ResizeObserver registrations are released while markup, in-container listeners and selection stay intact. A re-attached set resumes on the next pointer press, focus, key press or click inside it, window resize or hash change, or mgTabs/mgTabsRuntime call; an interaction resume also resumes other re-attached sets, including nested ones. On resume, a URL hash changed while suspended selects its panel (also on React re-render or mgTabsDestroy(container, true) plus re-init), and a stackOnMobile breakpoint crossed while suspended switches layout; after an interaction both wait until it has been handled, so a tap acts on the visible layout and its selection wins. Until a removal is found its listeners stay registered. Security (React path only): a tab object's data string is injected as raw HTML and is NOT sanitised — unlike TextCta, Drawer and the card components, Tab does not run DOMPurify, because a panel legitimately carries tables, forms and embeds that a sanitiser would strip. Sanitise it where tabdata is built. The vanilla HTML path has no equivalent: the panel markup is already in the page and tabs.js only enhances it.",
      "import": "import { Tab } from \"@undrr/undrr-mangrove/components/Tab.js\";",
      "importRequiresDom": true,
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-tabs--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-tabs.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 14
    },
    {
      "id": "components-tag",
      "name": "Tag",
      "summary": "Compact taxonomy label with theme-owned colours and radius. Variants: default, secondary, outline, accent. Spans for static metadata, anchors for destinations.",
      "description": "Compact taxonomy label with theme-owned colours and radius. Variants: default, secondary, outline, accent. Use spans for static metadata and anchors with href for destinations. Container children receive the same styling; static and linked tags share compact geometry (28px minimum height, 24px minimum width); links have visible keyboard focus.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-tag--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-tag.json",
      "vanillaHtml": true,
      "vanillaModule": false,
      "customProperties": 3
    },
    {
      "id": "components-typography",
      "name": "Typography",
      "summary": "Base typography styles applied to standard HTML heading and body elements. Use `mg-details` on a `<details>` element to apply Mangrove styled disclosure.",
      "description": "Base typography styles applied to standard HTML heading and body elements. Use `mg-details` on a `<details>` element to apply Mangrove styled disclosure.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-typography--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-typography.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-typography-links",
      "name": "Link",
      "summary": "Link styles applied to standard anchor elements. Underlined by default with interactive color.",
      "description": "Link styles applied to standard anchor elements. Underlined by default with interactive color.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-typography-links--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-typography-links.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-typography-typography-integration-example",
      "name": "TypographyIntegrationExample",
      "summary": "Integration example showing Mangrove typography classes in a page context.",
      "description": "Integration example showing Mangrove typography classes in a page context.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-typography-typography-integration-example--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-typography-typography-integration-example.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "components-user-feedback",
      "name": "UserFeedback",
      "summary": "Standalone page-usefulness prompt, generally placed as the sibling immediately before Footer. Response storage and consent remain product-owned.",
      "description": "Standalone page-usefulness prompt generally paired as the sibling immediately before Footer. Response storage and consent remain product-owned: keep the response callback separate from the report link, so a product can send the binary response to its own analytics service without Mangrove owning storage or consent decisions.",
      "import": "import UserFeedback from \"@undrr/undrr-mangrove/components/UserFeedback.js\";",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-user-feedback--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-user-feedback.json",
      "requiresReact": true,
      "hydration": true,
      "vanillaModule": false
    },
    {
      "id": "components-utility-css",
      "name": "UtilityCSS",
      "summary": "CSS utility class reference (spacing, visibility, text alignment, floats).",
      "description": "CSS utility class reference (spacing, visibility, text alignment, floats).",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/components-utility-css--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/components-utility-css.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "patterns-article-story",
      "name": "ArticleStory",
      "summary": "A news or event article page: headline, header image, reading body and related content cards.",
      "description": "A news or event article page: headline, header image, reading body and related content cards. imageProminence controls the header treatment: bleeds full width (large), stays in the reading column (compact), or runs a two-column Hero split band (split). heroImage controls whether the header shows the same image used for teasers/social cards, a different one, or none. Composes VerticalCard, TableOfContents and mg-reading.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/patterns-article-story--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/patterns-article-story.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "patterns-content-hub",
      "name": "ContentHub",
      "summary": "A named group of pages inside the parent site — a programme, a monitor, a guidance collection — carrying the same identity and section links on every page.",
      "description": "A named group of pages inside the parent site — a programme, a monitor, a guidance collection — carrying the same identity and section links on every page so readers move sideways without returning to a landing page. Composes HubHeader with shipped cards, hero and contents components.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/patterns-content-hub--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/patterns-content-hub.json",
      "vanillaHtml": true,
      "vanillaModule": true,
      "vanillaScripts": [
        "js/hub-header.js"
      ],
      "customProperties": 11
    },
    {
      "id": "patterns-landing-pages",
      "name": "LandingPage",
      "summary": "Three UNDRR landing page shapes: topic or initiative, report or publication, and collection index.",
      "description": "Three UNDRR landing page shapes: topic or initiative (hero, route cards, supporting band), report or publication (feature band and a reading column with contents), and collection index (grouped rows of covers).",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/patterns-landing-pages--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/patterns-landing-pages.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "example-boilerplate-component",
      "name": "Boilerplate",
      "summary": "Boilerplate component.\n\nClone this directory when creating a new component. Replace the name,\nprops, and markup with your own.",
      "description": "Boilerplate component.\n\nClone this directory when creating a new component. Replace the name,\nprops, and markup with your own.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/example-boilerplate-component--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/example-boilerplate-component.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "example-form-validation",
      "name": "Formvalidation",
      "summary": "Interactive form validation example demonstrating error summary blocks, field-level error messages, and snackbar toast notifications with multi-language support.",
      "description": "Interactive form validation example demonstrating error summary blocks, field-level error messages, and snackbar toast notifications with multi-language support.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/example-form-validation--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/example-form-validation.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "example-newsletter-promotion",
      "name": "Newsletterpromotion",
      "summary": "Interactive newsletter promotion pattern demonstrating email input validation, topic preferences checkboxes, submission states, and confirmation messaging.",
      "description": "Interactive newsletter promotion pattern demonstrating email input validation, topic preferences checkboxes, submission states, and confirmation messaging.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/example-newsletter-promotion--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/example-newsletter-promotion.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "example-page-template-example",
      "name": "PageTemplateExample",
      "summary": "Complete page templates showing how to compose Mangrove components into working UNDRR-branded pages with all required scripts and assets.",
      "description": "Complete page templates showing how to compose Mangrove components into working UNDRR-branded pages with all required scripts and assets.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/example-page-template-example--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/example-page-template-example.json",
      "vanillaHtml": true,
      "vanillaModule": false
    },
    {
      "id": "example-typescript-component",
      "name": "TypeScriptExampleComponent",
      "summary": "Example TypeScript component that wraps CtaButton with typed props.",
      "description": "Example TypeScript component that wraps CtaButton with typed props.\n\nThis component exists as a reference for writing TypeScript components\nin the Mangrove library. See the\n[component standards](?path=/docs/contributing-component-standards--docs)\nfor conventions and best practices.",
      "docsUrl": "https://mangrove.undrr.org/?path=/docs/example-typescript-component--docs",
      "detailsUrl": "https://mangrove.undrr.org/ai-components/example-typescript-component.json",
      "vanillaHtml": true,
      "vanillaModule": false
    }
  ],
  "generatedAt": "2026-09-27T05:43:42.738Z"
}