@nldd/design-system 0.8.96 → 0.8.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README.md +14 -10
  2. package/custom-elements.json +494 -92
  3. package/dist/components/components.js +609 -177
  4. package/dist/components/content/icon/icon-aliases.js +1 -1
  5. package/dist/components/content/icon/icon-aliases.js.map +1 -1
  6. package/dist/components/content/icon/icon-gallery-status.d.ts.map +1 -1
  7. package/dist/components/content/icon/icon-gallery-status.js +15 -4
  8. package/dist/components/content/icon/icon-gallery-status.js.map +1 -1
  9. package/dist/components/content/icon/icon-registry.js +12 -12
  10. package/dist/components/content/icon/icon-registry.js.map +1 -1
  11. package/dist/components/content/image/image.d.ts +19 -3
  12. package/dist/components/content/image/image.d.ts.map +1 -1
  13. package/dist/components/content/image/image.js +25 -4
  14. package/dist/components/content/image/image.js.map +1 -1
  15. package/dist/components/content/image/image.styles.d.ts.map +1 -1
  16. package/dist/components/content/image/image.styles.js +36 -0
  17. package/dist/components/content/image/image.styles.js.map +1 -1
  18. package/dist/components/content/image/image.template.d.ts.map +1 -1
  19. package/dist/components/content/image/image.template.js +13 -1
  20. package/dist/components/content/image/image.template.js.map +1 -1
  21. package/dist/components/content/rich-text/rich-text.d.ts +25 -12
  22. package/dist/components/content/rich-text/rich-text.d.ts.map +1 -1
  23. package/dist/components/content/rich-text/rich-text.js +25 -12
  24. package/dist/components/content/rich-text/rich-text.js.map +1 -1
  25. package/dist/components/{icon-DQHT2C7z.js → icon-D_ZGezHx.js} +13 -13
  26. package/dist/components/{icon-button-mevRsl4C.js → icon-button-NN0SrgS3.js} +1 -1
  27. package/dist/components/index.d.ts +1 -1
  28. package/dist/components/index.d.ts.map +1 -1
  29. package/dist/components/index.js +1 -1
  30. package/dist/components/index.js.map +1 -1
  31. package/dist/components/layout/box/box.d.ts +1 -1
  32. package/dist/components/layout/box/box.js +1 -1
  33. package/dist/components/layout/container/container.d.ts.map +1 -1
  34. package/dist/components/layout/container/container.js +2 -1
  35. package/dist/components/layout/container/container.js.map +1 -1
  36. package/dist/components/layout/page/page.d.ts +9 -3
  37. package/dist/components/layout/page/page.d.ts.map +1 -1
  38. package/dist/components/layout/page/page.js +36 -13
  39. package/dist/components/layout/page/page.js.map +1 -1
  40. package/dist/components/layout/page/page.styles.js +1 -1
  41. package/dist/components/layout/page-sections/full-bleed-section/full-bleed-section.d.ts +2 -0
  42. package/dist/components/layout/page-sections/full-bleed-section/full-bleed-section.d.ts.map +1 -1
  43. package/dist/components/layout/page-sections/full-bleed-section/full-bleed-section.js +3 -1
  44. package/dist/components/layout/page-sections/full-bleed-section/full-bleed-section.js.map +1 -1
  45. package/dist/components/layout/page-sections/full-bleed-section/full-bleed-section.styles.d.ts.map +1 -1
  46. package/dist/components/layout/page-sections/full-bleed-section/full-bleed-section.styles.js +5 -0
  47. package/dist/components/layout/page-sections/full-bleed-section/full-bleed-section.styles.js.map +1 -1
  48. package/dist/components/layout/page-sections/hero/hero.d.ts +57 -11
  49. package/dist/components/layout/page-sections/hero/hero.d.ts.map +1 -1
  50. package/dist/components/layout/page-sections/hero/hero.js +158 -15
  51. package/dist/components/layout/page-sections/hero/hero.js.map +1 -1
  52. package/dist/components/layout/page-sections/hero/hero.styles.d.ts.map +1 -1
  53. package/dist/components/layout/page-sections/hero/hero.styles.js +95 -41
  54. package/dist/components/layout/page-sections/hero/hero.styles.js.map +1 -1
  55. package/dist/components/layout/page-sections/one-half-one-half-section/one-half-one-half-section.d.ts +4 -0
  56. package/dist/components/layout/page-sections/one-half-one-half-section/one-half-one-half-section.d.ts.map +1 -1
  57. package/dist/components/layout/page-sections/one-half-one-half-section/one-half-one-half-section.js +8 -1
  58. package/dist/components/layout/page-sections/one-half-one-half-section/one-half-one-half-section.js.map +1 -1
  59. package/dist/components/layout/page-sections/one-half-one-half-section/one-half-one-half-section.styles.d.ts.map +1 -1
  60. package/dist/components/layout/page-sections/one-half-one-half-section/one-half-one-half-section.styles.js +13 -0
  61. package/dist/components/layout/page-sections/one-half-one-half-section/one-half-one-half-section.styles.js.map +1 -1
  62. package/dist/components/layout/page-sections/one-third-two-thirds-section/one-third-two-thirds-section.d.ts +4 -0
  63. package/dist/components/layout/page-sections/one-third-two-thirds-section/one-third-two-thirds-section.d.ts.map +1 -1
  64. package/dist/components/layout/page-sections/one-third-two-thirds-section/one-third-two-thirds-section.js +8 -1
  65. package/dist/components/layout/page-sections/one-third-two-thirds-section/one-third-two-thirds-section.js.map +1 -1
  66. package/dist/components/layout/page-sections/one-third-two-thirds-section/one-third-two-thirds-section.styles.d.ts.map +1 -1
  67. package/dist/components/layout/page-sections/one-third-two-thirds-section/one-third-two-thirds-section.styles.js +17 -0
  68. package/dist/components/layout/page-sections/one-third-two-thirds-section/one-third-two-thirds-section.styles.js.map +1 -1
  69. package/dist/components/layout/page-sections/page-section-controls.d.ts +11 -1
  70. package/dist/components/layout/page-sections/page-section-controls.d.ts.map +1 -1
  71. package/dist/components/layout/page-sections/page-section-controls.js +11 -2
  72. package/dist/components/layout/page-sections/page-section-controls.js.map +1 -1
  73. package/dist/components/layout/page-sections/sidebar-section/sidebar-section.d.ts +5 -1
  74. package/dist/components/layout/page-sections/sidebar-section/sidebar-section.d.ts.map +1 -1
  75. package/dist/components/layout/page-sections/sidebar-section/sidebar-section.js +6 -2
  76. package/dist/components/layout/page-sections/sidebar-section/sidebar-section.js.map +1 -1
  77. package/dist/components/layout/page-sections/sidebar-section/sidebar-section.styles.d.ts.map +1 -1
  78. package/dist/components/layout/page-sections/sidebar-section/sidebar-section.styles.js +11 -10
  79. package/dist/components/layout/page-sections/sidebar-section/sidebar-section.styles.js.map +1 -1
  80. package/dist/components/layout/page-sections/simple-section/simple-section.d.ts +2 -0
  81. package/dist/components/layout/page-sections/simple-section/simple-section.d.ts.map +1 -1
  82. package/dist/components/layout/page-sections/simple-section/simple-section.js +3 -2
  83. package/dist/components/layout/page-sections/simple-section/simple-section.js.map +1 -1
  84. package/dist/components/layout/page-sections/simple-section/simple-section.styles.js +2 -2
  85. package/dist/components/layout/page-sections/two-thirds-one-third-section/two-thirds-one-third-section.d.ts +4 -0
  86. package/dist/components/layout/page-sections/two-thirds-one-third-section/two-thirds-one-third-section.d.ts.map +1 -1
  87. package/dist/components/layout/page-sections/two-thirds-one-third-section/two-thirds-one-third-section.js +8 -1
  88. package/dist/components/layout/page-sections/two-thirds-one-third-section/two-thirds-one-third-section.js.map +1 -1
  89. package/dist/components/layout/page-sections/two-thirds-one-third-section/two-thirds-one-third-section.styles.d.ts.map +1 -1
  90. package/dist/components/layout/page-sections/two-thirds-one-third-section/two-thirds-one-third-section.styles.js +17 -0
  91. package/dist/components/layout/page-sections/two-thirds-one-third-section/two-thirds-one-third-section.styles.js.map +1 -1
  92. package/dist/components/layout/sheet/sheet.js +1 -1
  93. package/dist/components/layout/sheet/sheet.js.map +1 -1
  94. package/dist/components/layout/{app-view/app-view.d.ts → shell/shell.d.ts} +11 -11
  95. package/dist/components/layout/shell/shell.d.ts.map +1 -0
  96. package/dist/components/layout/{app-view/app-view.js → shell/shell.js} +24 -24
  97. package/dist/components/layout/shell/shell.js.map +1 -0
  98. package/dist/components/layout/shell/shell.styles.d.ts +2 -0
  99. package/dist/components/layout/shell/shell.styles.d.ts.map +1 -0
  100. package/dist/components/layout/{app-view/app-view.styles.js → shell/shell.styles.js} +8 -8
  101. package/dist/components/layout/shell/shell.styles.js.map +1 -0
  102. package/dist/components/layout/shell/shell.template.d.ts +4 -0
  103. package/dist/components/layout/shell/shell.template.d.ts.map +1 -0
  104. package/dist/components/layout/shell/shell.template.js +9 -0
  105. package/dist/components/layout/shell/shell.template.js.map +1 -0
  106. package/dist/components/layout/split-views/bar-split-view/bar-split-view.js +1 -1
  107. package/dist/components/layout/split-views/bar-split-view/bar-split-view.js.map +1 -1
  108. package/dist/components/layout/split-views/navigation-split-view/navigation-split-view.d.ts +1 -1
  109. package/dist/components/layout/split-views/navigation-split-view/navigation-split-view.js +1 -1
  110. package/dist/components/layout/split-views/side-by-side-split-view/side-by-side-split-view.d.ts +1 -1
  111. package/dist/components/layout/split-views/side-by-side-split-view/side-by-side-split-view.js +1 -1
  112. package/dist/components/lists-and-tables/cells/text-cell/text-cell.styles.d.ts.map +1 -1
  113. package/dist/components/lists-and-tables/cells/text-cell/text-cell.styles.js +2 -0
  114. package/dist/components/lists-and-tables/cells/text-cell/text-cell.styles.js.map +1 -1
  115. package/dist/components/lists-and-tables/cells/title-cell/title-cell.styles.d.ts.map +1 -1
  116. package/dist/components/lists-and-tables/cells/title-cell/title-cell.styles.js +2 -0
  117. package/dist/components/lists-and-tables/cells/title-cell/title-cell.styles.js.map +1 -1
  118. package/dist/components/lists-and-tables/list-item/list-item.d.ts +15 -5
  119. package/dist/components/lists-and-tables/list-item/list-item.d.ts.map +1 -1
  120. package/dist/components/lists-and-tables/list-item/list-item.js +20 -7
  121. package/dist/components/lists-and-tables/list-item/list-item.js.map +1 -1
  122. package/dist/components/lists-and-tables/list-item-segment/list-item-segment.d.ts +4 -1
  123. package/dist/components/lists-and-tables/list-item-segment/list-item-segment.d.ts.map +1 -1
  124. package/dist/components/lists-and-tables/list-item-segment/list-item-segment.js +8 -2
  125. package/dist/components/lists-and-tables/list-item-segment/list-item-segment.js.map +1 -1
  126. package/dist/components/lists-and-tables/list-item-segment/list-item-segment.template.d.ts +1 -1
  127. package/dist/components/lists-and-tables/list-item-segment/list-item-segment.template.d.ts.map +1 -1
  128. package/dist/components/lists-and-tables/list-item-segment/list-item-segment.template.js +1 -1
  129. package/dist/components/lists-and-tables/list-item-segment/list-item-segment.template.js.map +1 -1
  130. package/dist/components/navigation/menu-bar-item/menu-bar-item.d.ts +5 -0
  131. package/dist/components/navigation/menu-bar-item/menu-bar-item.d.ts.map +1 -1
  132. package/dist/components/navigation/menu-bar-item/menu-bar-item.js +13 -1
  133. package/dist/components/navigation/menu-bar-item/menu-bar-item.js.map +1 -1
  134. package/dist/components/navigation/menu-bar-item/menu-bar-item.styles.d.ts.map +1 -1
  135. package/dist/components/navigation/menu-bar-item/menu-bar-item.styles.js +12 -2
  136. package/dist/components/navigation/menu-bar-item/menu-bar-item.styles.js.map +1 -1
  137. package/dist/components/navigation/menu-bar-item/menu-bar-item.template.d.ts.map +1 -1
  138. package/dist/components/navigation/menu-bar-item/menu-bar-item.template.js +11 -10
  139. package/dist/components/navigation/menu-bar-item/menu-bar-item.template.js.map +1 -1
  140. package/dist/components/navigation/top-title-bar/top-title-bar.js +1 -1
  141. package/dist/components/navigation/top-title-bar/top-title-bar.js.map +1 -1
  142. package/dist/components/status-and-feedback/status-bar/status-bar.d.ts +10 -0
  143. package/dist/components/status-and-feedback/status-bar/status-bar.d.ts.map +1 -1
  144. package/dist/components/status-and-feedback/status-bar/status-bar.js +21 -0
  145. package/dist/components/status-and-feedback/status-bar/status-bar.js.map +1 -1
  146. package/dist/css/document-reset.css +3 -3
  147. package/dist/css/rich-text.css +36 -90
  148. package/dist/nldd.min.js +506 -349
  149. package/dist/types/vue.d.ts +67 -24
  150. package/dist/utilities/page-section-mixin.d.ts +5 -0
  151. package/dist/utilities/page-section-mixin.d.ts.map +1 -1
  152. package/dist/utilities/page-section-mixin.js +10 -1
  153. package/dist/utilities/page-section-mixin.js.map +1 -1
  154. package/dist/utilities/scroll-mode-controller.d.ts +29 -13
  155. package/dist/utilities/scroll-mode-controller.d.ts.map +1 -1
  156. package/dist/utilities/scroll-mode-controller.js +48 -13
  157. package/dist/utilities/scroll-mode-controller.js.map +1 -1
  158. package/package.json +4 -4
  159. package/dist/components/layout/app-view/app-view.d.ts.map +0 -1
  160. package/dist/components/layout/app-view/app-view.js.map +0 -1
  161. package/dist/components/layout/app-view/app-view.styles.d.ts +0 -2
  162. package/dist/components/layout/app-view/app-view.styles.d.ts.map +0 -1
  163. package/dist/components/layout/app-view/app-view.styles.js.map +0 -1
  164. package/dist/components/layout/app-view/app-view.template.d.ts +0 -4
  165. package/dist/components/layout/app-view/app-view.template.d.ts.map +0 -1
  166. package/dist/components/layout/app-view/app-view.template.js +0 -9
  167. package/dist/components/layout/app-view/app-view.template.js.map +0 -1
  168. package/dist/components/palettes.html +0 -245
  169. package/dist/components/sample-images/butterfly-1200.jpg +0 -0
  170. package/dist/components/sample-images/butterfly-1600.jpg +0 -0
  171. package/dist/components/sample-images/butterfly-480.jpg +0 -0
  172. package/dist/components/sample-images/butterfly-960.jpg +0 -0
  173. package/dist/palettes.html +0 -245
  174. package/dist/sample-images/butterfly-1200.jpg +0 -0
  175. package/dist/sample-images/butterfly-1600.jpg +0 -0
  176. package/dist/sample-images/butterfly-480.jpg +0 -0
  177. package/dist/sample-images/butterfly-960.jpg +0 -0
@@ -3970,7 +3970,7 @@
3970
3970
  "declarations": [
3971
3971
  {
3972
3972
  "kind": "class",
3973
- "description": "Wraps a native `<img>` with design-system styling: corner radius variants, aspect-ratio reservation, object-fit/position control, optional caption + credit. Renders as `<figure>` + `<figcaption>` only when a caption or credit is set — otherwise just the image, no extra wrapping. Hybrid source: the `src` attribute renders an internal `<img>`. To use a custom `<img>` or `<picture>` (e.g. with art-direction sources), slot it into the default slot and we'll style and wrap it like our own image.",
3973
+ "description": "Wraps a native `<img>` with design-system styling: corner radius variants, aspect-ratio reservation, object-fit/position control, optional caption + credit. Renders as `<figure>` + `<figcaption>` only when a caption or credit is set — otherwise just the image, no extra wrapping. Hybrid source: the `src` attribute renders an internal `<img>`. To use a custom `<img>` or `<picture>` (e.g. with art-direction sources), slot it into the default slot and we'll style and wrap it like our own image. Without an image (no `src`, `srcset`, `lqip` or slotted media) it shows a neutral area with an image icon, in the box, shape and caption a real image would get: a place where an image belongs, for a prototype or a pattern, or an image someone forgot. Without `aspect-ratio` that area is 16/9. While the built-in `<img>` loads without an `lqip`, the same area shows without the icon, and it goes once the image is in.",
3974
3974
  "name": "NLDDImage",
3975
3975
  "members": [
3976
3976
  {
@@ -4296,7 +4296,7 @@
4296
4296
  },
4297
4297
  "default": "''",
4298
4298
  "fieldName": "lqip",
4299
- "description": "Low-quality image placeholder as a CSV string `\"base,c1,c2,c3,c4,c5,c6\"` — seven 0-255 bytes, each packing an 8-bit Oklab triplet (2 bits L, 3 bits a, 3 bits b). The first is the base color shown outside the cell gradients; the other six are per-cell colors in row-major 3×2 order. Generate via the encoder in `lqip-encoder.ts` or via the \"LQIP encoder tool\" Storybook story. Extends Lean Rada's CSS-only LQIP (https://leanrada.com/notes/css-only-lqip/) with per-cell hue — Lean's original format encodes grayscale cells only; ours encodes a color per cell so multi-color subjects survive the placeholder."
4299
+ "description": "Loading preview (LQIP, low-quality image placeholder) as a CSV string `\"base,c1,c2,c3,c4,c5,c6\"` — seven 0-255 bytes, each packing an 8-bit Oklab triplet (2 bits L, 3 bits a, 3 bits b). The first is the base color shown outside the cell gradients; the other six are per-cell colors in row-major 3×2 order. Generate via the encoder in `lqip-encoder.ts` or via the \"LQIP encoder tool\" Storybook story. Extends Lean Rada's CSS-only LQIP (https://leanrada.com/notes/css-only-lqip/) with per-cell hue — Lean's original format encodes grayscale cells only; ours encodes a color per cell so multi-color subjects survive the preview."
4300
4300
  },
4301
4301
  {
4302
4302
  "name": "translations",
@@ -4662,7 +4662,7 @@
4662
4662
  "declarations": [
4663
4663
  {
4664
4664
  "kind": "class",
4665
- "description": "A container for rich text content that automatically applies responsive typography. Uses no shadow DOM so styles apply to all nested elements. Import nldd-rich-text.css globally in your application. The rich text lays out its direct children in a grid: the vertical rhythm between headings, paragraphs and lists, and the width zones below, apply to those children only. A single wrapper `div` without `class`, `style`, `role` or `data-width`, as a markdown renderer or a component root produces it, is passed through with `display: contents`, so its children count as direct. Any other wrapper becomes a single grid item, and the paragraphs inside it lose their spacing. Children are placed in three zones: text (headings, paragraphs, lists, blockquote, div/section) reads at the `main` size; media and tables (img, figure, video, iframe, table) get the `wide` accent; everything else, code blocks and every component, gets the full `full` span with `justify-self: start`, so the room is available without being forced. Overridable per child with `data-width=\"main\" | \"wide\" | \"full\"`. In the left-aligned layout, wide and full read as a bleed to the right; with `centered` they are symmetrical.",
4665
+ "description": "A container for rich text content that automatically applies responsive typography. Uses no shadow DOM so styles apply to all nested elements. Import nldd-rich-text.css globally in your application. The rich text lays out its direct children in a grid: the vertical rhythm between headings, paragraphs and lists, and the width zones below, apply to those children only. A single wrapper `div` without `class`, `style`, `role` or `data-rich-text-width`, as a markdown renderer or a component root produces it, is passed through with `display: contents`, so its children count as direct. Any other wrapper becomes a single grid item, and the paragraphs inside it lose their spacing. The headings keep one size on every width, the one they have on a phone. A heading in running text sits in a column as wide as a line of reading, on any screen, so its relation to the text beside it does not change and it has no reason to grow. Growing, an h2 on a wide screen was more than twice the size of the text, and an article broke into blocks at every heading. Page and section titles do grow: use nldd-title for those. Children are placed in three zones. A child belongs to the text unless it is listed, so it reads at the `main` size and is never wider than a line: text (headings, paragraphs, lists, blockquote, div/section) and every component that is not named below, such as nldd-box, nldd-card, nldd-banner, nldd-list and a button, and code (pre, nldd-code-viewer), which scrolls inside its block when a line is longer. Media, tables and a step bar (img, figure, video, iframe, table, nldd-table, nldd-image, nldd-step-bar) get the `wide` accent. What needs the room gets the `full` span: hr, nldd-collection and nldd-container. A child takes the room it needs inside its zone (`justify-self: start`), so the room is available without being forced. Overridable per child with `data-rich-text-width=\"main\" | \"wide\" | \"full\"`. In the left-aligned layout, wide and full read as a bleed to the right; with `centered` they are symmetrical.",
4666
4666
  "name": "NLDDRichText",
4667
4667
  "members": [
4668
4668
  {
@@ -4759,7 +4759,7 @@
4759
4759
  },
4760
4760
  "default": "false",
4761
4761
  "fieldName": "hyphens",
4762
- "description": "Opt-in automatic hyphenation for running text (p, li, dd). Needs a correct `lang` on the page (`lang=\"nl\"` on `<html>`, for instance): without language information the browser does not hyphenate. An `overflow-wrap: break-word` safety net on p/li is always on, independent of this attribute, so long URLs and compounds break neatly instead of overflowing even without a dictionary."
4762
+ "description": "Opt-in automatic hyphenation for running text (p, li, dd). Needs a correct `lang` on the page (`lang=\"nl\"` on `<html>`, for instance): without language information the browser does not hyphenate. An `overflow-wrap: break-word` safety net on headings, p and li is always on, independent of this attribute, so a word wider than the column breaks instead of overflowing, without a hyphen; headings never get one."
4763
4763
  }
4764
4764
  ],
4765
4765
  "superclass": {
@@ -6709,10 +6709,10 @@
6709
6709
  },
6710
6710
  {
6711
6711
  "kind": "js",
6712
- "name": "NLDDAppView",
6712
+ "name": "NLDDShell",
6713
6713
  "declaration": {
6714
- "name": "NLDDAppView",
6715
- "module": "./layout/app-view/app-view.js"
6714
+ "name": "NLDDShell",
6715
+ "module": "./layout/shell/shell.js"
6716
6716
  }
6717
6717
  },
6718
6718
  {
@@ -22786,70 +22786,6 @@
22786
22786
  }
22787
22787
  ]
22788
22788
  },
22789
- {
22790
- "kind": "javascript-module",
22791
- "path": "src/components/layout/app-view/app-view.ts",
22792
- "declarations": [
22793
- {
22794
- "kind": "class",
22795
- "description": "The required root shell of a Nederlandse Digitale Dienst application. Always contains a split view or an nldd-page as direct content. The document font comes from the package stylesheet (`@nldd/design-system/styles`), not from this component: it gives `body` the body font and content color as soon as an app-view is on the page, inside `@layer reset` so any rule of your own wins. Import only the tokens (`/styles/tokens`) and text you write in the light DOM keeps the browser default. Set background=\"tinted\" to give the whole application a tinted background. All descendants read --context-parent-background-color via --_app-view-background-color automatically. Individual components can override locally with their own background attribute. The same background color is forced on `document.body` so that browser- chrome surfaces (iOS overscroll bounce, status bar, page-margin areas) blend with the app instead of revealing the user-agent's default white. Cleared when the app-view disconnects. The app scrolls the DOCUMENT (root mode) or lets each `nldd-page` scroll inside its pane (nested mode). The mode is derived from the outermost horizontal split view: one column means the document scrolls, several columns mean the panes do. An app without such a split view is a single column at every width and therefore scrolls the document too — nested scrolling would cost it the rubber-band and the collapsing browser toolbar on iOS for nothing. Set `--context-scroll-mode` on the `nldd-app-view` itself to override the derived mode; an inherited value loses from it. In nested scroll mode `overscroll-behavior: none` is set on `document.documentElement` and `document.body` while the app-view is connected. Combined with `overscroll-behavior: contain` on `nldd-page`'s scroll target, this prevents iOS rubber-band on the viewport when scroll gestures land outside an `nldd-page` (e.g. on a top-bar). In root scroll mode the document itself is the scroller, so this is lifted to let the native rubber-band happen. Cleared on last disconnect.",
22796
- "name": "NLDDAppView",
22797
- "members": [
22798
- {
22799
- "kind": "field",
22800
- "name": "background",
22801
- "type": {
22802
- "text": "'base' | 'tinted'"
22803
- },
22804
- "default": "'base'",
22805
- "attribute": "background",
22806
- "reflects": true
22807
- }
22808
- ],
22809
- "attributes": [
22810
- {
22811
- "name": "background",
22812
- "type": {
22813
- "text": "'base' | 'tinted'"
22814
- },
22815
- "default": "'base'",
22816
- "fieldName": "background",
22817
- "description": "Background color (cascades to descendants)"
22818
- }
22819
- ],
22820
- "superclass": {
22821
- "name": "LitElement",
22822
- "package": "lit"
22823
- },
22824
- "tagName": "nldd-app-view",
22825
- "customElement": true,
22826
- "slots": [
22827
- {
22828
- "name": "",
22829
- "description": "Default slot for the application content"
22830
- }
22831
- ]
22832
- }
22833
- ],
22834
- "exports": [
22835
- {
22836
- "kind": "js",
22837
- "name": "NLDDAppView",
22838
- "declaration": {
22839
- "name": "NLDDAppView",
22840
- "module": "src/components/layout/app-view/app-view.ts"
22841
- }
22842
- },
22843
- {
22844
- "kind": "custom-element-definition",
22845
- "name": "nldd-app-view",
22846
- "declaration": {
22847
- "name": "NLDDAppView",
22848
- "module": "src/components/layout/app-view/app-view.ts"
22849
- }
22850
- }
22851
- ]
22852
- },
22853
22789
  {
22854
22790
  "kind": "javascript-module",
22855
22791
  "path": "src/components/layout/box/box.ts",
@@ -22878,7 +22814,7 @@
22878
22814
  },
22879
22815
  "default": "'tinted'",
22880
22816
  "fieldName": "background",
22881
- "description": "Which surface this box draws, named as it is on nldd-app-view, nldd-page, nldd-split-view-pane and nldd-card. It starts tinted where a card starts base: a box is there to stand out from the page, a card to sit on it. - `tinted` (default): a box on a plain page background. - `base`: a box on an already-tinted parent (the border ring gets +2 palette steps so it still reads against a card-on-card). - `critical`: a region whose actions are destructive or irreversible (a \"danger zone\"), tinted and outlined in critical. It carries no ARIA of its own: unlike nldd-banner this is not an announcement but a permanent part of the page, so the heading and the button labels have to name the danger — color is a reinforcement, never the only signal (WCAG 1.4.1). The box draws the surface and nothing else: it has no padding of its own, the same way nldd-card has none. Put an nldd-container inside it and let that set the inset, so one component owns spacing wherever it is used."
22817
+ "description": "Which surface this box draws, named as it is on nldd-shell, nldd-page, nldd-split-view-pane and nldd-card. It starts tinted where a card starts base: a box is there to stand out from the page, a card to sit on it. - `tinted` (default): a box on a plain page background. - `base`: a box on an already-tinted parent (the border ring gets +2 palette steps so it still reads against a card-on-card). - `critical`: a region whose actions are destructive or irreversible (a \"danger zone\"), tinted and outlined in critical. It carries no ARIA of its own: unlike nldd-banner this is not an announcement but a permanent part of the page, so the heading and the button labels have to name the danger — color is a reinforcement, never the only signal (WCAG 1.4.1). The box draws the surface and nothing else: it has no padding of its own, the same way nldd-card has none. Put an nldd-container inside it and let that set the inset, so one component owns spacing wherever it is used."
22882
22818
  }
22883
22819
  ],
22884
22820
  "superclass": {
@@ -24483,6 +24419,20 @@
24483
24419
  "module": "src/utilities/page-section-mixin.ts"
24484
24420
  }
24485
24421
  },
24422
+ {
24423
+ "kind": "field",
24424
+ "name": "grow",
24425
+ "type": {
24426
+ "text": "boolean"
24427
+ },
24428
+ "default": "false",
24429
+ "attribute": "grow",
24430
+ "reflects": true,
24431
+ "inheritedFrom": {
24432
+ "name": "PageSectionMixin",
24433
+ "module": "src/utilities/page-section-mixin.ts"
24434
+ }
24435
+ },
24486
24436
  {
24487
24437
  "kind": "field",
24488
24438
  "name": "paddingBlock",
@@ -24675,6 +24625,19 @@
24675
24625
  },
24676
24626
  "description": "Minimum section height (any CSS length, e.g. '400px', '100dvh') (mirrors width, which sets the body max-width)."
24677
24627
  },
24628
+ {
24629
+ "name": "grow",
24630
+ "type": {
24631
+ "text": "boolean"
24632
+ },
24633
+ "default": "false",
24634
+ "fieldName": "grow",
24635
+ "inheritedFrom": {
24636
+ "name": "PageSectionMixin",
24637
+ "module": "src/utilities/page-section-mixin.ts"
24638
+ },
24639
+ "description": "Takes the height the page has left, so the footer sits at the bottom of a short page. Without it, nldd-page lets its last section grow."
24640
+ },
24678
24641
  {
24679
24642
  "name": "padding-block",
24680
24643
  "type": {
@@ -24865,7 +24828,7 @@
24865
24828
  "declarations": [
24866
24829
  {
24867
24830
  "kind": "class",
24868
- "description": "A page header with a media area and a text panel (the main) that can stand in six positions. Every area is rectangular. With `main-width=\"full\"` the media area sits as its own strip above or below the panel rather than behind it. On mobile the media always stacks above the full-width panel. Without media the main fills the whole area; with `main-background=\"base\"` that area gets a border so it stays visible on the base surface. `main-background` gives the panel a surface color from the filled categories. Those carry a pure white or black content color along, so components with `color=\"inherit\"` (title, rich-text) are guaranteed to keep their contrast.",
24831
+ "description": "The section that says what a page is for: it names the main goal of what you can find there, draws the eye and is the visual welcome. It has a media area and a text panel (the main) that can stand in eight positions. Every area is rectangular. Use it on pages where a visitor first has to know where they are, such as a home or a topic page; where the title already does that, a section with a title is enough. The image in a hero sets the mood and is never the main content, so the panel always stands on it. Over an image the panel keeps a section gap from its edges, so it reads as a panel on the image rather than a frame cut out of it; with `main-width=\"full\"` it is a strip across the whole image, the same gap from the sides. On mobile the image comes first and the panel below it, indented by the section gap and overlapping the image by 48px. For an image beside text without that relation, use a section with an image beside text instead. Without media the main fills the whole area; with `main-background=\"base\"` that area gets a border so it stays visible on the base surface. The hero is the head of a page and sits right under the top bar, so its top padding is half that of the other page sections: the full distance is meant to separate two sections, and under the top bar it reads as a gap. The bottom keeps the full distance to the section below. Set `padding-top` to place a hero elsewhere. By default the panel falls over the bottom of the image and runs on below it (`layout=\"overlap\"`), so the image keeps its height whatever the content. `layout=\"contained\"` keeps the panel on the image, for a short panel or one that stands at the top or along a side. The height of a hero comes from its image: `media-aspect-ratio`, or a fixed `media-height`. The `height` of the other page sections is not used here: as a minimum height for the whole hero it stretched the panel once that sat below the image. A hero given `height` says so in development. `main-background` gives the panel a surface color from the filled categories. Those carry a pure white or black content color along, so components with `color=\"inherit\"` (title, rich-text) are guaranteed to keep their contrast.",
24869
24832
  "name": "NLDDHero",
24870
24833
  "members": [
24871
24834
  {
@@ -24879,6 +24842,16 @@
24879
24842
  "attribute": "width",
24880
24843
  "reflects": true
24881
24844
  },
24845
+ {
24846
+ "kind": "field",
24847
+ "name": "layout",
24848
+ "type": {
24849
+ "text": "HeroLayout"
24850
+ },
24851
+ "default": "'overlap'",
24852
+ "attribute": "layout",
24853
+ "reflects": true
24854
+ },
24882
24855
  {
24883
24856
  "kind": "field",
24884
24857
  "name": "mainBackground",
@@ -24895,7 +24868,7 @@
24895
24868
  "type": {
24896
24869
  "text": "HeroMainWidth"
24897
24870
  },
24898
- "default": "'1/2'",
24871
+ "default": "'auto'",
24899
24872
  "attribute": "main-width",
24900
24873
  "reflects": true
24901
24874
  },
@@ -24920,6 +24893,26 @@
24920
24893
  "attribute": "media-aspect-ratio",
24921
24894
  "reflects": true
24922
24895
  },
24896
+ {
24897
+ "kind": "field",
24898
+ "name": "overlapSize",
24899
+ "type": {
24900
+ "text": "string"
24901
+ },
24902
+ "default": "''",
24903
+ "attribute": "overlap-size",
24904
+ "reflects": true
24905
+ },
24906
+ {
24907
+ "kind": "field",
24908
+ "name": "mediaHeight",
24909
+ "type": {
24910
+ "text": "string"
24911
+ },
24912
+ "default": "''",
24913
+ "attribute": "media-height",
24914
+ "reflects": true
24915
+ },
24923
24916
  {
24924
24917
  "kind": "field",
24925
24918
  "name": "mediaSrc",
@@ -24984,6 +24977,20 @@
24984
24977
  "module": "src/utilities/page-section-mixin.ts"
24985
24978
  }
24986
24979
  },
24980
+ {
24981
+ "kind": "field",
24982
+ "name": "grow",
24983
+ "type": {
24984
+ "text": "boolean"
24985
+ },
24986
+ "default": "false",
24987
+ "attribute": "grow",
24988
+ "reflects": true,
24989
+ "inheritedFrom": {
24990
+ "name": "PageSectionMixin",
24991
+ "module": "src/utilities/page-section-mixin.ts"
24992
+ }
24993
+ },
24987
24994
  {
24988
24995
  "kind": "field",
24989
24996
  "name": "paddingBlock",
@@ -25151,6 +25158,15 @@
25151
25158
  "description": "Body max-width; 'full' removes the bound (section API)",
25152
25159
  "fieldName": "width"
25153
25160
  },
25161
+ {
25162
+ "name": "layout",
25163
+ "type": {
25164
+ "text": "HeroLayout"
25165
+ },
25166
+ "default": "'overlap'",
25167
+ "fieldName": "layout",
25168
+ "description": "How the panel relates to the image (default: 'overlap'). 'contained' keeps it on the image, in any of the eight positions; 'overlap' lets it fall `overlap-size` over the bottom of the image and run on below as far as its content needs, so the image keeps its height whatever the content. In 'overlap' the image has a fixed height (320px on md, 400px on lg) unless `media-height` or `media-aspect-ratio` is set, and only the horizontal side of `main-position` counts. A panel shorter than `overlap-size` ends inside the image and says so in development"
25169
+ },
25154
25170
  {
25155
25171
  "name": "main-background",
25156
25172
  "type": {
@@ -25165,9 +25181,9 @@
25165
25181
  "type": {
25166
25182
  "text": "HeroMainWidth"
25167
25183
  },
25168
- "default": "'1/2'",
25184
+ "default": "'auto'",
25169
25185
  "fieldName": "mainWidth",
25170
- "description": "Width of the panel (default: '1/2'); 'full' makes a full top or bottom strip and is ignored with 'left'/'right'"
25186
+ "description": "Width of the panel (default: 'auto'). 'auto' follows the content, between 480px and 640px and never wider than the image allows: a short title gets a narrow panel, a paragraph runs on to a readable line length. 'full' makes a strip across the whole image, at the top or the bottom, and is ignored with 'left'/'right'. Any CSS width (e.g. '560px', '60%') sets it exactly on md and lg, still never wider than the image allows; an invalid value falls back to 'auto'"
25171
25187
  },
25172
25188
  {
25173
25189
  "name": "main-position",
@@ -25187,6 +25203,24 @@
25187
25203
  "description": "Aspect ratio of the media area (CSS form, '16/9' or '16:9'); default '21/9'. On md/lg it sets the height of the hero, on sm the height of the media area",
25188
25204
  "fieldName": "mediaAspectRatio"
25189
25205
  },
25206
+ {
25207
+ "name": "overlap-size",
25208
+ "type": {
25209
+ "text": "string"
25210
+ },
25211
+ "default": "''",
25212
+ "fieldName": "overlapSize",
25213
+ "description": "With layout=\"overlap\": how far the panel falls over the bottom of the image, any CSS length (default: 160px). The overlap stays the same whatever the height of the image; a panel shorter than this ends inside the image"
25214
+ },
25215
+ {
25216
+ "name": "media-height",
25217
+ "type": {
25218
+ "text": "string"
25219
+ },
25220
+ "default": "''",
25221
+ "fieldName": "mediaHeight",
25222
+ "description": "Fixed height of the media area, any CSS length (e.g. '320px', '40vh'); wins over media-aspect-ratio. An invalid value falls back to the ratio"
25223
+ },
25190
25224
  {
25191
25225
  "name": "media-src",
25192
25226
  "type": {
@@ -25245,8 +25279,20 @@
25245
25279
  "inheritedFrom": {
25246
25280
  "name": "PageSectionMixin",
25247
25281
  "module": "src/utilities/page-section-mixin.ts"
25282
+ }
25283
+ },
25284
+ {
25285
+ "name": "grow",
25286
+ "type": {
25287
+ "text": "boolean"
25248
25288
  },
25249
- "description": "Minimum height of the section (section API)"
25289
+ "default": "false",
25290
+ "fieldName": "grow",
25291
+ "inheritedFrom": {
25292
+ "name": "PageSectionMixin",
25293
+ "module": "src/utilities/page-section-mixin.ts"
25294
+ },
25295
+ "description": "Takes the height the page has left, so the footer sits at the bottom of a short page. Without it, nldd-page lets its last section grow."
25250
25296
  },
25251
25297
  {
25252
25298
  "name": "padding-block",
@@ -25445,6 +25491,16 @@
25445
25491
  "attribute": "width",
25446
25492
  "reflects": true
25447
25493
  },
25494
+ {
25495
+ "kind": "field",
25496
+ "name": "verticalAlignment",
25497
+ "type": {
25498
+ "text": "'top' | 'center' | 'bottom'"
25499
+ },
25500
+ "default": "'top'",
25501
+ "attribute": "vertical-alignment",
25502
+ "reflects": true
25503
+ },
25448
25504
  {
25449
25505
  "kind": "field",
25450
25506
  "name": "background",
@@ -25472,6 +25528,20 @@
25472
25528
  "module": "src/utilities/page-section-mixin.ts"
25473
25529
  }
25474
25530
  },
25531
+ {
25532
+ "kind": "field",
25533
+ "name": "grow",
25534
+ "type": {
25535
+ "text": "boolean"
25536
+ },
25537
+ "default": "false",
25538
+ "attribute": "grow",
25539
+ "reflects": true,
25540
+ "inheritedFrom": {
25541
+ "name": "PageSectionMixin",
25542
+ "module": "src/utilities/page-section-mixin.ts"
25543
+ }
25544
+ },
25475
25545
  {
25476
25546
  "kind": "field",
25477
25547
  "name": "paddingBlock",
@@ -25639,6 +25709,15 @@
25639
25709
  "description": "Body max-width: 'full' removes the constraint so the section spans the full available width. Any CSS length (e.g. '480px') overrides the default max-width.",
25640
25710
  "fieldName": "width"
25641
25711
  },
25712
+ {
25713
+ "name": "vertical-alignment",
25714
+ "type": {
25715
+ "text": "'top' | 'center' | 'bottom'"
25716
+ },
25717
+ "default": "'top'",
25718
+ "fieldName": "verticalAlignment",
25719
+ "description": "Where the shorter column sits next to the longer one ('top' default). Only where the columns stand side by side; stacked, they follow each other."
25720
+ },
25642
25721
  {
25643
25722
  "name": "background",
25644
25723
  "type": {
@@ -25664,6 +25743,19 @@
25664
25743
  },
25665
25744
  "description": "Minimum section height (any CSS length, e.g. '400px', '100dvh') (mirrors width, which sets the body max-width)."
25666
25745
  },
25746
+ {
25747
+ "name": "grow",
25748
+ "type": {
25749
+ "text": "boolean"
25750
+ },
25751
+ "default": "false",
25752
+ "fieldName": "grow",
25753
+ "inheritedFrom": {
25754
+ "name": "PageSectionMixin",
25755
+ "module": "src/utilities/page-section-mixin.ts"
25756
+ },
25757
+ "description": "Takes the height the page has left, so the footer sits at the bottom of a short page. Without it, nldd-page lets its last section grow."
25758
+ },
25667
25759
  {
25668
25760
  "name": "padding-block",
25669
25761
  "type": {
@@ -25876,6 +25968,16 @@
25876
25968
  "attribute": "width",
25877
25969
  "reflects": true
25878
25970
  },
25971
+ {
25972
+ "kind": "field",
25973
+ "name": "verticalAlignment",
25974
+ "type": {
25975
+ "text": "'top' | 'center' | 'bottom'"
25976
+ },
25977
+ "default": "'top'",
25978
+ "attribute": "vertical-alignment",
25979
+ "reflects": true
25980
+ },
25879
25981
  {
25880
25982
  "kind": "field",
25881
25983
  "name": "background",
@@ -25903,6 +26005,20 @@
25903
26005
  "module": "src/utilities/page-section-mixin.ts"
25904
26006
  }
25905
26007
  },
26008
+ {
26009
+ "kind": "field",
26010
+ "name": "grow",
26011
+ "type": {
26012
+ "text": "boolean"
26013
+ },
26014
+ "default": "false",
26015
+ "attribute": "grow",
26016
+ "reflects": true,
26017
+ "inheritedFrom": {
26018
+ "name": "PageSectionMixin",
26019
+ "module": "src/utilities/page-section-mixin.ts"
26020
+ }
26021
+ },
25906
26022
  {
25907
26023
  "kind": "field",
25908
26024
  "name": "paddingBlock",
@@ -26070,6 +26186,15 @@
26070
26186
  "description": "Body max-width: 'full' removes the constraint so the section spans the full available width. Any CSS length (e.g. '480px') overrides the default max-width.",
26071
26187
  "fieldName": "width"
26072
26188
  },
26189
+ {
26190
+ "name": "vertical-alignment",
26191
+ "type": {
26192
+ "text": "'top' | 'center' | 'bottom'"
26193
+ },
26194
+ "default": "'top'",
26195
+ "fieldName": "verticalAlignment",
26196
+ "description": "Where the shorter column sits next to the longer one ('top' default). Only where the columns stand side by side; stacked, they follow each other."
26197
+ },
26073
26198
  {
26074
26199
  "name": "background",
26075
26200
  "type": {
@@ -26095,6 +26220,19 @@
26095
26220
  },
26096
26221
  "description": "Minimum section height (any CSS length, e.g. '400px', '100dvh') (mirrors width, which sets the body max-width)."
26097
26222
  },
26223
+ {
26224
+ "name": "grow",
26225
+ "type": {
26226
+ "text": "boolean"
26227
+ },
26228
+ "default": "false",
26229
+ "fieldName": "grow",
26230
+ "inheritedFrom": {
26231
+ "name": "PageSectionMixin",
26232
+ "module": "src/utilities/page-section-mixin.ts"
26233
+ },
26234
+ "description": "Takes the height the page has left, so the footer sits at the bottom of a short page. Without it, nldd-page lets its last section grow."
26235
+ },
26098
26236
  {
26099
26237
  "name": "padding-block",
26100
26238
  "type": {
@@ -26297,8 +26435,8 @@
26297
26435
  "type": {
26298
26436
  "text": "object"
26299
26437
  },
26300
- "default": "{ background: 'inherit', width: '', height: '', paddingBlock: '', paddingTop: '', paddingBottom: '', smPaddingBlock: '', smPaddingTop: '', smPaddingBottom: '', mdPaddingBlock: '', mdPaddingTop: '', mdPaddingBottom: '', lgPaddingBlock: '', lgPaddingTop: '', lgPaddingBottom: '', }",
26301
- "description": "Shared Storybook controls for the PageSectionMixin surface API\n(background, width, height and the 12 block-padding overrides).\nSpread into a section story's `args` / `argTypes`, and bind onto the host\nelement in `render` with the `pageSectionAttrs` directive."
26438
+ "default": "{ background: 'inherit', width: '', height: '', grow: false, paddingBlock: '', paddingTop: '', paddingBottom: '', smPaddingBlock: '', smPaddingTop: '', smPaddingBottom: '', mdPaddingBlock: '', mdPaddingTop: '', mdPaddingBottom: '', lgPaddingBlock: '', lgPaddingTop: '', lgPaddingBottom: '', }",
26439
+ "description": "Shared Storybook controls for the PageSectionMixin surface API\n(background, width, height, grow and the 12 block-padding overrides).\nSpread into a section story's `args` / `argTypes`, and bind onto the host\nelement in `render` with the `pageSectionAttrs` directive."
26302
26440
  },
26303
26441
  {
26304
26442
  "kind": "variable",
@@ -26306,7 +26444,7 @@
26306
26444
  "type": {
26307
26445
  "text": "object"
26308
26446
  },
26309
- "default": "{ background: { control: { type: 'select' }, options: ['inherit', 'base', 'tinted'], description: 'Oppervlak: \"inherit\" laat het oppervlak van de ouder doorschijnen, \"base\" en \"tinted\" tekenen een eigen oppervlak dat naar de inhoud cascadeert', table: { defaultValue: { summary: 'inherit' } }, }, width: { control: 'text', description: 'Maximale breedte van de inhoud: \"full\" haalt de grens weg, een CSS-lengte (bv. \"480px\") vervangt hem', }, height: { control: 'text', description: 'Minimale hoogte van de sectie, als CSS-lengte (bv. \"400px\" of \"100dvh\")', }, paddingBlock: paddingControl('padding-block', 'Padding boven en onder (token 0 tot 96, \"0\" haalt hem weg)'), paddingTop: paddingControl('padding-top', 'Alleen de padding boven'), paddingBottom: paddingControl('padding-bottom', 'Alleen de padding onder'), smPaddingBlock: paddingControl('sm-padding-block', 'Padding boven en onder op sm (tot 640px)'), smPaddingTop: paddingControl('sm-padding-top', 'Padding boven op sm (tot 640px)'), smPaddingBottom: paddingControl('sm-padding-bottom', 'Padding onder op sm (tot 640px)'), mdPaddingBlock: paddingControl('md-padding-block', 'Padding boven en onder op md (641 tot 1007px)'), mdPaddingTop: paddingControl('md-padding-top', 'Padding boven op md (641 tot 1007px)'), mdPaddingBottom: paddingControl('md-padding-bottom', 'Padding onder op md (641 tot 1007px)'), lgPaddingBlock: paddingControl('lg-padding-block', 'Padding boven en onder op lg (vanaf 1008px)'), lgPaddingTop: paddingControl('lg-padding-top', 'Padding boven op lg (vanaf 1008px)'), lgPaddingBottom: paddingControl('lg-padding-bottom', 'Padding onder op lg (vanaf 1008px)'), }"
26447
+ "default": "{ background: { control: { type: 'select' }, options: ['inherit', 'base', 'tinted'], description: 'Oppervlak: \"inherit\" laat het oppervlak van de ouder doorschijnen, \"base\" en \"tinted\" tekenen een eigen oppervlak dat naar de inhoud cascadeert', table: { defaultValue: { summary: 'inherit' } }, }, width: { control: 'text', description: 'Maximale breedte van de inhoud: \"full\" haalt de grens weg, een CSS-lengte (bv. \"480px\") vervangt hem', }, height: { control: 'text', description: 'Minimale hoogte van de sectie, als CSS-lengte (bv. \"400px\" of \"100dvh\")', }, grow: { control: 'boolean', description: 'Neemt de hoogte die de pagina over heeft, zodat de footer onderaan staat. Zonder `grow` groeit de laatste sectie van een `nldd-page`.', table: { defaultValue: { summary: false } }, }, paddingBlock: paddingControl('padding-block', 'Padding boven en onder (token 0 tot 96, \"0\" haalt hem weg)'), paddingTop: paddingControl('padding-top', 'Alleen de padding boven'), paddingBottom: paddingControl('padding-bottom', 'Alleen de padding onder'), smPaddingBlock: paddingControl('sm-padding-block', 'Padding boven en onder op sm (tot 640px)'), smPaddingTop: paddingControl('sm-padding-top', 'Padding boven op sm (tot 640px)'), smPaddingBottom: paddingControl('sm-padding-bottom', 'Padding onder op sm (tot 640px)'), mdPaddingBlock: paddingControl('md-padding-block', 'Padding boven en onder op md (641 tot 1007px)'), mdPaddingTop: paddingControl('md-padding-top', 'Padding boven op md (641 tot 1007px)'), mdPaddingBottom: paddingControl('md-padding-bottom', 'Padding onder op md (641 tot 1007px)'), lgPaddingBlock: paddingControl('lg-padding-block', 'Padding boven en onder op lg (vanaf 1008px)'), lgPaddingTop: paddingControl('lg-padding-top', 'Padding boven op lg (vanaf 1008px)'), lgPaddingBottom: paddingControl('lg-padding-bottom', 'Padding onder op lg (vanaf 1008px)'), }"
26310
26448
  },
26311
26449
  {
26312
26450
  "kind": "variable",
@@ -26347,7 +26485,7 @@
26347
26485
  "declarations": [
26348
26486
  {
26349
26487
  "kind": "class",
26350
- "description": "A page section with a left sidebar alongside the main content. - **Wide (section >= 1008px):** two columns. The sidebar is a sticky, scrollable tinted box (max-width 320px) beside the main content. Its sticky top/bottom insets default to 16px; override with `sticky-top` / `sticky-bottom` so it clears other sticky page elements (e.g. a sticky header). - **Narrow (section < 1008px):** the sidebar collapses behind a sheet (a left panel on md+ viewports, a bottom sheet on mobile), and the host reflects a `collapsed` attribute. The consumer owns the trigger: place any chrome (a button, a chosen-filters bar, …) wherever you want, show it only while collapsed (e.g. `nldd-sidebar-section[collapsed] .my-trigger { … }` or by reading `collapsed` / listening to `collapse-change`), and call `show()` / `toggle()` to open the sheet. Bind `aria-expanded` via the `open`/`close` events. The sheet gets a sticky title bar by default — the `sidebar-label` as title plus a \"Sluit\" button — overridable via the `sheet-top-title-bar` slot. The sidebar content lives in `slot=\"sidebar\"`. Its slot outlet moves between the box (expanded) and the sheet (collapsed) so there is a single, never-duplicated copy — the light DOM (and its state) is preserved across the switch. The box <-> sheet switch follows the section's OWN width (a ResizeObserver on the host), not the viewport — so a sidebar-section in a narrow column or a split-view pane collapses to the sheet just like one in a narrow viewport, and the sidebar never stacks above or crowds the main. Set `no-collapse` to opt out: a narrow section then stacks the sidebar (full-width) above the main instead of using a sheet. Inherits block `padding` and `height` from PageSectionMixin.",
26488
+ "description": "A page section with a left sidebar alongside the main content. - **Wide (section >= 1008px):** two columns. The sidebar is a sticky, scrollable box (max-width 320px) beside the main content. It takes the surface of the section around it and is edged by a divider line, so it reads as a block without drawing the eye away from the main. Its sticky top/bottom insets default to 16px; override with `sticky-top` / `sticky-bottom` so it clears other sticky page elements (e.g. a sticky header). - **Narrow (section < 1008px):** the sidebar collapses behind a sheet (a left panel on md+ viewports, a bottom sheet on mobile), and the host reflects a `collapsed` attribute. The consumer owns the trigger: place any chrome (a button, a chosen-filters bar, …) wherever you want, show it only while collapsed (e.g. `nldd-sidebar-section[collapsed] .my-trigger { … }` or by reading `collapsed` / listening to `collapse-change`), and call `show()` / `toggle()` to open the sheet. Bind `aria-expanded` via the `open`/`close` events. The sheet gets a sticky title bar by default — the `sidebar-label` as title plus a \"Sluit\" button — overridable via the `sheet-top-title-bar` slot. The sidebar content lives in `slot=\"sidebar\"`. Its slot outlet moves between the box (expanded) and the sheet (collapsed) so there is a single, never-duplicated copy — the light DOM (and its state) is preserved across the switch. The box <-> sheet switch follows the section's OWN width (a ResizeObserver on the host), not the viewport — so a sidebar-section in a narrow column or a split-view pane collapses to the sheet just like one in a narrow viewport, and the sidebar never stacks above or crowds the main. Set `no-collapse` to opt out: a narrow section then stacks the sidebar (full-width) above the main instead of using a sheet. Inherits block `padding` and `height` from PageSectionMixin.",
26351
26489
  "name": "NLDDSidebarSection",
26352
26490
  "members": [
26353
26491
  {
@@ -26476,6 +26614,20 @@
26476
26614
  "module": "src/utilities/page-section-mixin.ts"
26477
26615
  }
26478
26616
  },
26617
+ {
26618
+ "kind": "field",
26619
+ "name": "grow",
26620
+ "type": {
26621
+ "text": "boolean"
26622
+ },
26623
+ "default": "false",
26624
+ "attribute": "grow",
26625
+ "reflects": true,
26626
+ "inheritedFrom": {
26627
+ "name": "PageSectionMixin",
26628
+ "module": "src/utilities/page-section-mixin.ts"
26629
+ }
26630
+ },
26479
26631
  {
26480
26632
  "kind": "field",
26481
26633
  "name": "paddingBlock",
@@ -26734,6 +26886,19 @@
26734
26886
  "module": "src/utilities/page-section-mixin.ts"
26735
26887
  }
26736
26888
  },
26889
+ {
26890
+ "name": "grow",
26891
+ "type": {
26892
+ "text": "boolean"
26893
+ },
26894
+ "default": "false",
26895
+ "fieldName": "grow",
26896
+ "inheritedFrom": {
26897
+ "name": "PageSectionMixin",
26898
+ "module": "src/utilities/page-section-mixin.ts"
26899
+ },
26900
+ "description": "Takes the height the page has left, so the footer sits at the bottom of a short page. Without it, nldd-page lets its last section grow."
26901
+ },
26737
26902
  {
26738
26903
  "name": "padding-block",
26739
26904
  "type": {
@@ -26990,6 +27155,20 @@
26990
27155
  "module": "src/utilities/page-section-mixin.ts"
26991
27156
  }
26992
27157
  },
27158
+ {
27159
+ "kind": "field",
27160
+ "name": "grow",
27161
+ "type": {
27162
+ "text": "boolean"
27163
+ },
27164
+ "default": "false",
27165
+ "attribute": "grow",
27166
+ "reflects": true,
27167
+ "inheritedFrom": {
27168
+ "name": "PageSectionMixin",
27169
+ "module": "src/utilities/page-section-mixin.ts"
27170
+ }
27171
+ },
26993
27172
  {
26994
27173
  "kind": "field",
26995
27174
  "name": "paddingBlock",
@@ -27200,6 +27379,19 @@
27200
27379
  },
27201
27380
  "description": "Minimum section height (any CSS length, e.g. '400px', '100dvh') (mirrors width, which sets the body max-width)."
27202
27381
  },
27382
+ {
27383
+ "name": "grow",
27384
+ "type": {
27385
+ "text": "boolean"
27386
+ },
27387
+ "default": "false",
27388
+ "fieldName": "grow",
27389
+ "inheritedFrom": {
27390
+ "name": "PageSectionMixin",
27391
+ "module": "src/utilities/page-section-mixin.ts"
27392
+ },
27393
+ "description": "Takes the height the page has left, so the footer sits at the bottom of a short page. Without it, nldd-page lets its last section grow."
27394
+ },
27203
27395
  {
27204
27396
  "name": "padding-block",
27205
27397
  "type": {
@@ -27404,6 +27596,16 @@
27404
27596
  "attribute": "width",
27405
27597
  "reflects": true
27406
27598
  },
27599
+ {
27600
+ "kind": "field",
27601
+ "name": "verticalAlignment",
27602
+ "type": {
27603
+ "text": "'top' | 'center' | 'bottom'"
27604
+ },
27605
+ "default": "'top'",
27606
+ "attribute": "vertical-alignment",
27607
+ "reflects": true
27608
+ },
27407
27609
  {
27408
27610
  "kind": "field",
27409
27611
  "name": "background",
@@ -27431,6 +27633,20 @@
27431
27633
  "module": "src/utilities/page-section-mixin.ts"
27432
27634
  }
27433
27635
  },
27636
+ {
27637
+ "kind": "field",
27638
+ "name": "grow",
27639
+ "type": {
27640
+ "text": "boolean"
27641
+ },
27642
+ "default": "false",
27643
+ "attribute": "grow",
27644
+ "reflects": true,
27645
+ "inheritedFrom": {
27646
+ "name": "PageSectionMixin",
27647
+ "module": "src/utilities/page-section-mixin.ts"
27648
+ }
27649
+ },
27434
27650
  {
27435
27651
  "kind": "field",
27436
27652
  "name": "paddingBlock",
@@ -27598,6 +27814,15 @@
27598
27814
  "description": "Body max-width: 'full' removes the constraint so the section spans the full available width. Any CSS length (e.g. '480px') overrides the default max-width.",
27599
27815
  "fieldName": "width"
27600
27816
  },
27817
+ {
27818
+ "name": "vertical-alignment",
27819
+ "type": {
27820
+ "text": "'top' | 'center' | 'bottom'"
27821
+ },
27822
+ "default": "'top'",
27823
+ "fieldName": "verticalAlignment",
27824
+ "description": "Where the shorter column sits next to the longer one ('top' default). Only where the columns stand side by side; stacked, they follow each other."
27825
+ },
27601
27826
  {
27602
27827
  "name": "background",
27603
27828
  "type": {
@@ -27623,6 +27848,19 @@
27623
27848
  },
27624
27849
  "description": "Minimum section height (any CSS length, e.g. '400px', '100dvh') (mirrors width, which sets the body max-width)."
27625
27850
  },
27851
+ {
27852
+ "name": "grow",
27853
+ "type": {
27854
+ "text": "boolean"
27855
+ },
27856
+ "default": "false",
27857
+ "fieldName": "grow",
27858
+ "inheritedFrom": {
27859
+ "name": "PageSectionMixin",
27860
+ "module": "src/utilities/page-section-mixin.ts"
27861
+ },
27862
+ "description": "Takes the height the page has left, so the footer sits at the bottom of a short page. Without it, nldd-page lets its last section grow."
27863
+ },
27626
27864
  {
27627
27865
  "name": "padding-block",
27628
27866
  "type": {
@@ -27821,7 +28059,7 @@
27821
28059
  "declarations": [
27822
28060
  {
27823
28061
  "kind": "class",
27824
- "description": "A page layout with optional sticky header and footer. Without sticky-header, the host is the scroll container and the header is in normal flow. With sticky-header, the header becomes absolute and .page__scroll takes over scrolling, padded by the measured header height. That padding freezes once you scroll, so a collapsing bar cannot drag the content up under the cursor. In root-scroll mode (--context-scroll-mode: root, derived upstream by nldd-app-view) the page stops owning a scroller: the document scrolls and the sticky header/footer stick against the document, offset by --context-inset-top/bottom. The mode is read on connect/resize and reflected to [data-scroll] so the CSS can branch. The page passes those insets on to its own content, with its sticky header and footer added: anything sticky inside (an nldd-sidebar-section, a sticky table head) reads --context-inset-top / --context-inset-bottom and clears every bar above and below it without being told a number. The heights are measured, because a top title bar shrinks as you scroll past its anchor. While the page owns the scroller, only its own bars count: the chrome above the page sits outside that scroller and does not push sticky content down. A page carries the landmarks of a document: its header is the banner, its content the main landmark, its footer the contentinfo. A document has one of each, so a page that sits beside another one cannot have them. Such a page renders a section and a plain div instead, which drops all three at once: a header inside sectioning content is no longer a banner. With `accessible-label` that section is a named region, so there is still one landmark to jump to; without a name it is no landmark at all, which beats an unnamed one. `landmarks` says which of the two a page is, and `auto` (the default) reads it off where the page sits: - in an overlay (nldd-sheet, nldd-modal-dialog, nldd-window, nldd-popover) a region, because the overlay is not the document; - in a pane of nldd-navigation-split-view, nldd-side-by-side-split-view or nldd-stacked-split-view a region, because those place pages beside each other; - anywhere else the page, including the `main` slot of an nldd-bar-split-view, which stacks bars around a single content area. So an app shell has no main until you say which pane holds the primary content, with `landmarks=\"page\"` on that one page. Only the application knows which pane that is. Two pages that both render a main is invalid HTML, and the page says so in development.",
28062
+ "description": "A page layout with optional sticky header and footer. Without sticky-header, the host is the scroll container and the header is in normal flow. With sticky-header, the header becomes absolute and .page__scroll takes over scrolling, padded by the measured header height. That padding freezes once you scroll, so a collapsing bar cannot drag the content up under the cursor. In root-scroll mode (--context-scroll-mode: root, derived upstream by nldd-shell) the page stops owning a scroller: the document scrolls and the sticky header/footer stick against the document, offset by --context-inset-top/bottom. The mode is read on connect/resize and reflected to [data-scroll] so the CSS can branch. The page passes those insets on to its own content, with its sticky header and footer added: anything sticky inside (an nldd-sidebar-section, a sticky table head) reads --context-inset-top / --context-inset-bottom and clears every bar above and below it without being told a number. The heights are measured, because a top title bar shrinks as you scroll past its anchor. While the page owns the scroller, only its own bars count: the chrome above the page sits outside that scroller and does not push sticky content down. A page carries the landmarks of a document: its header is the banner, its content the main landmark, its footer the contentinfo. A document has one of each, so a page that sits beside another one cannot have them. Such a page renders a section and a plain div instead, which drops all three at once: a header inside sectioning content is no longer a banner. With `accessible-label` that section is a named region, so there is still one landmark to jump to; without a name it is no landmark at all, which beats an unnamed one. `landmarks` says which of the two a page is, and `auto` (the default) reads it off where the page sits: - in an overlay (nldd-sheet, nldd-modal-dialog, nldd-window, nldd-popover) a region, because the overlay is not the document; - in a pane of nldd-navigation-split-view, nldd-side-by-side-split-view or nldd-stacked-split-view a region, because those place pages beside each other; - anywhere else the page, including the `main` slot of an nldd-bar-split-view, which stacks bars around a single content area. So an app shell has no main until you say which pane holds the primary content, with `landmarks=\"page\"` on that one page. Only the application knows which pane that is. Two pages that both render a main is invalid HTML, and the page says so in development.",
27825
28063
  "name": "NLDDPage",
27826
28064
  "members": [
27827
28065
  {
@@ -28469,6 +28707,70 @@
28469
28707
  }
28470
28708
  ]
28471
28709
  },
28710
+ {
28711
+ "kind": "javascript-module",
28712
+ "path": "src/components/layout/shell/shell.ts",
28713
+ "declarations": [
28714
+ {
28715
+ "kind": "class",
28716
+ "description": "The required root shell of a Nederlandse Digitale Dienst application. Always contains a split view or an nldd-page as direct content. The document font comes from the package stylesheet (`@nldd/design-system/styles`), not from this component: it gives `body` the body font and content color as soon as a shell is on the page, inside `@layer reset` so any rule of your own wins. Import only the tokens (`/styles/tokens`) and text you write in the light DOM keeps the browser default. Set background=\"tinted\" to give the whole application a tinted background. All descendants read --context-parent-background-color via --_shell-background-color automatically. Individual components can override locally with their own background attribute. The same background color is forced on `document.body` so that browser- chrome surfaces (iOS overscroll bounce, status bar, page-margin areas) blend with the app instead of revealing the user-agent's default white. Cleared when the shell disconnects. The app scrolls the DOCUMENT (root mode) or lets each `nldd-page` scroll inside its pane (nested mode). The mode is derived from the outermost horizontal split view: one column means the document scrolls, several columns mean the panes do. An app without such a split view is a single column at every width and therefore scrolls the document too — nested scrolling would cost it the rubber-band and the collapsing browser toolbar on iOS for nothing. Set `--context-scroll-mode` on the `nldd-shell` itself to override the derived mode; an inherited value loses from it. In nested scroll mode `overscroll-behavior: none` is set on `document.documentElement` and `document.body` while the shell is connected. Combined with `overscroll-behavior: contain` on `nldd-page`'s scroll target, this prevents iOS rubber-band on the viewport when scroll gestures land outside an `nldd-page` (e.g. on a top-bar). In root scroll mode the document itself is the scroller, so this is lifted to let the native rubber-band happen. Cleared on last disconnect.",
28717
+ "name": "NLDDShell",
28718
+ "members": [
28719
+ {
28720
+ "kind": "field",
28721
+ "name": "background",
28722
+ "type": {
28723
+ "text": "'base' | 'tinted'"
28724
+ },
28725
+ "default": "'base'",
28726
+ "attribute": "background",
28727
+ "reflects": true
28728
+ }
28729
+ ],
28730
+ "attributes": [
28731
+ {
28732
+ "name": "background",
28733
+ "type": {
28734
+ "text": "'base' | 'tinted'"
28735
+ },
28736
+ "default": "'base'",
28737
+ "fieldName": "background",
28738
+ "description": "Background color (cascades to descendants)"
28739
+ }
28740
+ ],
28741
+ "superclass": {
28742
+ "name": "LitElement",
28743
+ "package": "lit"
28744
+ },
28745
+ "tagName": "nldd-shell",
28746
+ "customElement": true,
28747
+ "slots": [
28748
+ {
28749
+ "name": "",
28750
+ "description": "Default slot for the application content"
28751
+ }
28752
+ ]
28753
+ }
28754
+ ],
28755
+ "exports": [
28756
+ {
28757
+ "kind": "js",
28758
+ "name": "NLDDShell",
28759
+ "declaration": {
28760
+ "name": "NLDDShell",
28761
+ "module": "src/components/layout/shell/shell.ts"
28762
+ }
28763
+ },
28764
+ {
28765
+ "kind": "custom-element-definition",
28766
+ "name": "nldd-shell",
28767
+ "declaration": {
28768
+ "name": "NLDDShell",
28769
+ "module": "src/components/layout/shell/shell.ts"
28770
+ }
28771
+ }
28772
+ ]
28773
+ },
28472
28774
  {
28473
28775
  "kind": "javascript-module",
28474
28776
  "path": "src/components/layout/spacer/spacer.ts",
@@ -31478,6 +31780,17 @@
31478
31780
  "attribute": "current",
31479
31781
  "reflects": true
31480
31782
  },
31783
+ {
31784
+ "kind": "field",
31785
+ "name": "currentType",
31786
+ "type": {
31787
+ "text": "'page' | 'step' | 'location' | 'date' | 'time' | 'true'"
31788
+ },
31789
+ "default": "'page'",
31790
+ "description": "The `aria-current` value of a current segment; see nldd-list-item's `current-type`.",
31791
+ "attribute": "current-type",
31792
+ "reflects": true
31793
+ },
31481
31794
  {
31482
31795
  "kind": "field",
31483
31796
  "name": "disabled",
@@ -31621,11 +31934,20 @@
31621
31934
  "type": {
31622
31935
  "text": "boolean"
31623
31936
  },
31624
- "description": "Marks the segment as the current page (`aria-current=\"page\"`). The row it sits in paints itself as the current row from it, so on a segmented row this is the only place it has to be set.",
31937
+ "description": "Marks the segment as the current one, with `aria-current` set to `current-type`. The row it sits in paints itself as the current row from it, so on a segmented row this is the only place it has to be set.",
31625
31938
  "name": "current",
31626
31939
  "default": "false",
31627
31940
  "fieldName": "current"
31628
31941
  },
31942
+ {
31943
+ "type": {
31944
+ "text": "'page' | 'step' | 'location' | 'date' | 'time' | 'true'"
31945
+ },
31946
+ "description": "The `aria-current` value of a `current` segment (default 'page'). Use 'location' for a table of contents, whose rows point at sections of the page you are on.",
31947
+ "name": "current-type",
31948
+ "default": "'page'",
31949
+ "fieldName": "currentType"
31950
+ },
31629
31951
  {
31630
31952
  "type": {
31631
31953
  "text": "boolean"
@@ -31683,7 +32005,7 @@
31683
32005
  "declarations": [
31684
32006
  {
31685
32007
  "kind": "class",
31686
- "description": "A row within an `nldd-list`. Renders as a link when `href` is set, as a checkbox when `checkbox` is set, as a button when `button` is set, or as a plain container otherwise. All cells and segments share one flat slot, in source order. With one action, make the row itself the control (`href`, `button`, `checkbox` or `radio`): the whole row is then one hit area. With two or more, give each its own `nldd-list-item-segment` and leave the row without an action of its own. Both at once nests a control inside a control, and the item warns about that in development. Two rules govern every row: 1. State fills always paint the WIDENED row geometry — the row box extended by the indicator inline inset on both sides — whether or not the row is interactive. Paint never differs between a selected plain row and a selected interactive row. 2. The widened strip belongs to the ROW, never to a segment. A row with any action (its own `href`/`button`/`checkbox`, or a slotted segment) pulls itself outward (`is-interactive` host class → negative inline margin) and pads the row block back by the same amount, so content stays on the grid. A row-wide action owns that padding itself, making the whole widened box one hit area; slotted segments stay in the grid, so their footprint is position-independent and tree columns line up at any depth. By default the divider starts at the row's first text or title cell, so the line lands on the words rather than on whatever leads up to them — an icon, an avatar, a checkbox, or the spacers a tree indents with. Rows of different shapes then still line their dividers up with each other, and a tree's dividers step inward with its indentation. Text inside an `nldd-list-item-segment` counts as the row's content, and the marker is that text cell rather than the action: the action carries its own inline padding, so its edge sits before the words. A row with no text or title cell keeps the full content width. Mark a cell with `divider-start` and/or `divider-end` to place it yourself instead — an explicit marker replaces the derived one entirely, so `divider-start` on the leading cell restores the full-width line. Multiple markers resolve as the union: first `divider-start` through last `divider-end`. A start past the last end is an authoring error — the item DEV-warns and falls back to the full content width. A branch row can disclose its children in two ways: a dedicated `nldd-list-item-segment[disclosure]` segment (only the chevron is clickable), or the row itself as the control (`button` + `expanded`, the whole row toggles). In the second case, mark the chevron's `nldd-icon-cell` with `disclosure` and the row turns it with `expanded` — the same affordance, without having to trade a clickable row for a turning chevron. `checkbox` makes the WHOLE row the control: the inner action becomes a `role=\"checkbox\"` button carrying `aria-checked`, it toggles `checked` on activation and fires `change`. Slot an `nldd-checkbox decorative` (or any glyph) before the text: it only shows the state, since the row already conveys role and state, and a second focusable control would double the tab stops. Do NOT nest a real `<input type=\"checkbox\">` in the action: interactive content inside a `<button>` is invalid HTML and AT announces the button, not the checked state. A `<label>` variant is not offered for the same reason it cannot work — label-to-input association walks the DOM tree, and a slotted input is not a descendant of a label in the shadow root. When it renders as a link, `target` and `rel` are forwarded to the inner `<a>` (e.g. `target=\"_blank\" rel=\"noopener noreferrer\"`). With `target=\"_blank\"` the item also injects a visually hidden \"opens in new tab\" announcement for assistive technology (WCAG 2.1 SC 3.2.2). The item synchronizes its ARIA with its parent `nldd-list`'s `type`: - `list` parent → `role=\"listitem\"` - `navigation` parent → `role=\"listitem\"` + `aria-current=\"page\"` on the inner `<a>` / `<button>` when `selected` - `listbox` parent → `role=\"option\"` + `aria-selected` reflecting `selected`. The list points its search input's `aria-activedescendant` at the active option via `_highlighted` (separate from `selected`).",
32008
+ "description": "A row within an `nldd-list`. Renders as a link when `href` is set, as a checkbox when `checkbox` is set, as a button when `button` is set, or as a plain container otherwise. All cells and segments share one flat slot, in source order. With one action, make the row itself the control (`href`, `button`, `checkbox` or `radio`): the whole row is then one hit area. With two or more, give each its own `nldd-list-item-segment` and leave the row without an action of its own. Both at once nests a control inside a control, and the item warns about that in development. Two rules govern every row: 1. State fills always paint the WIDENED row geometry — the row box extended by the indicator inline inset on both sides — whether or not the row is interactive. Paint never differs between a selected plain row and a selected interactive row. 2. The widened strip belongs to the ROW, never to a segment. A row with any action (its own `href`/`button`/`checkbox`, or a slotted segment) pulls itself outward (`is-interactive` host class → negative inline margin) and pads the row block back by the same amount, so content stays on the grid. A row-wide action owns that padding itself, making the whole widened box one hit area; slotted segments stay in the grid, so their footprint is position-independent and tree columns line up at any depth. By default the divider starts at the row's first text or title cell, so the line lands on the words rather than on whatever leads up to them — an icon, an avatar, a checkbox, or the spacers a tree indents with. Rows of different shapes then still line their dividers up with each other, and a tree's dividers step inward with its indentation. Text inside an `nldd-list-item-segment` counts as the row's content, and the marker is that text cell rather than the action: the action carries its own inline padding, so its edge sits before the words. A row with no text or title cell keeps the full content width. Mark a cell with `divider-start` and/or `divider-end` to place it yourself instead — an explicit marker replaces the derived one entirely, so `divider-start` on the leading cell restores the full-width line. Multiple markers resolve as the union: first `divider-start` through last `divider-end`. A start past the last end is an authoring error — the item DEV-warns and falls back to the full content width. A branch row can disclose its children in two ways: a dedicated `nldd-list-item-segment[disclosure]` segment (only the chevron is clickable), or the row itself as the control (`button` + `expanded`, the whole row toggles). In the second case, mark the chevron's `nldd-icon-cell` with `disclosure` and the row turns it with `expanded` — the same affordance, without having to trade a clickable row for a turning chevron. `checkbox` makes the WHOLE row the control: the inner action becomes a `role=\"checkbox\"` button carrying `aria-checked`, it toggles `checked` on activation and fires `change`. Slot an `nldd-checkbox decorative` (or any glyph) before the text: it only shows the state, since the row already conveys role and state, and a second focusable control would double the tab stops. Do NOT nest a real `<input type=\"checkbox\">` in the action: interactive content inside a `<button>` is invalid HTML and AT announces the button, not the checked state. A `<label>` variant is not offered for the same reason it cannot work — label-to-input association walks the DOM tree, and a slotted input is not a descendant of a label in the shadow root. When it renders as a link, `target` and `rel` are forwarded to the inner `<a>` (e.g. `target=\"_blank\" rel=\"noopener noreferrer\"`). With `target=\"_blank\"` the item also injects a visually hidden \"opens in new tab\" announcement for assistive technology (WCAG 2.1 SC 3.2.2). The item synchronizes its ARIA with its parent `nldd-list`'s `type`: - `list` parent → `role=\"listitem\"` - `navigation` parent → `role=\"listitem\"` + `aria-current` on the inner `<a>` / `<button>` when `current` or `selected`, with `current-type` as its value (`page` unless set) - `listbox` parent → `role=\"option\"` + `aria-selected` reflecting `selected`. The list points its search input's `aria-activedescendant` at the active option via `_highlighted` (separate from `selected`).",
31687
32009
  "name": "NLDDListItem",
31688
32010
  "slots": [
31689
32011
  {
@@ -31822,6 +32144,17 @@
31822
32144
  "attribute": "current",
31823
32145
  "reflects": true
31824
32146
  },
32147
+ {
32148
+ "kind": "field",
32149
+ "name": "currentType",
32150
+ "type": {
32151
+ "text": "'page' | 'step' | 'location' | 'date' | 'time' | 'true'"
32152
+ },
32153
+ "default": "'page'",
32154
+ "description": "What kind of \"current\" this row is, for `aria-current`.\n\n`page` fits a menu of pages, but a table of contents points at sections\nof the page you are already on: there every row would announce itself as\n\"the current page\". `location` says \"you are here\" instead.",
32155
+ "attribute": "current-type",
32156
+ "reflects": true
32157
+ },
31825
32158
  {
31826
32159
  "kind": "field",
31827
32160
  "name": "disabled",
@@ -31964,7 +32297,7 @@
31964
32297
  "type": {
31965
32298
  "text": "boolean"
31966
32299
  },
31967
- "description": "Marks the item as selected: it is one of the rows you picked. Selection is consumer-managed; the list never sets it. In a `navigation` parent it puts `aria-current=\"page\"` on the inner action, in a `listbox` parent it drives `aria-selected`.",
32300
+ "description": "Marks the item as selected: it is one of the rows you picked. Selection is consumer-managed; the list never sets it. In a `navigation` parent it puts `aria-current` on the inner action, with `current-type` as its value; in a `listbox` parent it drives `aria-selected`.",
31968
32301
  "name": "selected",
31969
32302
  "default": "false",
31970
32303
  "fieldName": "selected"
@@ -31990,11 +32323,20 @@
31990
32323
  "type": {
31991
32324
  "text": "boolean"
31992
32325
  },
31993
- "description": "Marks the item as the one you are on: the page a menu row points at, the record a list has open. Exactly one row in a list carries it, where `selected` may be on many. It paints like `selected` at rest, and takes the highlighted fill while focus is anywhere in the row — including inside a nested `nldd-list-item-segment`, which is what a segmented row needs: the focus never reaches the row's own control, because there is none. In a `navigation` parent it puts `aria-current=\"page\"` on the inner action. On a segmented row set it on the segment that holds the link instead: the row reads `current` off its own segments and paints itself, so it is written once, where `aria-current` belongs.",
32326
+ "description": "Marks the item as the one you are on: the page a menu row points at, the record a list has open. Exactly one row in a list carries it, where `selected` may be on many. It paints like `selected` at rest, and takes the highlighted fill while focus is anywhere in the row — including inside a nested `nldd-list-item-segment`, which is what a segmented row needs: the focus never reaches the row's own control, because there is none. In a `navigation` parent it puts `aria-current` on the inner action, with `current-type` as its value. On a segmented row set it on the segment that holds the link instead: the row reads `current` off its own segments and paints itself, so it is written once, where `aria-current` belongs.",
31994
32327
  "name": "current",
31995
32328
  "default": "false",
31996
32329
  "fieldName": "current"
31997
32330
  },
32331
+ {
32332
+ "type": {
32333
+ "text": "'page' | 'step' | 'location' | 'date' | 'time' | 'true'"
32334
+ },
32335
+ "description": "The `aria-current` value a `current` or `selected` row puts on its action in a `navigation` parent (default 'page'). Use 'location' for a table of contents, whose rows point at sections of the page you are on.",
32336
+ "name": "current-type",
32337
+ "default": "'page'",
32338
+ "fieldName": "currentType"
32339
+ },
31998
32340
  {
31999
32341
  "type": {
32000
32342
  "text": "boolean"
@@ -33596,6 +33938,10 @@
33596
33938
  }
33597
33939
  ],
33598
33940
  "slots": [
33941
+ {
33942
+ "name": "icon",
33943
+ "description": "Takes the place of the icon: an `nldd-avatar` for the person who is signed in, for instance. It gets the size of an icon, and follows `content-priority` and `icon-only` as the icon does. Wins over `icon`."
33944
+ },
33599
33945
  {
33600
33946
  "name": "",
33601
33947
  "description": "Content of the expandable popover. Wrap items in an `<nldd-menu>` so this component does not have to duplicate the menu API (variant, accessible-label, translations, filterFn and so on). Event listeners on items work directly, because nothing is cloned anymore."
@@ -37154,7 +37500,7 @@
37154
37500
  "declarations": [
37155
37501
  {
37156
37502
  "kind": "class",
37157
- "description": "A narrow, page-wide status bar (24px) with a deep background color per variant. Use it for persistent system state: an outage, planned maintenance, a draft view or a recording in progress. The bar deliberately shows no icon and supports text only. The text itself has to name the status (\"Storing: …\", \"Gepland onderhoud …\"), so the meaning does not follow from color alone (WCAG 1.4.1). Keep the text short: the bar shows one line and truncates with an ellipsis, certainly on narrower screens. For a long message with a lot of information only the essence belongs in the bar. Point to a separate page or sheet for the rest (through `href` or `button`, for instance), where the user can read on. The whole bar can be clickable: set `href` (renders an `<a>`) or `button` (renders a `<button>`; listen for the native `click` event). Without either the bar is static. On interaction a chevron appears as an affordance. One action per bar at most; several actions, or links in running text, belong in nldd-banner. role and aria-live are set automatically from the variant: - critical → role=\"alert\" (implies aria-live=\"assertive\"; interrupts the screen reader) - others → role=\"status\" aria-live=\"polite\" Not overridable. If you need a quieter component, pick a different one. Use `critical` only for a real emergency: role=\"alert\" interrupts the screen reader on every change of the content, so do not put text in it that changes regularly (a counting-down timer, for example).",
37503
+ "description": "A narrow, page-wide status bar (24px) with a deep background color per variant. Use it for persistent system state: an outage, planned maintenance, a draft view or a recording in progress. The bar deliberately shows no icon and supports text only. The text itself has to name the status (\"Storing: …\", \"Gepland onderhoud …\"), so the meaning does not follow from color alone (WCAG 1.4.1). Keep the text short: the bar shows one line and truncates with an ellipsis, certainly on narrower screens. For a long message with a lot of information only the essence belongs in the bar. Point to a separate page or sheet for the rest (through `href` or `button`, for instance), where the user can read on. The whole bar can be clickable: set `href` (renders an `<a>`) or `button` (renders a `<button>`; listen for the native `click` event). Without either the bar is static. On interaction a chevron appears as an affordance. One action per bar at most; several actions, or links in running text, belong in nldd-banner. The bar is the first thing on the screen: above nldd-top-navigation-bar or nldd-top-title-bar, across the whole app, also when a split view shows several panes. It reports the state of the service, not of one page, so it never sits inside the content or below a top bar. Below a top bar it says so in development. role and aria-live are set automatically from the variant: - critical → role=\"alert\" (implies aria-live=\"assertive\"; interrupts the screen reader) - others → role=\"status\" aria-live=\"polite\" Not overridable. If you need a quieter component, pick a different one. Use `critical` only for a real emergency: role=\"alert\" interrupts the screen reader on every change of the content, so do not put text in it that changes regularly (a counting-down timer, for example).",
37158
37504
  "name": "NLDDStatusBar",
37159
37505
  "members": [
37160
37506
  {
@@ -38337,7 +38683,7 @@
38337
38683
  "declarations": [
38338
38684
  {
38339
38685
  "kind": "mixin",
38340
- "description": "Shared surface controls for the page-section components. Adds three\northogonal capabilities, all written as inline host styles / custom\nproperties (no per-component CSS needed for the background — custom\nproperties inherit through the shadow boundary into the section's block\nelement and slotted content):\n\n- **background**: `inherit` (the default — transparent, shows the ancestor's\n surface) | `base` (the base surface color) | `tinted`. Setting\n `base`/`tinted` also cascades `--context-parent-background-color` so\n descendants (cards, nested sections) read the same surface.\n- **block padding**: `padding-block` (both edges) with `padding-top`\n / `padding-bottom` per-edge overrides, each with responsive `sm-` /\n `md-` / `lg-` variants (12 attrs total). Token scale `0`–`96`; `0` strips\n the padding. Per breakpoint the section CSS resolves: scope override →\n base override → responsive default. The inline (gutter) padding stays\n design-controlled.\n- **height**: any CSS length (e.g. '400px', '100dvh') applied as the host's\n min-height (so the section is at least that tall) — mirroring how `width`\n maps to the body max-width.",
38686
+ "description": "Shared surface controls for the page-section components. Adds three\northogonal capabilities, all written as inline host styles / custom\nproperties (no per-component CSS needed for the background — custom\nproperties inherit through the shadow boundary into the section's block\nelement and slotted content):\n\n- **background**: `inherit` (the default — transparent, shows the ancestor's\n surface) | `base` (the base surface color) | `tinted`. Setting\n `base`/`tinted` also cascades `--context-parent-background-color` so\n descendants (cards, nested sections) read the same surface.\n- **block padding**: `padding-block` (both edges) with `padding-top`\n / `padding-bottom` per-edge overrides, each with responsive `sm-` /\n `md-` / `lg-` variants (12 attrs total). Token scale `0`–`96`; `0` strips\n the padding. Per breakpoint the section CSS resolves: scope override →\n base override → responsive default. The inline (gutter) padding stays\n design-controlled.\n- **height**: any CSS length (e.g. '400px', '100dvh') applied as the host's\n min-height (so the section is at least that tall) — mirroring how `width`\n maps to the body max-width.\n- **grow**: the section takes the height the page has left, so the footer\n sits at the bottom of a short page. Without it, nldd-page lets its last\n section grow. nldd-page reads this and marks the growing section with\n `data-growing`; it never writes `grow`, which stays the author's.",
38341
38687
  "name": "PageSectionMixin",
38342
38688
  "members": [
38343
38689
  {
@@ -38359,6 +38705,16 @@
38359
38705
  "attribute": "height",
38360
38706
  "reflects": true
38361
38707
  },
38708
+ {
38709
+ "kind": "field",
38710
+ "name": "grow",
38711
+ "type": {
38712
+ "text": "boolean"
38713
+ },
38714
+ "default": "false",
38715
+ "attribute": "grow",
38716
+ "reflects": true
38717
+ },
38362
38718
  {
38363
38719
  "kind": "field",
38364
38720
  "name": "paddingBlock",
@@ -38555,6 +38911,14 @@
38555
38911
  },
38556
38912
  "fieldName": "height"
38557
38913
  },
38914
+ {
38915
+ "name": "grow",
38916
+ "type": {
38917
+ "text": "boolean"
38918
+ },
38919
+ "default": "false",
38920
+ "fieldName": "grow"
38921
+ },
38558
38922
  {
38559
38923
  "name": "padding-block",
38560
38924
  "type": {
@@ -39287,7 +39651,7 @@
39287
39651
  "text": "string"
39288
39652
  },
39289
39653
  "default": "'nldd-single-column-change'",
39290
- "description": "Bubbling + composed event a horizontal split view fires when it collapses to\n(or expands out of) a single visible column. nldd-app-view listens for it to\nderive the document-vs-nested scroll mode."
39654
+ "description": "Bubbling + composed event a horizontal split view fires when it collapses to\n(or expands out of) a single visible column. nldd-shell listens for it to\nderive the document-vs-nested scroll mode."
39291
39655
  },
39292
39656
  {
39293
39657
  "kind": "function",
@@ -39305,11 +39669,35 @@
39305
39669
  }
39306
39670
  }
39307
39671
  ],
39308
- "description": "Nearest ancestor app-view (light-DOM `closest`; slotted layers stay in the\nconsumer's light tree so this reaches across the slot boundaries), or null\nwhen a layer is used stand-alone (e.g. a bare page in the docs).\n\nAn overlay ends the search: a sheet or a modal dialog is its own scroll\ncontainer and its own top edge, so a page inside one owns its scroller\nwhatever the app around it does. Without this the app-view would push its\nroot mode straight through the overlay and the page's sticky header would\nstick against the document, over the content of the overlay. The overlays\nreset --context-scroll-mode as well, which is what the stand-alone read\nbelow then finds."
39672
+ "description": "Nearest ancestor shell (light-DOM `closest`; slotted layers stay in the\nconsumer's light tree so this reaches across the slot boundaries), or null\nwhen a layer is used stand-alone (e.g. a bare page in the docs).\n\nAn overlay ends the search: a sheet or a modal dialog is its own scroll\ncontainer and its own top edge, so a page inside one owns its scroller\nwhatever the app around it does. Without this the shell would push its\nroot mode straight through the overlay and the page's sticky header would\nstick against the document, over the content of the overlay. The overlays\nreset --context-scroll-mode as well, which is what the stand-alone read\nbelow then finds."
39673
+ },
39674
+ {
39675
+ "kind": "function",
39676
+ "name": "whenScrollModeProviderDefined",
39677
+ "return": {
39678
+ "type": {
39679
+ "text": "void"
39680
+ }
39681
+ },
39682
+ "parameters": [
39683
+ {
39684
+ "name": "host",
39685
+ "type": {
39686
+ "text": "Element"
39687
+ }
39688
+ },
39689
+ {
39690
+ "name": "adopt",
39691
+ "type": {
39692
+ "text": "(provider: ScrollModeProvider) => void"
39693
+ }
39694
+ }
39695
+ ],
39696
+ "description": "Hands `adopt` the provider above `host` once it is defined, when it was not\nyet at the moment `host` connected.\n\nCustom elements upgrade in the order their modules are defined, and an app\ndoes not control that: importing nldd-sidebar-section defines nldd-page, and\na route that loads before its shell defines the page before the shell. The\nprovider is then in the DOM but has no `registerScrollConsumer` yet, so\nfindScrollModeProvider returns null and the layer starts out stand-alone.\nThis lets it register as soon as the provider is defined. Nothing happens\nwhen the host has left the DOM by then, or sits under another provider."
39309
39697
  },
39310
39698
  {
39311
39699
  "kind": "class",
39312
- "description": "Reads the inherited `--context-scroll-mode` and reflects it to the host's\n`[data-scroll]` attribute so CSS can branch.\n\nIn root-scroll mode the DOCUMENT scrolls (see nldd-app-view): every layout\nlayer between the document and an nldd-page — app-view, the split views and\ntheir panes — must flow (overflow: visible) instead of clipping, so the page's\nsticky header/footer can stick against the document. Rather than duplicate the\nread-and-reflect logic in each of those components, they share this controller.\n\nThe mode is derived upstream by nldd-app-view. When an app-view is present the\nhost registers as a consumer and app-view pushes an authoritative re-read on\nevery change (a bare `--context-scroll-mode` update would otherwise not reach\nthe resize-polling layers in time — rAF runs before ResizeObserver). Without\nan app-view (a stand-alone page), it falls back to re-reading on window resize\nso a manual/media-query override still works. `nldd-page` keeps its own inline\nlogic because it also has to re-wire scroll listeners.",
39700
+ "description": "Reads the inherited `--context-scroll-mode` and reflects it to the host's\n`[data-scroll]` attribute so CSS can branch.\n\nIn root-scroll mode the DOCUMENT scrolls (see nldd-shell): every layout\nlayer between the document and an nldd-page — shell, the split views and\ntheir panes — must flow (overflow: visible) instead of clipping, so the page's\nsticky header/footer can stick against the document. Rather than duplicate the\nread-and-reflect logic in each of those components, they share this controller.\n\nThe mode is derived upstream by nldd-shell. When a shell is present the\nhost registers as a consumer and shell pushes an authoritative re-read on\nevery change (a bare `--context-scroll-mode` update would otherwise not reach\nthe resize-polling layers in time — rAF runs before ResizeObserver). Without\na shell (a stand-alone page), it falls back to re-reading on window resize\nso a manual/media-query override still works. `nldd-page` keeps its own inline\nlogic because it also has to re-wire scroll listeners.",
39313
39701
  "name": "ScrollModeController",
39314
39702
  "members": [
39315
39703
  {
@@ -39365,6 +39753,12 @@
39365
39753
  }
39366
39754
  }
39367
39755
  },
39756
+ {
39757
+ "kind": "field",
39758
+ "name": "_adopt",
39759
+ "privacy": "private",
39760
+ "description": "Switches from stand-alone to push once a provider that was not yet\ndefined at connect is."
39761
+ },
39368
39762
  {
39369
39763
  "kind": "method",
39370
39764
  "name": "hostDisconnected",
@@ -39391,7 +39785,7 @@
39391
39785
  }
39392
39786
  }
39393
39787
  ],
39394
- "description": "ScrollModeConsumer — nldd-app-view pushes the mode it derived. When a mode is\npassed it is applied directly; this is race-free, whereas re-reading\n`getComputedStyle` during a synchronous push can return a stale value for a\ndeeply-nested host (the var may not have propagated through an ancestor's\npending re-render yet). With no argument (resize / no app-view) the inherited\nvar is re-read instead."
39788
+ "description": "ScrollModeConsumer — nldd-shell pushes the mode it derived. When a mode is\npassed it is applied directly; this is race-free, whereas re-reading\n`getComputedStyle` during a synchronous push can return a stale value for a\ndeeply-nested host (the var may not have propagated through an ancestor's\npending re-render yet). With no argument (resize / no shell) the inherited\nvar is re-read instead."
39395
39789
  },
39396
39790
  {
39397
39791
  "kind": "method",
@@ -39438,6 +39832,14 @@
39438
39832
  "module": "src/utilities/scroll-mode-controller.ts"
39439
39833
  }
39440
39834
  },
39835
+ {
39836
+ "kind": "js",
39837
+ "name": "whenScrollModeProviderDefined",
39838
+ "declaration": {
39839
+ "name": "whenScrollModeProviderDefined",
39840
+ "module": "src/utilities/scroll-mode-controller.ts"
39841
+ }
39842
+ },
39441
39843
  {
39442
39844
  "kind": "js",
39443
39845
  "name": "ScrollModeController",