@orange-halo/components 2.1.0 → 3.0.0

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 (130) hide show
  1. package/custom-elements.json +968 -362
  2. package/dist/base.d.ts.map +1 -1
  3. package/dist/base.js +1 -2
  4. package/dist/base.js.map +1 -1
  5. package/dist/index.d.ts +4 -8
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +2 -4
  8. package/dist/index.js.map +1 -1
  9. package/dist/oh-accordion.d.ts +53 -8
  10. package/dist/oh-accordion.d.ts.map +1 -1
  11. package/dist/oh-accordion.js +99 -29
  12. package/dist/oh-accordion.js.map +1 -1
  13. package/dist/oh-alert.d.ts +26 -8
  14. package/dist/oh-alert.d.ts.map +1 -1
  15. package/dist/oh-alert.js +96 -36
  16. package/dist/oh-alert.js.map +1 -1
  17. package/dist/oh-badge.d.ts +32 -13
  18. package/dist/oh-badge.d.ts.map +1 -1
  19. package/dist/oh-badge.js +38 -19
  20. package/dist/oh-badge.js.map +1 -1
  21. package/dist/oh-breadcrumb.d.ts +39 -12
  22. package/dist/oh-breadcrumb.d.ts.map +1 -1
  23. package/dist/oh-breadcrumb.js +66 -25
  24. package/dist/oh-breadcrumb.js.map +1 -1
  25. package/dist/oh-button.d.ts +49 -23
  26. package/dist/oh-button.d.ts.map +1 -1
  27. package/dist/oh-button.figma.js +1 -3
  28. package/dist/oh-button.figma.js.map +1 -1
  29. package/dist/oh-button.js +133 -82
  30. package/dist/oh-button.js.map +1 -1
  31. package/dist/oh-card.d.ts +47 -19
  32. package/dist/oh-card.d.ts.map +1 -1
  33. package/dist/oh-card.js +143 -96
  34. package/dist/oh-card.js.map +1 -1
  35. package/dist/oh-checkbox-group.d.ts +56 -12
  36. package/dist/oh-checkbox-group.d.ts.map +1 -1
  37. package/dist/oh-checkbox-group.figma.js +4 -6
  38. package/dist/oh-checkbox-group.figma.js.map +1 -1
  39. package/dist/oh-checkbox-group.js +114 -49
  40. package/dist/oh-checkbox-group.js.map +1 -1
  41. package/dist/oh-checkbox.d.ts +54 -17
  42. package/dist/oh-checkbox.d.ts.map +1 -1
  43. package/dist/oh-checkbox.js +117 -60
  44. package/dist/oh-checkbox.js.map +1 -1
  45. package/dist/oh-cluster.d.ts +19 -14
  46. package/dist/oh-cluster.d.ts.map +1 -1
  47. package/dist/oh-cluster.js +19 -19
  48. package/dist/oh-cluster.js.map +1 -1
  49. package/dist/oh-container.d.ts +19 -16
  50. package/dist/oh-container.d.ts.map +1 -1
  51. package/dist/oh-container.js +21 -23
  52. package/dist/oh-container.js.map +1 -1
  53. package/dist/oh-drawer.d.ts +28 -11
  54. package/dist/oh-drawer.d.ts.map +1 -1
  55. package/dist/oh-drawer.js +52 -24
  56. package/dist/oh-drawer.js.map +1 -1
  57. package/dist/oh-footer.d.ts +37 -18
  58. package/dist/oh-footer.d.ts.map +1 -1
  59. package/dist/oh-footer.js +38 -19
  60. package/dist/oh-footer.js.map +1 -1
  61. package/dist/oh-grid.d.ts +27 -14
  62. package/dist/oh-grid.d.ts.map +1 -1
  63. package/dist/oh-grid.js +28 -21
  64. package/dist/oh-grid.js.map +1 -1
  65. package/dist/oh-icon.d.ts +21 -5
  66. package/dist/oh-icon.d.ts.map +1 -1
  67. package/dist/oh-icon.js +27 -9
  68. package/dist/oh-icon.js.map +1 -1
  69. package/dist/oh-input.d.ts +110 -21
  70. package/dist/oh-input.d.ts.map +1 -1
  71. package/dist/oh-input.figma.js +2 -2
  72. package/dist/oh-input.figma.js.map +1 -1
  73. package/dist/oh-input.js +227 -71
  74. package/dist/oh-input.js.map +1 -1
  75. package/dist/oh-link.d.ts +42 -19
  76. package/dist/oh-link.d.ts.map +1 -1
  77. package/dist/oh-link.js +83 -38
  78. package/dist/oh-link.js.map +1 -1
  79. package/dist/oh-modal.d.ts +35 -6
  80. package/dist/oh-modal.d.ts.map +1 -1
  81. package/dist/oh-modal.js +90 -39
  82. package/dist/oh-modal.js.map +1 -1
  83. package/dist/oh-navbar.d.ts +42 -19
  84. package/dist/oh-navbar.d.ts.map +1 -1
  85. package/dist/oh-navbar.js +44 -20
  86. package/dist/oh-navbar.js.map +1 -1
  87. package/dist/oh-progress.d.ts +26 -7
  88. package/dist/oh-progress.d.ts.map +1 -1
  89. package/dist/oh-progress.js +35 -14
  90. package/dist/oh-progress.js.map +1 -1
  91. package/dist/oh-radio-group.d.ts +55 -13
  92. package/dist/oh-radio-group.d.ts.map +1 -1
  93. package/dist/oh-radio-group.figma.js +2 -2
  94. package/dist/oh-radio-group.figma.js.map +1 -1
  95. package/dist/oh-radio-group.js +122 -51
  96. package/dist/oh-radio-group.js.map +1 -1
  97. package/dist/oh-radio.d.ts +55 -17
  98. package/dist/oh-radio.d.ts.map +1 -1
  99. package/dist/oh-radio.js +120 -61
  100. package/dist/oh-radio.js.map +1 -1
  101. package/dist/oh-select.d.ts +59 -16
  102. package/dist/oh-select.d.ts.map +1 -1
  103. package/dist/oh-select.js +141 -69
  104. package/dist/oh-select.js.map +1 -1
  105. package/dist/oh-skip-link.d.ts +33 -15
  106. package/dist/oh-skip-link.d.ts.map +1 -1
  107. package/dist/oh-skip-link.js +43 -32
  108. package/dist/oh-skip-link.js.map +1 -1
  109. package/dist/oh-stack.d.ts +17 -14
  110. package/dist/oh-stack.d.ts.map +1 -1
  111. package/dist/oh-stack.js +18 -20
  112. package/dist/oh-stack.js.map +1 -1
  113. package/dist/oh-tabs.d.ts +55 -30
  114. package/dist/oh-tabs.d.ts.map +1 -1
  115. package/dist/oh-tabs.js +100 -76
  116. package/dist/oh-tabs.js.map +1 -1
  117. package/dist/oh-textarea.d.ts +129 -0
  118. package/dist/oh-textarea.d.ts.map +1 -0
  119. package/dist/oh-textarea.js +401 -0
  120. package/dist/oh-textarea.js.map +1 -0
  121. package/dist/oh-toggle.d.ts +45 -12
  122. package/dist/oh-toggle.d.ts.map +1 -1
  123. package/dist/oh-toggle.js +84 -34
  124. package/dist/oh-toggle.js.map +1 -1
  125. package/dist/styles/typography.js +1 -1
  126. package/package.json +7 -7
  127. package/dist/oh-hero.d.ts +0 -33
  128. package/dist/oh-hero.d.ts.map +0 -1
  129. package/dist/oh-hero.js +0 -246
  130. package/dist/oh-hero.js.map +0 -1
@@ -8,8 +8,14 @@
8
8
  "declarations": [
9
9
  {
10
10
  "kind": "class",
11
- "description": "",
11
+ "description": "Collapsible sections, each with a heading that shows and hides its content. Use one item for a single show/hide section.\n\n**Use it for** content readers scan by heading and open as needed (FAQs, details, a \"Show as table\" section). **Don't use it for** content most readers need (leave it visible); for switching between views of the same thing (use tabs); or for site navigation.\n\n**Parts:** `items` is an array of `{ heading, hiddenText?, open? }` (in HTML, a JSON array). Item N's content is any markup in a child with `slot=\"item-N\"`, such as a paragraph or a table.\n\n**Variants:** `subtle` (default), inline with surrounding content, its trigger styled as a link; `standout`, each item a separate boxed surface, for when the sections are the page's main content.\n\n**States:** collapsed and expanded per item (any number can be open; `open` sets the starting state), plus hover and focus-visible on the trigger.\n\n**Behaviour:** each trigger is a `<button>` inside a heading at `heading-level` (default 3), so the items fit the page's outline. Click, Enter or Space toggles it. While collapsed, the panel is `aria-hidden` and `inert`, so nothing inside it takes focus. Motion is turned off under `prefers-reduced-motion`.\n\n**Accessibility:** the trigger has `aria-expanded` and `aria-controls`; the panel is a `region` labelled by its trigger. `hiddenText` adds heading text only screen readers hear, so several items with the same visible heading (e.g. \"Show as table\") can be told apart. Set `heading-level` to fit the headings around it.\n\n**Look:** set by tokens. `subtle`: the trigger uses `color.text.link` and an underline set by `decoration.underlineThickness`, `underlineDash` and `underlinePeriod`, which clears on hover; focus is a solid `color.brand.primary` underline; items are divided by `stroke.divider` in `color.border.subtle`. `standout`: each item uses `color.surface.raised`, a `stroke.control` border in `color.border.emphasis` (`color.brand.primary` when expanded), `shape.container` corners and an `elevation.offset.*` shadow in `elevation.color.neutral`, which moves by `lift.hoverMd` on hover. Type uses `typography.body.*`; motion uses `motion.*` tokens.",
12
12
  "name": "OhAccordion",
13
+ "slots": [
14
+ {
15
+ "description": "The content of the item at index N (item-0 is the first)",
16
+ "name": "item-N"
17
+ }
18
+ ],
13
19
  "members": [
14
20
  {
15
21
  "kind": "field",
@@ -18,6 +24,7 @@
18
24
  "text": "AccordionItem[]"
19
25
  },
20
26
  "default": "[]",
27
+ "description": "The sections: { heading, hiddenText?, open? }. In HTML, a JSON array.\nEach item's content is a child with slot=\"item-<index>\".",
21
28
  "attribute": "items"
22
29
  },
23
30
  {
@@ -27,6 +34,7 @@
27
34
  "text": "AccordionVariant"
28
35
  },
29
36
  "default": "\"subtle\"",
37
+ "description": "subtle (inline) or standout (boxed)",
30
38
  "attribute": "variant",
31
39
  "reflects": true
32
40
  },
@@ -37,6 +45,7 @@
37
45
  "text": "HeadingLevel"
38
46
  },
39
47
  "default": "3",
48
+ "description": "The heading level of each item's trigger, to fit the page's outline",
40
49
  "attribute": "heading-level",
41
50
  "reflects": true
42
51
  }
@@ -48,6 +57,7 @@
48
57
  "text": "AccordionItem[]"
49
58
  },
50
59
  "default": "[]",
60
+ "description": "The sections: { heading, hiddenText?, open? }. In HTML, a JSON array.\nEach item's content is a child with slot=\"item-<index>\".",
51
61
  "fieldName": "items"
52
62
  },
53
63
  {
@@ -56,6 +66,7 @@
56
66
  "text": "AccordionVariant"
57
67
  },
58
68
  "default": "\"subtle\"",
69
+ "description": "subtle (inline) or standout (boxed)",
59
70
  "fieldName": "variant"
60
71
  },
61
72
  {
@@ -64,6 +75,7 @@
64
75
  "text": "HeadingLevel"
65
76
  },
66
77
  "default": "3",
78
+ "description": "The heading level of each item's trigger, to fit the page's outline",
67
79
  "fieldName": "headingLevel"
68
80
  }
69
81
  ],
@@ -100,8 +112,28 @@
100
112
  "declarations": [
101
113
  {
102
114
  "kind": "class",
103
- "description": "",
115
+ "description": "A message box that tells the user about the result of an action or something that needs their attention.\n\n**Use it for** feedback on what just happened (saved, failed) or a notice about the page or account, near the content it's about. **Don't use it for** a short status label (use `oh-badge`); for a field's validation error (use the field's own error message); or for a message that must interrupt the user (use `oh-modal`).\n\n**Variants:** `info` (default), `success`, `warning`, `error`, each by its feedback role. Each has its own icon, so the meaning isn't carried by colour alone.\n\n**Behaviour:** with `dismissible`, a \"Close\" button follows the content; selecting it fires `oh-dismiss` and sets `hidden` on the alert. Content goes in the default slot and can include links.\n\n**Accessibility:** set `live` only for an alert added after the page has rendered (e.g. after submit); it adds `role=\"alert\"` so screen readers announce it. Leave it off for alerts present on page load. Icons are `aria-hidden`; put the meaning in the text. Links show a solid outline in the current text colour on focus; the close button shows an underline.\n\n**Look:** set by tokens. Each variant uses `color.feedback.<variant>Subtle` for the background and `color.feedback.<variant>` for the border, icon and links; text is `color.text.primary`. `stroke.control` sets the border, `shape.container` the corners, `typography.body.*` the text, and `decoration.underlineThickness`, `underlineDash` and `underlinePeriod` the link underline. The close button uses `closeButton.backgroundHover`, `closeButton.shadowHover`, `elevation.offset.*`, `lift.*` and `shape.compact`.",
104
116
  "name": "OhAlert",
117
+ "cssParts": [
118
+ {
119
+ "description": "The alert box.",
120
+ "name": "alert"
121
+ },
122
+ {
123
+ "description": "The message wrapper.",
124
+ "name": "content"
125
+ },
126
+ {
127
+ "description": "The close button (only when `dismissible`).",
128
+ "name": "close"
129
+ }
130
+ ],
131
+ "slots": [
132
+ {
133
+ "description": "The message. Can include links.",
134
+ "name": ""
135
+ }
136
+ ],
105
137
  "members": [
106
138
  {
107
139
  "kind": "field",
@@ -135,6 +167,12 @@
135
167
  "reflects": true
136
168
  }
137
169
  ],
170
+ "events": [
171
+ {
172
+ "description": "When the close button is selected, before the alert hides.",
173
+ "name": "oh-dismiss"
174
+ }
175
+ ],
138
176
  "attributes": [
139
177
  {
140
178
  "name": "variant",
@@ -195,8 +233,24 @@
195
233
  "declarations": [
196
234
  {
197
235
  "kind": "class",
198
- "description": "",
236
+ "description": "A short, non-interactive label that shows the status or category of the thing next to it.\n\n**Use it for** a status (\"Delivered\", \"Pending\"), a count or a tag next to the item it describes. **Don't use it for** anything the user can select (use `oh-button` or a link); or for a message with more than a word or two (use `oh-alert`).\n\n**Variants:** `brand` (default) and `accent` for categories; `success`, `warning`, `error` and `info` for status. **Appearance:** `subtle` (default), for most badges; `filled`, the stronger appearance, for the one status that matters most.\n\n**Parts:** the default slot holds the text; the `icon` slot an optional leading icon, sized to the text.\n\n**Behaviour:** none. It doesn't take focus or respond to the pointer.\n\n**Accessibility:** the badge is plain text to screen readers, so the text must make sense on its own (say \"Pending\", don't rely on the colour). Mark a decorative icon `aria-hidden`.\n\n**Look:** set by tokens. Subtle uses the variant's `color.feedback.<variant>Subtle`, `color.brand.primarySubtle` or `color.accent.subtle` background with the role colour as text; filled uses the role colour (`color.feedback.<variant>`, `color.brand.primary`, `color.accent.default`) as background with `color.text.on<Role>` as text. `shape.compact` sets the corners; `typography.body.*`, `typography.label.base.fontWeight` and `typography.control.letterSpacing` the text.",
199
237
  "name": "OhBadge",
238
+ "cssParts": [
239
+ {
240
+ "description": "The badge.",
241
+ "name": "badge"
242
+ }
243
+ ],
244
+ "slots": [
245
+ {
246
+ "description": "The badge text.",
247
+ "name": ""
248
+ },
249
+ {
250
+ "description": "Optional leading icon.",
251
+ "name": "icon"
252
+ }
253
+ ],
200
254
  "members": [
201
255
  {
202
256
  "kind": "field",
@@ -210,12 +264,13 @@
210
264
  },
211
265
  {
212
266
  "kind": "field",
213
- "name": "type",
267
+ "name": "appearance",
214
268
  "type": {
215
- "text": "BadgeType"
269
+ "text": "BadgeAppearance"
216
270
  },
217
271
  "default": "\"subtle\"",
218
- "attribute": "type",
272
+ "description": "`subtle` (default) for most badges; `filled`, the stronger appearance, for the one status that matters most",
273
+ "attribute": "appearance",
219
274
  "reflects": true
220
275
  }
221
276
  ],
@@ -229,12 +284,13 @@
229
284
  "fieldName": "variant"
230
285
  },
231
286
  {
232
- "name": "type",
287
+ "name": "appearance",
233
288
  "type": {
234
- "text": "BadgeType"
289
+ "text": "BadgeAppearance"
235
290
  },
236
291
  "default": "\"subtle\"",
237
- "fieldName": "type"
292
+ "description": "`subtle` (default) for most badges; `filled`, the stronger appearance, for the one status that matters most",
293
+ "fieldName": "appearance"
238
294
  }
239
295
  ],
240
296
  "superclass": {
@@ -270,7 +326,7 @@
270
326
  "declarations": [
271
327
  {
272
328
  "kind": "class",
273
- "description": "",
329
+ "description": "A breadcrumb trail showing where the current page sits in the site's hierarchy.\n\n**Use it for** pages two or more levels deep in a hierarchy. **Don't use it\nfor** a site's main navigation (use `oh-navbar`) or for steps in a process.\n\n**Parts:** pass `items`, an array of `{ label, href }`, from the top level\ndown. The last item is the current page and is shown as text, not a link.\n\n**Behaviour:** below the `size.breakpoint.sm` width the trail collapses to a\nsingle \"Back to [parent]\" link to the second-to-last item; with one item,\nnothing shows there. Link underlines retract on hover; keyboard focus\n(`:focus-visible`) shows a solid underline and a background tint.\nTransitions are cut short under `prefers-reduced-motion`. Renders nothing\nwhen `items` is empty.\n\n**Accessibility:** renders `<nav aria-label=\"Breadcrumb\">` with an ordered\nlist, `aria-current=\"page\"` on the last item and `aria-hidden` separators.\nUse one breadcrumb per page.\n\n**Look:** set by tokens — `color.text.link` the links,\n`decoration.underlineThickness`, `decoration.underlineDash` and\n`decoration.underlinePeriod` their underline; `color.brand.primary` the\nfocus underline and `color.surface.hover` the focus tint;\n`color.text.primary` and `typography.label.base.fontWeight` the current\npage; `color.text.secondary` the separators; `typography.body.*` the text;\n`spacing.*` the gaps; `motion.relaxed` and `motion.easeGentle` the\ntransitions.",
274
330
  "name": "OhBreadcrumb",
275
331
  "members": [
276
332
  {
@@ -326,8 +382,28 @@
326
382
  "declarations": [
327
383
  {
328
384
  "kind": "class",
329
- "description": "",
385
+ "description": "A button that starts an action, or a link styled as a button when `href` is set.\n\n**Use it for** actions: submitting, saving, opening a dialog, confirming.\n**Don't use it for** links inside running text (use `oh-link`).\n\n**Variants:** `primary` for the main action, `secondary` for the others,\n`accent` for an action that takes the accent colour role. **Sizes:** `sm`, `md` (default), `lg`.\n**States:** rest, hover, active, focus and `loading`.\n\n**Behaviour:** fires `oh-click` when the inner `<button>` is clicked, except\nwhile `loading`. `loading` shows a spinner, keeps the label for screen\nreaders, sets `aria-busy` and `aria-disabled` and ignores clicks, while the\nbutton stays focusable. With `href` it renders an `<a>` (and\n`target=\"_blank\"` adds `rel=\"noopener noreferrer\"`); link buttons don't fire\n`oh-click`. It has no `disabled` property and doesn't submit a form by\nitself: handle `oh-click`. Under `prefers-reduced-motion` it doesn't move.\n\n**Accessibility:** focus shows a solid underline on the label. An\n`icon-only` button has no visible text, so always set `accessible-label`\n(not `aria-label`, which isn't forwarded into the shadow root).\n\n**Look:** set by tokens — `stroke.control` (border width), `shape.control`\n(corners), `typography.control.*` (type), `button.variant.<variant>.*`\n(background, text, border and shadow colour per state), `button.size.<size>.*`\n(font size, padding, minimum height), `elevation.offset.*` (shadow offset)\nand `lift.hoverMd` / `lift.pressMd` (movement on hover and press).",
330
386
  "name": "OhButton",
387
+ "cssParts": [
388
+ {
389
+ "description": "The inner `<button>` or `<a>`.",
390
+ "name": "button"
391
+ }
392
+ ],
393
+ "slots": [
394
+ {
395
+ "description": "The label.",
396
+ "name": ""
397
+ },
398
+ {
399
+ "description": "An icon before the label.",
400
+ "name": "icon-left"
401
+ },
402
+ {
403
+ "description": "An icon after the label.",
404
+ "name": "icon-right"
405
+ }
406
+ ],
331
407
  "members": [
332
408
  {
333
409
  "kind": "field",
@@ -427,6 +503,12 @@
427
503
  "description": "Blur the internal button/anchor element"
428
504
  }
429
505
  ],
506
+ "events": [
507
+ {
508
+ "description": "The button was clicked (not while loading). `detail.originalEvent` is the click.",
509
+ "name": "oh-click"
510
+ }
511
+ ],
430
512
  "attributes": [
431
513
  {
432
514
  "name": "variant",
@@ -527,8 +609,40 @@
527
609
  "declarations": [
528
610
  {
529
611
  "kind": "class",
530
- "description": "",
612
+ "description": "A surface that groups related content (a summary, a teaser, a settings group), with optional header and footer.\n\n**Use it for** a self-contained block of content among others, or a whole-card link to more detail (`interactive`). **Don't use it for** page layout or spacing alone (use `oh-stack`, `oh-grid`); for a message that needs attention (use `oh-alert`); or for a single action (use `oh-button`).\n\n**Variants:** `default`, the standard card; `featured`, for the one card that should stand out; `subtle`, a quieter card, for dense layouts. **Padding:** `none`, `sm`, `md` (default), `lg` set the content padding (and the header and footer padding to match). With `none`, the content sets its own padding.\n\n**States (interactive only):** rest, hover, active (pressed) and focus-visible.\n\n**Behaviour:** with `interactive`, the card is focusable (`tabindex=\"0\"`), has `role=\"button\"`, and fires `oh-click` on click, Enter or Space. Hover movement is turned off under `prefers-reduced-motion`.\n\n**Accessibility:** focus shows a solid outline (`focus.ringWidth`, `focus.ringColor`, `focus.ringOffset`). Links inside use `color.text.linkRaised`, which keeps contrast on card surfaces. An interactive card is one button: give it a short heading so its accessible name makes sense, and don't put other buttons or links inside it.\n\n**Look:** set by tokens. `card.variant.<variant>.gradientStart`/`gradientMid`/`gradientEnd` set each variant's surface, `card.variant.<variant>.borderColor` and `card.base.borderWidth` its border, `shape.large` the corners, and `elevation.surface.default`/`subtle`/`featured` its shadow. Hover uses `color.border.strong` (or `card.variant.featured.borderColorHover`), `elevation.surface.hover`/`featuredHover` and `lift.hoverMd`/`lift.hoverSm`; active uses `elevation.surface.active`; focus sets the border to `color.brand.primary` and adds `focus.glowColor` with `elevation.surface.focus`/`featuredFocus`. Header and footer dividers use `card.section.dividerColor` and `stroke.divider`; the header surface uses `card.section.headerGradientStart`/`End`, the footer `color.surface.raised` to `color.surface.inset`; motion uses `motion.gentle` and `motion.easeGentle`.",
531
613
  "name": "OhCard",
614
+ "cssParts": [
615
+ {
616
+ "description": "The card surface (the button when `interactive`).",
617
+ "name": "card"
618
+ },
619
+ {
620
+ "description": "The header wrapper.",
621
+ "name": "header"
622
+ },
623
+ {
624
+ "description": "The content wrapper.",
625
+ "name": "content"
626
+ },
627
+ {
628
+ "description": "The footer wrapper.",
629
+ "name": "footer"
630
+ }
631
+ ],
632
+ "slots": [
633
+ {
634
+ "description": "The card's main content.",
635
+ "name": ""
636
+ },
637
+ {
638
+ "description": "Optional header, above the content, with a divider below. Not drawn when nothing is slotted.",
639
+ "name": "header"
640
+ },
641
+ {
642
+ "description": "Optional footer, below the content, with a divider above (e.g. actions). Not drawn when nothing is slotted.",
643
+ "name": "footer"
644
+ }
645
+ ],
532
646
  "members": [
533
647
  {
534
648
  "kind": "field",
@@ -536,7 +650,7 @@
536
650
  "type": {
537
651
  "text": "CardVariant"
538
652
  },
539
- "default": "\"raised\"",
653
+ "default": "\"default\"",
540
654
  "attribute": "variant",
541
655
  "reflects": true
542
656
  },
@@ -561,13 +675,19 @@
561
675
  "reflects": true
562
676
  }
563
677
  ],
678
+ "events": [
679
+ {
680
+ "description": "When an `interactive` card is clicked or activated with Enter or Space. `detail.originalEvent` holds the source event.",
681
+ "name": "oh-click"
682
+ }
683
+ ],
564
684
  "attributes": [
565
685
  {
566
686
  "name": "variant",
567
687
  "type": {
568
688
  "text": "CardVariant"
569
689
  },
570
- "default": "\"raised\"",
690
+ "default": "\"default\"",
571
691
  "fieldName": "variant"
572
692
  },
573
693
  {
@@ -620,17 +740,18 @@
620
740
  "declarations": [
621
741
  {
622
742
  "kind": "class",
623
- "description": "",
743
+ "description": "A set of related checkboxes under one legend, where any number can be\nchosen.\n\n**Use it for** choosing any number of options from a short list, such as\ninterests or notification types. **Don't use it for** one standalone\nyes/no option (use `oh-checkbox`), exactly one choice (use\n`oh-radio-group`, or `oh-select` for a long list), or settings that apply\nstraight away (use `oh-toggle`).\n\n**Parts:** a `label` (rendered as the fieldset's `<legend>`) and a list of `options` (`{ label, value }`).\n`value` is the array of checked option values. **States:** each option\nunchecked, checked, hover, active and focus; the group can be `required`\n(a marker on the label) and in error (set `error-text`).\n\n**Behaviour:** Tab moves through the options and Space toggles one. Each\nchange updates `value` and fires `oh-change` with the new array. The\nnative checkboxes sit in the shadow root, so they don't submit with a\nnative form: read `value` or listen for `oh-change`. `required` doesn't\nvalidate; set the error yourself.\n\n**Accessibility:** a `<fieldset>` with a `<legend>`, so screen readers\nread the label with each option. Always set `label`. The error shows\nafter the legend and before the options, with an icon; the fieldset gets\n`aria-invalid` and `aria-describedby`, and the error is announced\n(`role=\"alert\"`) only when it appears after first render. Focus underlines\nthe option's label.\n\n**Look:** set by tokens — the same as `oh-checkbox`: `stroke.control` in\n`color.border.emphasis` (border), `shape.compact` (corners),\n`elevation.offset.*` with `elevation.color.secondary` / `elevation.color.primary` (shadow),\n`lift.hoverSm` / `lift.pressSm` (movement on hover and press),\n`color.brand.primary` and `color.text.onBrand` (checked),\n`color.feedback.error` and `elevation.color.error` (error); `typography.control.*`\nfor the legend and labels.",
624
744
  "name": "OhCheckboxGroup",
625
745
  "members": [
626
746
  {
627
747
  "kind": "field",
628
- "name": "legend",
748
+ "name": "label",
629
749
  "type": {
630
750
  "text": "string"
631
751
  },
632
752
  "default": "\"\"",
633
- "attribute": "legend"
753
+ "description": "The group's label, rendered as the fieldset's <legend>. Always set one",
754
+ "attribute": "label"
634
755
  },
635
756
  {
636
757
  "kind": "field",
@@ -671,32 +792,30 @@
671
792
  },
672
793
  {
673
794
  "kind": "field",
674
- "name": "error",
675
- "type": {
676
- "text": "boolean"
677
- },
678
- "default": "false",
679
- "attribute": "error",
680
- "reflects": true
681
- },
682
- {
683
- "kind": "field",
684
- "name": "errorMessage",
795
+ "name": "errorText",
685
796
  "type": {
686
797
  "text": "string"
687
798
  },
688
799
  "default": "\"\"",
689
- "attribute": "errormessage"
800
+ "description": "Error shown with the control and linked to it. Setting it puts the\ncontrol in its error state; clear it to leave that state.",
801
+ "attribute": "error-text"
802
+ }
803
+ ],
804
+ "events": [
805
+ {
806
+ "description": "An option was toggled. detail: { value } (the checked values)",
807
+ "name": "oh-change"
690
808
  }
691
809
  ],
692
810
  "attributes": [
693
811
  {
694
- "name": "legend",
812
+ "name": "label",
695
813
  "type": {
696
814
  "text": "string"
697
815
  },
698
816
  "default": "\"\"",
699
- "fieldName": "legend"
817
+ "description": "The group's label, rendered as the fieldset's <legend>. Always set one",
818
+ "fieldName": "label"
700
819
  },
701
820
  {
702
821
  "name": "name",
@@ -731,20 +850,13 @@
731
850
  "fieldName": "required"
732
851
  },
733
852
  {
734
- "name": "error",
735
- "type": {
736
- "text": "boolean"
737
- },
738
- "default": "false",
739
- "fieldName": "error"
740
- },
741
- {
742
- "name": "errormessage",
853
+ "name": "error-text",
743
854
  "type": {
744
855
  "text": "string"
745
856
  },
746
857
  "default": "\"\"",
747
- "fieldName": "errorMessage"
858
+ "description": "Error shown with the control and linked to it. Setting it puts the\ncontrol in its error state; clear it to leave that state.",
859
+ "fieldName": "errorText"
748
860
  }
749
861
  ],
750
862
  "superclass": {
@@ -780,8 +892,22 @@
780
892
  "declarations": [
781
893
  {
782
894
  "kind": "class",
783
- "description": "",
895
+ "description": "A single checkbox with its label, for turning one option on or off.\n\n**Use it for** one yes/no choice, such as agreeing to terms, or as part of\na set where any number can be chosen. **Don't use it for** a set of\nrelated options on its own (use `oh-checkbox-group`, which adds the\nfieldset and legend), one choice from several (use `oh-radio-group`), or a\nsetting that applies straight away (use `oh-toggle`).\n\n**States:** unchecked, checked, hover, active, focus, error (set `error-text`).\n\n**Behaviour:** clicking the box or the label toggles it, as does Space\nwhen it's focused. Each change sets `checked` and fires `oh-change`. The\nnative `<input type=\"checkbox\">` sits in the shadow root, so it doesn't\nsubmit with a native form: read `checked` or listen for `oh-change`. It\nhas no `disabled` property.\n\n**Accessibility:** a real native checkbox, visually hidden, carries the\nrole, state and keyboard behaviour; the drawn box is decoration. Always\nset `label`: it's the checkbox's name. Focus underlines the label. The\nerror message shows under the checkbox with an icon, sets `aria-invalid`\nand is linked with `aria-describedby`; it's announced (`role=\"alert\"`)\nonly when it appears after first render.\n\n**Look:** set by tokens — `stroke.control` in `color.border.emphasis`\n(border), `shape.compact` (corners), `typography.control.*` (label),\n`elevation.offset.*` and `elevation.color.secondary` (shadow), `lift.hoverSm` /\n`lift.pressSm` (movement on hover and press), `color.border.hover`\n(hover), `color.brand.primary` (and its hover and active tokens),\n`color.text.onBrand` and `elevation.color.primary` (checked),\n`color.feedback.error` and `elevation.color.error` (error).",
784
896
  "name": "OhCheckbox",
897
+ "cssParts": [
898
+ {
899
+ "description": "The drawn checkbox",
900
+ "name": "box"
901
+ },
902
+ {
903
+ "description": "The label text",
904
+ "name": "label"
905
+ },
906
+ {
907
+ "description": "The error message",
908
+ "name": "error"
909
+ }
910
+ ],
785
911
  "members": [
786
912
  {
787
913
  "kind": "field",
@@ -822,22 +948,13 @@
822
948
  },
823
949
  {
824
950
  "kind": "field",
825
- "name": "error",
826
- "type": {
827
- "text": "boolean"
828
- },
829
- "default": "false",
830
- "attribute": "error",
831
- "reflects": true
832
- },
833
- {
834
- "kind": "field",
835
- "name": "errorMessage",
951
+ "name": "errorText",
836
952
  "type": {
837
953
  "text": "string"
838
954
  },
839
955
  "default": "\"\"",
840
- "attribute": "errormessage"
956
+ "description": "Error shown with the control and linked to it. Setting it puts the\ncontrol in its error state; clear it to leave that state.",
957
+ "attribute": "error-text"
841
958
  },
842
959
  {
843
960
  "kind": "field",
@@ -851,6 +968,12 @@
851
968
  "reflects": true
852
969
  }
853
970
  ],
971
+ "events": [
972
+ {
973
+ "description": "The checkbox was toggled. detail: { checked, value }",
974
+ "name": "oh-change"
975
+ }
976
+ ],
854
977
  "attributes": [
855
978
  {
856
979
  "name": "checked",
@@ -885,20 +1008,13 @@
885
1008
  "fieldName": "value"
886
1009
  },
887
1010
  {
888
- "name": "error",
889
- "type": {
890
- "text": "boolean"
891
- },
892
- "default": "false",
893
- "fieldName": "error"
894
- },
895
- {
896
- "name": "errormessage",
1011
+ "name": "error-text",
897
1012
  "type": {
898
1013
  "text": "string"
899
1014
  },
900
1015
  "default": "\"\"",
901
- "fieldName": "errorMessage"
1016
+ "description": "Error shown with the control and linked to it. Setting it puts the\ncontrol in its error state; clear it to leave that state.",
1017
+ "fieldName": "errorText"
902
1018
  },
903
1019
  {
904
1020
  "name": "force-state",
@@ -943,8 +1059,14 @@
943
1059
  "declarations": [
944
1060
  {
945
1061
  "kind": "class",
946
- "description": "",
1062
+ "description": "A horizontal group of items that wraps onto new lines when space runs out.\n\n**Use it for** button groups, tags and rows of links. **Don't use it for**\nvertical lists (use `oh-stack`) or equal-width columns (use `oh-grid`).\n\n**Gaps:** `gap` is `none`, `xs` (`spacing.1`), `sm` (`spacing.2`), `md`\n(default, `spacing.4`), `lg` (`spacing.6`) or `xl` (`spacing.8`), between\nitems and between rows. `justify` is `start` (default), `center`, `end`,\n`between` or `around`; `align` is `start`, `center` (default), `end` or\n`baseline`. `nowrap` keeps everything on one line.",
947
1063
  "name": "OhCluster",
1064
+ "slots": [
1065
+ {
1066
+ "description": "The items to group.",
1067
+ "name": ""
1068
+ }
1069
+ ],
948
1070
  "members": [
949
1071
  {
950
1072
  "kind": "field",
@@ -1054,8 +1176,14 @@
1054
1176
  "declarations": [
1055
1177
  {
1056
1178
  "kind": "class",
1057
- "description": "",
1179
+ "description": "A centred wrapper that limits content to a maximum width and adds side padding.\n\n**Use it for** the outer width of a page or section. **Don't use it for**\nspacing between items (use `oh-stack`, `oh-cluster` or `oh-grid`).\n\n**Sizes:** `size` picks the max-width: `sm`, `md`, `lg` (default) and `xl`\nuse `layout.container.sm` to `layout.container.xl`; `full` is the full\nwidth with no side padding. `center` centres the text.\n\n**Behaviour:** side padding is `spacing.4`, rising to `spacing.6` from the\n`size.breakpoint.sm` width and `spacing.8` from `size.breakpoint.lg`.",
1058
1180
  "name": "OhContainer",
1181
+ "slots": [
1182
+ {
1183
+ "description": "The content to contain.",
1184
+ "name": ""
1185
+ }
1186
+ ],
1059
1187
  "members": [
1060
1188
  {
1061
1189
  "kind": "field",
@@ -1129,8 +1257,20 @@
1129
1257
  "declarations": [
1130
1258
  {
1131
1259
  "kind": "class",
1132
- "description": "",
1260
+ "description": "A panel that slides in from the side of the viewport, over the page, for navigation or supplementary content.\n\n**Use it for** a site's navigation on small screens, filters, or settings that relate to the page behind. **Don't use it for** a decision the user must make before going on (use `oh-modal`); or for content that should always be visible (put it in the page).\n\n**Parts:** `heading` (an optional visible `h2`), a built-in Close button, and the default slot for the content, which scrolls when it's taller than the viewport.\n\n**Positions:** `left` (default) or `right`.\n\n**Behaviour:** set `open`, or call `show()` and `hide()`. On open, focus moves to the Close button, Tab and Shift+Tab wrap inside the panel, and the page behind stops scrolling. The Close button, Escape, a click on the backdrop and `hide()` close it and fire `oh-close`; focus then returns to the element that opened it. While closed the panel is `inert`. Motion is off under `prefers-reduced-motion`.\n\n**Accessibility:** the panel is `role=\"dialog\"` with `aria-modal=\"true\"`, labelled by `heading`, or \"Navigation menu\" when there's no heading, so set `heading` for any other use. The Close button's accessible name is \"Close menu\".\n\n**Look:** set by tokens. `color.surface.overlay` sets the backdrop and `color.surface.base` the panel. A left drawer's shadow is `elevation.strong`; a right drawer's is an `elevation.offset.lg` offset in `color.border.strong`. The heading uses `typography.heading.h5.fontSize` and `typography.emphasis.fontWeight`. Motion uses `motion.relaxed` and `motion.easeGentle`. `--oh-drawer-width` sets the width.",
1133
1261
  "name": "OhDrawer",
1262
+ "cssProperties": [
1263
+ {
1264
+ "description": "Width of the drawer. It never fills the whole viewport width.",
1265
+ "name": "--oh-drawer-width"
1266
+ }
1267
+ ],
1268
+ "slots": [
1269
+ {
1270
+ "description": "Default slot for drawer content",
1271
+ "name": ""
1272
+ }
1273
+ ],
1134
1274
  "members": [
1135
1275
  {
1136
1276
  "kind": "field",
@@ -1178,7 +1318,8 @@
1178
1318
  "name": "oh-close",
1179
1319
  "type": {
1180
1320
  "text": "CustomEvent"
1181
- }
1321
+ },
1322
+ "description": "When the drawer is closed by the Close button, Escape, the backdrop or `hide()`. Not fired when you set `open` to false yourself."
1182
1323
  }
1183
1324
  ],
1184
1325
  "attributes": [
@@ -1242,8 +1383,22 @@
1242
1383
  "declarations": [
1243
1384
  {
1244
1385
  "kind": "class",
1245
- "description": "",
1386
+ "description": "A site footer with a logo, copyright line, social links and columns of links.\n\n**Use it for** the footer at the bottom of every page. **Don't use it for**\nthe main navigation (use `oh-navbar`).\n\n**Parts:** the `logo` slot; `copyright`, a line of text under the logo;\nthe `social` slot for `oh-icon` links (with `inverse`); and the default\nslot, where each `oh-stack` becomes a column (start it with a heading, then\n`oh-link`s with `inverse`).\n\n**Behaviour:** the columns follow `oh-grid`'s four-column steps at the\n`size.breakpoint.*` widths; at and below `size.breakpoint.md` the logo\ncolumn spans the full width.\n\n**Accessibility:** renders a `<footer>`. Give the logo an accessible name,\neach social icon a `label`, and the column headings a level that fits the\npage's outline.\n\n**Look:** set by tokens — `color.accent.default` the background,\n`color.text.onAccent` the text, `typography.body.*` the type, `spacing.8`\nthe vertical padding.",
1246
1387
  "name": "OhFooter",
1388
+ "slots": [
1389
+ {
1390
+ "description": "Slot for logo element",
1391
+ "name": "logo"
1392
+ },
1393
+ {
1394
+ "description": "Slot for social media icons",
1395
+ "name": "social"
1396
+ },
1397
+ {
1398
+ "description": "Default slot for link columns (use oh-stack for each column)",
1399
+ "name": ""
1400
+ }
1401
+ ],
1247
1402
  "members": [
1248
1403
  {
1249
1404
  "kind": "field",
@@ -1300,8 +1455,14 @@
1300
1455
  "declarations": [
1301
1456
  {
1302
1457
  "kind": "class",
1303
- "description": "",
1458
+ "description": "A CSS grid of equal-width columns, fixed or as many as fit.\n\n**Use it for** cards, galleries and other sets of similar items. **Don't\nuse it for** a single column (use `oh-stack`) or items of varying width in\na row (use `oh-cluster`).\n\n**Columns:** `columns` is `1`–`4`, `auto-fit` (default) or `auto-fill`.\nAuto columns are at least `min-width` wide (any CSS length); `auto-fit`\nstretches the items to fill the row, `auto-fill` keeps empty tracks.\n**Gaps:** `gap` is `none`, `xs` (`spacing.1`), `sm` (`spacing.2`), `md`\n(default, `spacing.4`), `lg` (`spacing.6`) or `xl` (`spacing.8`).\n`align-items` is `start`, `center`, `end` or `stretch` (default).\n\n**Behaviour:** fixed columns respond to the viewport: up to\n`size.breakpoint.sm` they become one column; up to `size.breakpoint.md`,\n3 and 4 become 2; up to `size.breakpoint.lg`, 4 becomes 3.",
1304
1459
  "name": "OhGrid",
1460
+ "slots": [
1461
+ {
1462
+ "description": "The grid items.",
1463
+ "name": ""
1464
+ }
1465
+ ],
1305
1466
  "members": [
1306
1467
  {
1307
1468
  "kind": "field",
@@ -1406,371 +1567,286 @@
1406
1567
  },
1407
1568
  {
1408
1569
  "kind": "javascript-module",
1409
- "path": "src/oh-hero.ts",
1570
+ "path": "src/oh-icon.ts",
1410
1571
  "declarations": [
1411
1572
  {
1412
1573
  "kind": "class",
1413
- "description": "",
1414
- "name": "OhHero",
1574
+ "description": "An icon from the system's built-in set, shown on its own, with a label, or as an icon-only link.\n\n**Use it for** an icon next to text, an icon that carries meaning on its own (with `label`), or a compact link such as a social profile (`href` + `label`). **Don't use it for** an icon-only button (use `oh-button` with `icon-only`); or for an image or logo (use `<img>`).\n\n**Names:** `name` picks the icon: social (`twitter`, `github`, `linkedin`, `instagram`, `youtube`, `facebook`, `email`, `substack`), navigation (`arrow-*`, `chevron-*`, `external-link`), actions (`close`, `plus`, `minus`, `check`, `search`, `menu`, `settings`, `heart`, `sparkle`) and feedback (`info`, `warning`, `error`, `success`). An unknown name renders nothing and logs a warning.\n\n**Sizes:** with no `size` the icon is 1em and follows the text; `sm`, `md`, `lg`, `xl` set fixed sizes. **`inverse`:** for icons on an accent-coloured or dark background.\n\n**Behaviour:** the icon takes the current text colour. With `href` it renders as a link, with hover, active and focus-visible states; `target=\"_blank\"` adds `rel=\"noopener noreferrer\"`.\n\n**Accessibility:** without `label` the icon is decorative (`aria-hidden=\"true\"`). With `label` it's `role=\"img\"` with that name. As a link, `label` is required (it logs a warning without one) and becomes the link's `aria-label`. Focus-visible shows a solid ring in `focus.ringColor` (`color.text.onAccent` when `inverse`).\n\n**Look:** set by tokens. The icon is `currentColor`; `inverse` sets `color.text.onAccent`. As a link: `shape.compact` corners, hover moves by `lift.hoverMd` with an `elevation.offset.lg` shadow in `color.border.default` (`color.text.onAccent` when `inverse`); motion uses `motion.snappy` and `motion.easeGentle`, off under `prefers-reduced-motion`.",
1575
+ "name": "OhIcon",
1415
1576
  "members": [
1416
1577
  {
1417
1578
  "kind": "field",
1418
- "name": "variant",
1579
+ "name": "name",
1419
1580
  "type": {
1420
- "text": "HeroVariant"
1581
+ "text": "IconName"
1421
1582
  },
1422
- "default": "\"content\"",
1423
- "attribute": "variant",
1424
- "reflects": true
1583
+ "default": "\"info\"",
1584
+ "attribute": "name"
1425
1585
  },
1426
1586
  {
1427
1587
  "kind": "field",
1428
1588
  "name": "size",
1429
1589
  "type": {
1430
- "text": "HeroSize"
1590
+ "text": "IconSize | undefined"
1431
1591
  },
1432
- "default": "\"lg\"",
1433
1592
  "attribute": "size",
1434
1593
  "reflects": true
1435
1594
  },
1436
1595
  {
1437
1596
  "kind": "field",
1438
- "name": "heading",
1439
- "type": {
1440
- "text": "string"
1441
- },
1442
- "default": "\"\"",
1443
- "attribute": "heading"
1444
- },
1445
- {
1446
- "kind": "field",
1447
- "name": "subtitle",
1597
+ "name": "inverse",
1448
1598
  "type": {
1449
- "text": "string"
1599
+ "text": "boolean"
1450
1600
  },
1451
- "default": "\"\"",
1452
- "attribute": "subtitle"
1601
+ "default": "false",
1602
+ "attribute": "inverse",
1603
+ "reflects": true
1453
1604
  },
1454
1605
  {
1455
1606
  "kind": "field",
1456
- "name": "journeyName",
1607
+ "name": "label",
1457
1608
  "type": {
1458
- "text": "string"
1609
+ "text": "string | undefined"
1459
1610
  },
1460
- "default": "\"\"",
1461
- "attribute": "journey-name"
1611
+ "attribute": "label"
1462
1612
  },
1463
1613
  {
1464
1614
  "kind": "field",
1465
- "name": "currentStep",
1615
+ "name": "href",
1466
1616
  "type": {
1467
- "text": "number"
1617
+ "text": "string | undefined"
1468
1618
  },
1469
- "default": "1",
1470
- "attribute": "current-step"
1619
+ "attribute": "href"
1471
1620
  },
1472
1621
  {
1473
1622
  "kind": "field",
1474
- "name": "totalSteps",
1623
+ "name": "target",
1475
1624
  "type": {
1476
- "text": "number"
1625
+ "text": "string | undefined"
1477
1626
  },
1478
- "default": "1",
1479
- "attribute": "total-steps"
1627
+ "attribute": "target"
1480
1628
  }
1481
1629
  ],
1482
1630
  "attributes": [
1483
1631
  {
1484
- "name": "variant",
1632
+ "name": "name",
1485
1633
  "type": {
1486
- "text": "HeroVariant"
1634
+ "text": "IconName"
1487
1635
  },
1488
- "default": "\"content\"",
1489
- "fieldName": "variant"
1636
+ "default": "\"info\"",
1637
+ "fieldName": "name"
1490
1638
  },
1491
1639
  {
1492
1640
  "name": "size",
1493
1641
  "type": {
1494
- "text": "HeroSize"
1642
+ "text": "IconSize | undefined"
1495
1643
  },
1496
- "default": "\"lg\"",
1497
1644
  "fieldName": "size"
1498
1645
  },
1499
1646
  {
1500
- "name": "heading",
1501
- "type": {
1502
- "text": "string"
1503
- },
1504
- "default": "\"\"",
1505
- "fieldName": "heading"
1506
- },
1507
- {
1508
- "name": "subtitle",
1647
+ "name": "inverse",
1509
1648
  "type": {
1510
- "text": "string"
1649
+ "text": "boolean"
1511
1650
  },
1512
- "default": "\"\"",
1513
- "fieldName": "subtitle"
1651
+ "default": "false",
1652
+ "fieldName": "inverse"
1514
1653
  },
1515
1654
  {
1516
- "name": "journey-name",
1655
+ "name": "label",
1517
1656
  "type": {
1518
- "text": "string"
1657
+ "text": "string | undefined"
1519
1658
  },
1520
- "default": "\"\"",
1521
- "fieldName": "journeyName"
1659
+ "fieldName": "label"
1522
1660
  },
1523
1661
  {
1524
- "name": "current-step",
1662
+ "name": "href",
1525
1663
  "type": {
1526
- "text": "number"
1664
+ "text": "string | undefined"
1527
1665
  },
1528
- "default": "1",
1529
- "fieldName": "currentStep"
1666
+ "fieldName": "href"
1530
1667
  },
1531
1668
  {
1532
- "name": "total-steps",
1669
+ "name": "target",
1533
1670
  "type": {
1534
- "text": "number"
1671
+ "text": "string | undefined"
1535
1672
  },
1536
- "default": "1",
1537
- "fieldName": "totalSteps"
1673
+ "fieldName": "target"
1538
1674
  }
1539
1675
  ],
1540
1676
  "superclass": {
1541
- "name": "LitElement",
1542
- "package": "lit"
1677
+ "name": "OhElement",
1678
+ "module": "/src/base.js"
1543
1679
  },
1544
- "tagName": "oh-hero",
1680
+ "tagName": "oh-icon",
1545
1681
  "customElement": true
1546
1682
  }
1547
1683
  ],
1548
1684
  "exports": [
1549
1685
  {
1550
1686
  "kind": "js",
1551
- "name": "OhHero",
1687
+ "name": "OhIcon",
1552
1688
  "declaration": {
1553
- "name": "OhHero",
1554
- "module": "src/oh-hero.ts"
1689
+ "name": "OhIcon",
1690
+ "module": "src/oh-icon.ts"
1555
1691
  }
1556
1692
  },
1557
1693
  {
1558
1694
  "kind": "custom-element-definition",
1559
- "name": "oh-hero",
1695
+ "name": "oh-icon",
1560
1696
  "declaration": {
1561
- "name": "OhHero",
1562
- "module": "src/oh-hero.ts"
1697
+ "name": "OhIcon",
1698
+ "module": "src/oh-icon.ts"
1563
1699
  }
1564
1700
  }
1565
1701
  ]
1566
1702
  },
1567
1703
  {
1568
1704
  "kind": "javascript-module",
1569
- "path": "src/oh-icon.ts",
1705
+ "path": "src/oh-input.ts",
1570
1706
  "declarations": [
1571
1707
  {
1572
1708
  "kind": "class",
1573
- "description": "",
1574
- "name": "OhIcon",
1709
+ "description": "A single-line text field that submits with a native form, with optional\ntyping suggestions.\n\n**Use it for** short free text: names, email addresses, search terms.\n**Don't use it for** several lines (use `oh-textarea`) or a choice from a\nfixed list (use `oh-select`, or `oh-radio-group` for a few options).\n`suggestions` offers values while still allowing any text.\n\n**Types:** `text` (default), `email`, `password`, `search`, `tel`, `url`.\nOne size. **States:** rest, hover, focus, error (set `error-text`),\ndisabled, required.\n\n**Behaviour:** form-associated: the value submits under `name`, `required`\nblocks submission (validity comes from the inner `<input>`), a form reset\nrestores the starting value, and a disabled `<fieldset>` disables it.\nFires `oh-input` as the text changes and `oh-change` when it's committed.\n`suggestions` renders a native `<datalist>`, so the browser handles its\nkeyboard and screen reader support. `autocomplete` is passed to the inner\n`<input>`.\n\n**Accessibility:** always set `label`: it's the field's name. The error\nshows after the label and before the field, with an icon, and is linked\nwith `aria-describedby` and `aria-invalid`; it's announced (`role=\"alert\"`)\nonly when it appears after first render. Helper text is linked the same\nway (it's hidden while an error shows). Focus is a solid inset ring.\nSet `autocomplete` for personal data (WCAG 1.3.5).\n\n**Look:** set by tokens — `input.base.borderWidth` (`stroke.control`) in\n`color.border.emphasis` (border), `shape.control` (corners),\n`typography.control.*` (type), `input.size.md.minHeight` (height),\n`elevation.offset.md` and `elevation.color.field` (inset shadow),\n`color.border.hover` (hover), `focus.ringColor` and\n`color.surface.highlight` (focus), `color.feedback.error`,\n`color.feedback.errorSubtle` and `elevation.color.error` (error),\n`color.surface.disabled`, `color.border.disabled` and\n`color.text.disabled` (disabled).",
1710
+ "name": "OhInput",
1711
+ "cssParts": [
1712
+ {
1713
+ "description": "The visible label",
1714
+ "name": "label"
1715
+ },
1716
+ {
1717
+ "description": "The text field",
1718
+ "name": "input"
1719
+ },
1720
+ {
1721
+ "description": "The helper text, and the error message (which also has the error part)",
1722
+ "name": "helper"
1723
+ },
1724
+ {
1725
+ "description": "The error message",
1726
+ "name": "error"
1727
+ }
1728
+ ],
1575
1729
  "members": [
1576
1730
  {
1577
1731
  "kind": "field",
1578
- "name": "name",
1732
+ "name": "formAssociated",
1579
1733
  "type": {
1580
- "text": "IconName"
1734
+ "text": "boolean"
1581
1735
  },
1582
- "default": "\"info\"",
1583
- "attribute": "name"
1736
+ "static": true,
1737
+ "default": "true"
1584
1738
  },
1585
1739
  {
1586
1740
  "kind": "field",
1587
- "name": "size",
1741
+ "name": "type",
1588
1742
  "type": {
1589
- "text": "IconSize | undefined"
1743
+ "text": "InputType"
1590
1744
  },
1591
- "attribute": "size",
1592
- "reflects": true
1745
+ "default": "\"text\"",
1746
+ "description": "The kind of text: text, email, password, search, tel or url",
1747
+ "attribute": "type"
1593
1748
  },
1594
1749
  {
1595
1750
  "kind": "field",
1596
- "name": "inverse",
1751
+ "name": "value",
1597
1752
  "type": {
1598
- "text": "boolean"
1753
+ "text": "string"
1599
1754
  },
1600
- "default": "false",
1601
- "attribute": "inverse",
1602
- "reflects": true
1603
- },
1604
- {
1605
- "kind": "field",
1606
- "name": "label",
1607
- "type": {
1608
- "text": "string | undefined"
1609
- },
1610
- "attribute": "label"
1755
+ "default": "\"\"",
1756
+ "description": "The text in the field",
1757
+ "attribute": "value"
1611
1758
  },
1612
1759
  {
1613
1760
  "kind": "field",
1614
- "name": "href",
1761
+ "name": "placeholder",
1615
1762
  "type": {
1616
- "text": "string | undefined"
1763
+ "text": "string"
1617
1764
  },
1618
- "attribute": "href"
1765
+ "default": "\"\"",
1766
+ "description": "Example text shown while the field is empty. Not a replacement for the label",
1767
+ "attribute": "placeholder"
1619
1768
  },
1620
1769
  {
1621
1770
  "kind": "field",
1622
- "name": "target",
1623
- "type": {
1624
- "text": "string | undefined"
1625
- },
1626
- "attribute": "target"
1627
- }
1628
- ],
1629
- "attributes": [
1630
- {
1631
- "name": "name",
1632
- "type": {
1633
- "text": "IconName"
1634
- },
1635
- "default": "\"info\"",
1636
- "fieldName": "name"
1637
- },
1638
- {
1639
- "name": "size",
1640
- "type": {
1641
- "text": "IconSize | undefined"
1642
- },
1643
- "fieldName": "size"
1644
- },
1645
- {
1646
- "name": "inverse",
1647
- "type": {
1648
- "text": "boolean"
1649
- },
1650
- "default": "false",
1651
- "fieldName": "inverse"
1652
- },
1653
- {
1654
1771
  "name": "label",
1655
1772
  "type": {
1656
- "text": "string | undefined"
1657
- },
1658
- "fieldName": "label"
1659
- },
1660
- {
1661
- "name": "href",
1662
- "type": {
1663
- "text": "string | undefined"
1773
+ "text": "string"
1664
1774
  },
1665
- "fieldName": "href"
1775
+ "default": "\"\"",
1776
+ "description": "The visible label. Always set one: it names the field",
1777
+ "attribute": "label"
1666
1778
  },
1667
- {
1668
- "name": "target",
1669
- "type": {
1670
- "text": "string | undefined"
1671
- },
1672
- "fieldName": "target"
1673
- }
1674
- ],
1675
- "superclass": {
1676
- "name": "OhElement",
1677
- "module": "/src/base.js"
1678
- },
1679
- "tagName": "oh-icon",
1680
- "customElement": true
1681
- }
1682
- ],
1683
- "exports": [
1684
- {
1685
- "kind": "js",
1686
- "name": "OhIcon",
1687
- "declaration": {
1688
- "name": "OhIcon",
1689
- "module": "src/oh-icon.ts"
1690
- }
1691
- },
1692
- {
1693
- "kind": "custom-element-definition",
1694
- "name": "oh-icon",
1695
- "declaration": {
1696
- "name": "OhIcon",
1697
- "module": "src/oh-icon.ts"
1698
- }
1699
- }
1700
- ]
1701
- },
1702
- {
1703
- "kind": "javascript-module",
1704
- "path": "src/oh-input.ts",
1705
- "declarations": [
1706
- {
1707
- "kind": "class",
1708
- "description": "",
1709
- "name": "OhInput",
1710
- "members": [
1711
1779
  {
1712
1780
  "kind": "field",
1713
- "name": "type",
1781
+ "name": "helperText",
1714
1782
  "type": {
1715
- "text": "InputType"
1783
+ "text": "string"
1716
1784
  },
1717
- "default": "\"text\"",
1718
- "attribute": "type"
1785
+ "default": "\"\"",
1786
+ "description": "Help shown under the field and linked to it",
1787
+ "attribute": "helper-text"
1719
1788
  },
1720
1789
  {
1721
1790
  "kind": "field",
1722
- "name": "value",
1791
+ "name": "errorText",
1723
1792
  "type": {
1724
1793
  "text": "string"
1725
1794
  },
1726
1795
  "default": "\"\"",
1727
- "attribute": "value"
1796
+ "description": "Error shown before the field and linked to it. Setting it puts the field in its error state",
1797
+ "attribute": "error-text"
1728
1798
  },
1729
1799
  {
1730
1800
  "kind": "field",
1731
- "name": "placeholder",
1801
+ "name": "name",
1732
1802
  "type": {
1733
1803
  "text": "string"
1734
1804
  },
1735
1805
  "default": "\"\"",
1736
- "attribute": "placeholder"
1806
+ "description": "The name the value is submitted under",
1807
+ "attribute": "name",
1808
+ "reflects": true
1737
1809
  },
1738
1810
  {
1739
1811
  "kind": "field",
1740
- "name": "label",
1812
+ "name": "required",
1741
1813
  "type": {
1742
- "text": "string"
1814
+ "text": "boolean"
1743
1815
  },
1744
- "default": "\"\"",
1745
- "attribute": "label"
1816
+ "default": "false",
1817
+ "description": "Must be filled in before the form submits",
1818
+ "attribute": "required",
1819
+ "reflects": true
1746
1820
  },
1747
1821
  {
1748
1822
  "kind": "field",
1749
- "name": "helperText",
1823
+ "name": "disabled",
1750
1824
  "type": {
1751
- "text": "string"
1825
+ "text": "boolean"
1752
1826
  },
1753
- "default": "\"\"",
1754
- "attribute": "helpertext"
1827
+ "default": "false",
1828
+ "description": "Not editable, and left out of the form's data",
1829
+ "attribute": "disabled",
1830
+ "reflects": true
1755
1831
  },
1756
1832
  {
1757
1833
  "kind": "field",
1758
- "name": "errorText",
1834
+ "name": "suggestions",
1759
1835
  "type": {
1760
- "text": "string"
1836
+ "text": "string[]"
1761
1837
  },
1762
- "default": "\"\"",
1763
- "attribute": "errortext"
1838
+ "default": "[]",
1839
+ "description": "Values offered while typing, shown by the browser as a list under the\nfield. They suggest, they don't restrict: any text is still allowed.\nSet it as a property (an array of strings) or, in HTML, as a JSON array:\nsuggestions='[\"Option one\",\"Option two\"]'. Browsers also offer the\nfield's autofill history, so set autocomplete=\"off\" to show only these.",
1840
+ "attribute": "suggestions"
1764
1841
  },
1765
1842
  {
1766
1843
  "kind": "field",
1767
- "name": "required",
1844
+ "name": "autocomplete",
1768
1845
  "type": {
1769
- "text": "boolean"
1846
+ "text": "string | undefined"
1770
1847
  },
1771
- "default": "false",
1772
- "attribute": "required",
1773
- "reflects": true
1848
+ "description": "The input's purpose, for autofill and assistive tech (WCAG 1.3.5):\nan HTML autocomplete token such as \"email\", \"name\" or \"tel\".\nPassed to the inner <input>.",
1849
+ "attribute": "autocomplete"
1774
1850
  },
1775
1851
  {
1776
1852
  "kind": "field",
@@ -1783,13 +1859,66 @@
1783
1859
  "attribute": "force-state",
1784
1860
  "reflects": true
1785
1861
  },
1862
+ {
1863
+ "kind": "field",
1864
+ "name": "form",
1865
+ "description": "The form this field belongs to",
1866
+ "readonly": true
1867
+ },
1786
1868
  {
1787
1869
  "kind": "method",
1788
- "name": "focus"
1870
+ "name": "focus",
1871
+ "parameters": [
1872
+ {
1873
+ "name": "options",
1874
+ "optional": true,
1875
+ "type": {
1876
+ "text": "FocusOptions"
1877
+ }
1878
+ }
1879
+ ]
1789
1880
  },
1790
1881
  {
1791
1882
  "kind": "method",
1792
1883
  "name": "blur"
1884
+ },
1885
+ {
1886
+ "kind": "method",
1887
+ "name": "formResetCallback"
1888
+ },
1889
+ {
1890
+ "kind": "method",
1891
+ "name": "formDisabledCallback",
1892
+ "parameters": [
1893
+ {
1894
+ "name": "disabled",
1895
+ "type": {
1896
+ "text": "boolean"
1897
+ }
1898
+ }
1899
+ ]
1900
+ },
1901
+ {
1902
+ "kind": "method",
1903
+ "name": "formStateRestoreCallback",
1904
+ "parameters": [
1905
+ {
1906
+ "name": "state",
1907
+ "type": {
1908
+ "text": "string | File | FormData | null"
1909
+ }
1910
+ }
1911
+ ]
1912
+ }
1913
+ ],
1914
+ "events": [
1915
+ {
1916
+ "description": "Whenever the text changes: typing, or picking a suggestion. detail: { value, originalEvent }",
1917
+ "name": "oh-input"
1918
+ },
1919
+ {
1920
+ "description": "When the value is committed (on blur or Enter). detail: { value, originalEvent }",
1921
+ "name": "oh-change"
1793
1922
  }
1794
1923
  ],
1795
1924
  "attributes": [
@@ -1799,6 +1928,7 @@
1799
1928
  "text": "InputType"
1800
1929
  },
1801
1930
  "default": "\"text\"",
1931
+ "description": "The kind of text: text, email, password, search, tel or url",
1802
1932
  "fieldName": "type"
1803
1933
  },
1804
1934
  {
@@ -1807,6 +1937,7 @@
1807
1937
  "text": "string"
1808
1938
  },
1809
1939
  "default": "\"\"",
1940
+ "description": "The text in the field",
1810
1941
  "fieldName": "value"
1811
1942
  },
1812
1943
  {
@@ -1815,6 +1946,7 @@
1815
1946
  "text": "string"
1816
1947
  },
1817
1948
  "default": "\"\"",
1949
+ "description": "Example text shown while the field is empty. Not a replacement for the label",
1818
1950
  "fieldName": "placeholder"
1819
1951
  },
1820
1952
  {
@@ -1823,32 +1955,71 @@
1823
1955
  "text": "string"
1824
1956
  },
1825
1957
  "default": "\"\"",
1958
+ "description": "The visible label. Always set one: it names the field",
1826
1959
  "fieldName": "label"
1827
1960
  },
1828
1961
  {
1829
- "name": "helpertext",
1962
+ "name": "helper-text",
1830
1963
  "type": {
1831
1964
  "text": "string"
1832
1965
  },
1833
1966
  "default": "\"\"",
1967
+ "description": "Help shown under the field and linked to it",
1834
1968
  "fieldName": "helperText"
1835
1969
  },
1836
1970
  {
1837
- "name": "errortext",
1971
+ "name": "error-text",
1838
1972
  "type": {
1839
1973
  "text": "string"
1840
1974
  },
1841
1975
  "default": "\"\"",
1976
+ "description": "Error shown before the field and linked to it. Setting it puts the field in its error state",
1842
1977
  "fieldName": "errorText"
1843
1978
  },
1979
+ {
1980
+ "name": "name",
1981
+ "type": {
1982
+ "text": "string"
1983
+ },
1984
+ "default": "\"\"",
1985
+ "description": "The name the value is submitted under",
1986
+ "fieldName": "name"
1987
+ },
1844
1988
  {
1845
1989
  "name": "required",
1846
1990
  "type": {
1847
1991
  "text": "boolean"
1848
1992
  },
1849
1993
  "default": "false",
1994
+ "description": "Must be filled in before the form submits",
1850
1995
  "fieldName": "required"
1851
1996
  },
1997
+ {
1998
+ "name": "disabled",
1999
+ "type": {
2000
+ "text": "boolean"
2001
+ },
2002
+ "default": "false",
2003
+ "description": "Not editable, and left out of the form's data",
2004
+ "fieldName": "disabled"
2005
+ },
2006
+ {
2007
+ "name": "suggestions",
2008
+ "type": {
2009
+ "text": "string[]"
2010
+ },
2011
+ "default": "[]",
2012
+ "description": "Values offered while typing, shown by the browser as a list under the\nfield. They suggest, they don't restrict: any text is still allowed.\nSet it as a property (an array of strings) or, in HTML, as a JSON array:\nsuggestions='[\"Option one\",\"Option two\"]'. Browsers also offer the\nfield's autofill history, so set autocomplete=\"off\" to show only these.",
2013
+ "fieldName": "suggestions"
2014
+ },
2015
+ {
2016
+ "name": "autocomplete",
2017
+ "type": {
2018
+ "text": "string | undefined"
2019
+ },
2020
+ "description": "The input's purpose, for autofill and assistive tech (WCAG 1.3.5):\nan HTML autocomplete token such as \"email\", \"name\" or \"tel\".\nPassed to the inner <input>.",
2021
+ "fieldName": "autocomplete"
2022
+ },
1852
2023
  {
1853
2024
  "name": "force-state",
1854
2025
  "type": {
@@ -1892,8 +2063,14 @@
1892
2063
  "declarations": [
1893
2064
  {
1894
2065
  "kind": "class",
1895
- "description": "",
2066
+ "description": "A text link, for use inside body copy or on its own as a call to action.\n\n**Use it for** navigating to another page or place. **Don't use it for**\nactions that don't navigate (use `oh-button` instead).\n\n**Variants:** `inline` (default) sits in running text; `standalone` is\nlarger and bolder for links on their own, and can show a trailing arrow\n(`arrow`). `inverse` is for links on accent surfaces.\n\n**Behaviour:** renders a native `<a>`, so Enter follows it and it takes\nfocus in tab order. On hover the underline retracts and the arrow nudges\nforward. Keyboard focus (`:focus-visible`) shows a solid underline and a\ntint; mouse focus doesn't. Transitions are cut short under\n`prefers-reduced-motion`. With `target=\"_blank\"` it adds an external icon,\nscreen-reader text \"(opens in new tab)\" and `rel=\"noopener noreferrer\"`\nwhen `rel` isn't set; the arrow is not shown on external links.\n\n**Accessibility:** the underline shows at rest and on focus, so links\ndon't rely on colour. Write link text that makes sense out of context.\n\n**Look:** set by tokens — `color.text.link` the colour (`color.text.onAccent`\nwhen `inverse`); `decoration.underlineThickness`, `decoration.underlineDash`\nand `decoration.underlinePeriod` the underline; `color.brand.primary`\n(`color.text.onAccent` when `inverse`) and\n`decoration.underlineFocusThickness` the focus underline; `focus.glowColor`\n(`link.inverse.focusBackground` when `inverse`) the focus tint;\n`typography.body.fontFamily`, plus `typography.body.lg.fontSize` and\n`typography.emphasis.fontWeight` for `standalone`; `motion.slow` and\n`motion.snappy` the transitions.",
1896
2067
  "name": "OhLink",
2068
+ "slots": [
2069
+ {
2070
+ "description": "The link text.",
2071
+ "name": ""
2072
+ }
2073
+ ],
1897
2074
  "members": [
1898
2075
  {
1899
2076
  "kind": "field",
@@ -2034,8 +2211,40 @@
2034
2211
  "declarations": [
2035
2212
  {
2036
2213
  "kind": "class",
2037
- "description": "",
2214
+ "description": "A dialog that opens over the page and holds the user's attention until they close it or act on it.\n\n**Use it for** a short task or decision that must be done before going on: a confirmation, a small form. **Don't use it for** content the user may want alongside the page (use `oh-drawer`); for a message that doesn't need an answer (use `oh-alert`); or for long, multi-step flows (use a page).\n\n**Parts:** `heading` (a visible `h2`); the default slot for the body, which scrolls when it's taller than the viewport; the `footer` slot for actions.\n\n**Sizes:** `sm`, `md` (default) and `lg` set the dialog's width (never wider than the viewport).\n\n**Behaviour:** set `open` to show it. On open, focus moves to the Close button (or the first focusable element when there's none), Tab and Shift+Tab wrap inside the dialog, and the page behind stops scrolling. On close, focus returns to the element that had it. With `dismissible` (the default), the Close button, Escape and a click on the backdrop each fire `oh-close` and set `open` to false; without it, only your own buttons close it. Motion is reduced under `prefers-reduced-motion`.\n\n**Accessibility:** the panel is `role=\"dialog\"` with `aria-modal=\"true\"`, named by `heading`. Without a visible heading, set `accessible-label` (not `aria-label` on the host, which isn't forwarded). The close button has a visible \"Close\" label.\n\n**Look:** set by tokens. `modal.overlay` sets the backdrop; the panel uses `color.surface.base`, a `stroke.control` border in `color.border.emphasis`, `shape.container` corners and an `elevation.offset.2xl` shadow in `elevation.color.overlay`. Header and footer dividers use `stroke.control` in `color.border.subtle`; the title uses `typography.heading.h4.*`, the body `typography.body.*`. The close button uses `closeButton.*`, `lift.*` and `shape.compact`. Motion uses `motion.gentle` and `motion.easeEmphasized`.",
2038
2215
  "name": "OhModal",
2216
+ "cssParts": [
2217
+ {
2218
+ "description": "The dialog panel.",
2219
+ "name": "modal"
2220
+ },
2221
+ {
2222
+ "description": "The header (heading and close button).",
2223
+ "name": "header"
2224
+ },
2225
+ {
2226
+ "description": "The close button (only when `dismissible`).",
2227
+ "name": "close"
2228
+ },
2229
+ {
2230
+ "description": "The scrolling body.",
2231
+ "name": "body"
2232
+ },
2233
+ {
2234
+ "description": "The footer.",
2235
+ "name": "footer"
2236
+ }
2237
+ ],
2238
+ "slots": [
2239
+ {
2240
+ "description": "The dialog body.",
2241
+ "name": ""
2242
+ },
2243
+ {
2244
+ "description": "Actions, below the body.",
2245
+ "name": "footer"
2246
+ }
2247
+ ],
2039
2248
  "members": [
2040
2249
  {
2041
2250
  "kind": "field",
@@ -2056,6 +2265,15 @@
2056
2265
  "default": "\"\"",
2057
2266
  "attribute": "heading"
2058
2267
  },
2268
+ {
2269
+ "kind": "field",
2270
+ "name": "accessibleLabel",
2271
+ "type": {
2272
+ "text": "string | undefined"
2273
+ },
2274
+ "description": "Names the dialog when it has no visible heading. Use this rather than\naria-label on the host, which isn't forwarded into the shadow root.\nA visible heading always wins.",
2275
+ "attribute": "accessible-label"
2276
+ },
2059
2277
  {
2060
2278
  "kind": "field",
2061
2279
  "name": "dismissible",
@@ -2077,6 +2295,12 @@
2077
2295
  "reflects": true
2078
2296
  }
2079
2297
  ],
2298
+ "events": [
2299
+ {
2300
+ "description": "When the user closes the dialog with the Close button, Escape or the backdrop. Not fired when you set `open` to false yourself.",
2301
+ "name": "oh-close"
2302
+ }
2303
+ ],
2080
2304
  "attributes": [
2081
2305
  {
2082
2306
  "name": "open",
@@ -2094,6 +2318,14 @@
2094
2318
  "default": "\"\"",
2095
2319
  "fieldName": "heading"
2096
2320
  },
2321
+ {
2322
+ "name": "accessible-label",
2323
+ "type": {
2324
+ "text": "string | undefined"
2325
+ },
2326
+ "description": "Names the dialog when it has no visible heading. Use this rather than\naria-label on the host, which isn't forwarded into the shadow root.\nA visible heading always wins.",
2327
+ "fieldName": "accessibleLabel"
2328
+ },
2097
2329
  {
2098
2330
  "name": "dismissible",
2099
2331
  "type": {
@@ -2144,8 +2376,28 @@
2144
2376
  "declarations": [
2145
2377
  {
2146
2378
  "kind": "class",
2147
- "description": "",
2379
+ "description": "A site header bar with a logo and the site's main navigation links, which move into a drawer on narrow viewports.\n\n**Use it for** the main navigation at the top of every page. **Don't use\nit for** in-page sections (use `oh-tabs`) or a trail through the hierarchy\n(use `oh-breadcrumb`).\n\n**Parts:** the `logo` slot (a link to the home page), the default slot for\nthe bar's links (`oh-link`), and the `mobile` slot for the same links in the\ndrawer. `drawer-heading` names the drawer (defaults to \"Menu\").\n\n**Behaviour:** at and below the `size.breakpoint.md` width the links hide\nand an icon-only menu button (\"Open navigation menu\") opens an `oh-drawer`\nfrom the left, which traps focus and closes on Escape or its close button.\n\n**Accessibility:** the bar and the drawer each wrap their links in a\n`<nav>`; the drawer is a modal dialog. Give the logo link an accessible\nname (`alt` on its image, or text).\n\n**Look:** set by tokens — `color.surface.base` the background,\n`focus.glowColor` the shadow, `typography.body.*` the text, `spacing.*` the\npadding and gaps, `stroke.divider` and `color.border.subtle` the dividers\nbetween drawer links. `--oh-navbar-logo-height` sets the logo height.",
2148
2380
  "name": "OhNavbar",
2381
+ "cssProperties": [
2382
+ {
2383
+ "description": "Height of the slotted logo link or image",
2384
+ "name": "--oh-navbar-logo-height"
2385
+ }
2386
+ ],
2387
+ "slots": [
2388
+ {
2389
+ "description": "Slot for logo/brand element",
2390
+ "name": "logo"
2391
+ },
2392
+ {
2393
+ "description": "Default slot for navigation links",
2394
+ "name": ""
2395
+ },
2396
+ {
2397
+ "description": "The navigation links again, shown in the drawer",
2398
+ "name": "mobile"
2399
+ }
2400
+ ],
2149
2401
  "members": [
2150
2402
  {
2151
2403
  "kind": "field",
@@ -2202,11 +2454,25 @@
2202
2454
  "declarations": [
2203
2455
  {
2204
2456
  "kind": "class",
2205
- "description": "",
2457
+ "description": "A bar that shows how much of a task is done, with an optional percentage and visible label.\n\n**Use it for** a task with a known end: an upload, a download, steps completed. **Don't use it for** a wait of unknown length (it has no indeterminate state); or for a measurement that isn't progress, like storage used against a quota (a meter).\n\n**Variants:** `brand` (default), and `success`, `info`, `warning`, `error` by their feedback role. **Sizes:** `sm`, `md` (default), `lg` set the track height and the value's text size. **`inverse`:** for use on a brand-coloured or dark background.\n\n**Behaviour:** `value` runs from 0 to `max` (default 100) and is clamped to that range; the bar and the percentage show `value / max`, rounded. `show-value` (on by default) shows the percentage; `show-label` shows `label` above the bar. The fill's width animates when the value changes, except under `prefers-reduced-motion`.\n\n**Accessibility:** the bar is a `progressbar` with `aria-valuenow`, `aria-valuemin`, `aria-valuemax` and `aria-label` from `label` (default \"Progress\"). Always set `label` to say what is progressing. The visible percentage is `aria-hidden`, since screen readers read the value from the progressbar.\n\n**Look:** set by tokens. The track uses `color.surface.inset`, a `stroke.control` border in `color.border.default`, `shape.pill` corners and an inset `elevation.offset.sm` shadow in `progress.track.insetShadow`. The fill is `color.brand.primary` or `color.feedback.<variant>`. Text uses `color.text.primary` and `typography.body.*`. Inverse uses `progress.inverse.trackBackground`, `progress.inverse.trackBorder`, `progress.inverse.fill` and `color.text.onBrand`. Motion uses `motion.relaxed` and `motion.easeGentle`.",
2206
2458
  "name": "OhProgress",
2207
- "members": [
2459
+ "cssParts": [
2208
2460
  {
2209
- "kind": "field",
2461
+ "description": "The bar's track.",
2462
+ "name": "track"
2463
+ },
2464
+ {
2465
+ "description": "The filled part of the track.",
2466
+ "name": "fill"
2467
+ },
2468
+ {
2469
+ "description": "The percentage text.",
2470
+ "name": "value"
2471
+ }
2472
+ ],
2473
+ "members": [
2474
+ {
2475
+ "kind": "field",
2210
2476
  "name": "value",
2211
2477
  "type": {
2212
2478
  "text": "number"
@@ -2408,7 +2674,7 @@
2408
2674
  "declarations": [
2409
2675
  {
2410
2676
  "kind": "class",
2411
- "description": "",
2677
+ "description": "A set of radio buttons under one label, where exactly one can be chosen.\n\n**Use it for** one choice from a few options that should all be visible,\nsuch as a plan or a delivery speed. **Don't use it for** a long list (use\n`oh-select`), several choices (use `oh-checkbox-group`) or an on/off\nsetting (use `oh-toggle` or `oh-checkbox`). Use it rather than separate\n`oh-radio` elements, which can't form a group.\n\n**Parts:** a `label` for the group and a list of `options`\n(`{ label, value }`). `value` is the chosen option's value. **States:**\neach option unchecked, checked, hover, active and focus; the group can be\n`required` and in error (set `error-text`).\n\n**Behaviour:** Tab moves into and out of the group; arrow keys move\nbetween options and choose them (the browser's native radio behaviour).\nEach change sets `value` and fires `oh-change`. The native radios sit in\nthe shadow root, so they don't submit with a native form: read `value` or\nlisten for `oh-change`. `required` sets `aria-required` and a marker on\nthe label but doesn't validate; set the error yourself.\n\n**Accessibility:** `role=\"radiogroup\"` labelled by `label`, so always set\none. The error shows after the label and before the options, with an\nicon; the group gets `aria-invalid` and `aria-describedby`, and the error\nis announced (`role=\"alert\"`) only when it appears after first render.\nFocus underlines the option's label.\n\n**Look:** set by tokens — the same as `oh-radio`: `stroke.control` in\n`color.border.emphasis` (border), `shape.pill` (circle),\n`elevation.offset.*` with `elevation.color.secondary` / `elevation.color.primary` (shadow),\n`lift.hoverSm` / `lift.pressSm` (movement on hover and press),\n`color.brand.primary` and `color.text.onBrand` (checked),\n`color.feedback.error` and `elevation.color.error` (error); `typography.control.*`\nfor the group label and option labels.",
2412
2678
  "name": "OhRadioGroup",
2413
2679
  "members": [
2414
2680
  {
@@ -2459,22 +2725,19 @@
2459
2725
  },
2460
2726
  {
2461
2727
  "kind": "field",
2462
- "name": "error",
2463
- "type": {
2464
- "text": "boolean"
2465
- },
2466
- "default": "false",
2467
- "attribute": "error",
2468
- "reflects": true
2469
- },
2470
- {
2471
- "kind": "field",
2472
- "name": "errorMessage",
2728
+ "name": "errorText",
2473
2729
  "type": {
2474
2730
  "text": "string"
2475
2731
  },
2476
2732
  "default": "\"\"",
2477
- "attribute": "errormessage"
2733
+ "description": "Error shown with the control and linked to it. Setting it puts the\ncontrol in its error state; clear it to leave that state.",
2734
+ "attribute": "error-text"
2735
+ }
2736
+ ],
2737
+ "events": [
2738
+ {
2739
+ "description": "An option was chosen. detail: { value }",
2740
+ "name": "oh-change"
2478
2741
  }
2479
2742
  ],
2480
2743
  "attributes": [
@@ -2519,20 +2782,13 @@
2519
2782
  "fieldName": "required"
2520
2783
  },
2521
2784
  {
2522
- "name": "error",
2523
- "type": {
2524
- "text": "boolean"
2525
- },
2526
- "default": "false",
2527
- "fieldName": "error"
2528
- },
2529
- {
2530
- "name": "errormessage",
2785
+ "name": "error-text",
2531
2786
  "type": {
2532
2787
  "text": "string"
2533
2788
  },
2534
2789
  "default": "\"\"",
2535
- "fieldName": "errorMessage"
2790
+ "description": "Error shown with the control and linked to it. Setting it puts the\ncontrol in its error state; clear it to leave that state.",
2791
+ "fieldName": "errorText"
2536
2792
  }
2537
2793
  ],
2538
2794
  "superclass": {
@@ -2568,8 +2824,22 @@
2568
2824
  "declarations": [
2569
2825
  {
2570
2826
  "kind": "class",
2571
- "description": "",
2827
+ "description": "A single radio button with its label.\n\n**Use it for** a one-off radio you manage yourself. **For a set of\nchoices, use `oh-radio-group`.** Each `oh-radio` keeps its native radio\ninside its own shadow root, so two of them with the same `name` don't form\na group: checking one doesn't uncheck the other, and arrow keys don't move\nbetween them. `oh-radio-group` renders the whole set in one place, with\narrow-key navigation and one label for the group. For an independent\non/off choice use `oh-checkbox`.\n\n**States:** unchecked, checked, hover, active, focus, error (set `error-text`).\n\n**Behaviour:** clicking the circle or label checks it. Checking sets\n`checked` and fires `oh-change`. The native radio sits in the shadow\nroot, so it doesn't submit with a native form.\n\n**Accessibility:** a real native radio, visually hidden, carries the role\nand state; the drawn circle is decoration. Always set `label`: it's the\nradio's name. Focus underlines the label. The error message shows under\nthe radio with an icon, sets `aria-invalid` and is linked with\n`aria-describedby`; it's announced (`role=\"alert\"`) only when it appears\nafter first render.\n\n**Look:** set by tokens — `stroke.control` in `color.border.emphasis`\n(border), `shape.pill` (circle), `typography.control.*` (label),\n`elevation.offset.*` and `elevation.color.secondary` (shadow), `lift.hoverSm` /\n`lift.pressSm` (movement on hover and press), `color.border.hover`\n(hover), `color.brand.primary` (and its hover and active tokens),\n`color.text.onBrand` and `elevation.color.primary` (checked),\n`color.feedback.error` and `elevation.color.error` (error).",
2572
2828
  "name": "OhRadio",
2829
+ "cssParts": [
2830
+ {
2831
+ "description": "The drawn radio circle",
2832
+ "name": "circle"
2833
+ },
2834
+ {
2835
+ "description": "The label text",
2836
+ "name": "label"
2837
+ },
2838
+ {
2839
+ "description": "The error message",
2840
+ "name": "error"
2841
+ }
2842
+ ],
2573
2843
  "members": [
2574
2844
  {
2575
2845
  "kind": "field",
@@ -2610,22 +2880,13 @@
2610
2880
  },
2611
2881
  {
2612
2882
  "kind": "field",
2613
- "name": "error",
2614
- "type": {
2615
- "text": "boolean"
2616
- },
2617
- "default": "false",
2618
- "attribute": "error",
2619
- "reflects": true
2620
- },
2621
- {
2622
- "kind": "field",
2623
- "name": "errorMessage",
2883
+ "name": "errorText",
2624
2884
  "type": {
2625
2885
  "text": "string"
2626
2886
  },
2627
2887
  "default": "\"\"",
2628
- "attribute": "errormessage"
2888
+ "description": "Error shown with the control and linked to it. Setting it puts the\ncontrol in its error state; clear it to leave that state.",
2889
+ "attribute": "error-text"
2629
2890
  },
2630
2891
  {
2631
2892
  "kind": "field",
@@ -2639,6 +2900,12 @@
2639
2900
  "reflects": true
2640
2901
  }
2641
2902
  ],
2903
+ "events": [
2904
+ {
2905
+ "description": "The radio was checked. detail: { checked, value }",
2906
+ "name": "oh-change"
2907
+ }
2908
+ ],
2642
2909
  "attributes": [
2643
2910
  {
2644
2911
  "name": "checked",
@@ -2673,20 +2940,13 @@
2673
2940
  "fieldName": "value"
2674
2941
  },
2675
2942
  {
2676
- "name": "error",
2677
- "type": {
2678
- "text": "boolean"
2679
- },
2680
- "default": "false",
2681
- "fieldName": "error"
2682
- },
2683
- {
2684
- "name": "errormessage",
2943
+ "name": "error-text",
2685
2944
  "type": {
2686
2945
  "text": "string"
2687
2946
  },
2688
2947
  "default": "\"\"",
2689
- "fieldName": "errorMessage"
2948
+ "description": "Error shown with the control and linked to it. Setting it puts the\ncontrol in its error state; clear it to leave that state.",
2949
+ "fieldName": "errorText"
2690
2950
  },
2691
2951
  {
2692
2952
  "name": "force-state",
@@ -2731,7 +2991,7 @@
2731
2991
  "declarations": [
2732
2992
  {
2733
2993
  "kind": "class",
2734
- "description": "",
2994
+ "description": "A dropdown for choosing one option from a list.\n\n**Use it for** one choice from a list too long to show every option.\n**Don't use it for** a few options (use `oh-radio-group`, which shows them\nall), several choices (use `oh-checkbox-group`) or free text (use\n`oh-input` with `suggestions`).\n\n**Parts:** a trigger showing the selected option's label (or\n`placeholder`), and a list of `options` (`{ label, value }`). One size.\n**States:** rest, hover, active, focus, open, error (set `error-text`),\nrequired.\n\n**Behaviour:** click the trigger, or press Enter, Space or an arrow key,\nto open the list. Arrow keys, Home and End move the highlight, Enter or\nSpace selects, Escape and Tab close, and clicking outside closes. Typing\nletters jumps to a matching option (and selects it while the list is\nclosed). Selecting sets `value`, returns focus to the trigger and fires\n`oh-change`. It isn't form-associated: it doesn't submit with a native\nform, so read `value` or listen for `oh-change`. It has no `disabled`\nproperty.\n\n**Accessibility:** the trigger is a `combobox` controlling a `listbox`,\nwith `aria-activedescendant` for the highlighted option, so focus stays\non the trigger. Always set `label`: it names the trigger and the list.\nThe error shows after the label and before the trigger, with an icon, sets\n`aria-invalid` and is linked with `aria-describedby`; it's announced\n(`role=\"alert\"`) only when it appears after first render. Focus is a\nsolid underline on the trigger text.\n\n**Look:** set by tokens — `stroke.control` in `color.border.emphasis`\n(border), `shape.control` (trigger corners), `shape.container` (list\ncorners), `typography.control.*` (type), `elevation.offset.*` and\n`elevation.color.secondary` (shadow), `lift.hoverMd` / `lift.pressSm` (movement\non hover and press), `color.border.hover` (hover), `focus.ringColor` and\n`color.surface.highlight` (open), `color.surface.hover` and\n`color.brand.primary` (selected option), `color.feedback.error` and\n`elevation.color.error` (error).",
2735
2995
  "name": "OhSelect",
2736
2996
  "members": [
2737
2997
  {
@@ -2796,7 +3056,7 @@
2796
3056
  "text": "string"
2797
3057
  },
2798
3058
  "default": "\"\"",
2799
- "attribute": "helpertext"
3059
+ "attribute": "helper-text"
2800
3060
  },
2801
3061
  {
2802
3062
  "kind": "field",
@@ -2805,7 +3065,13 @@
2805
3065
  "text": "string"
2806
3066
  },
2807
3067
  "default": "\"\"",
2808
- "attribute": "errortext"
3068
+ "attribute": "error-text"
3069
+ }
3070
+ ],
3071
+ "events": [
3072
+ {
3073
+ "description": "An option was selected. detail: { value }",
3074
+ "name": "oh-change"
2809
3075
  }
2810
3076
  ],
2811
3077
  "attributes": [
@@ -2858,7 +3124,7 @@
2858
3124
  "fieldName": "required"
2859
3125
  },
2860
3126
  {
2861
- "name": "helpertext",
3127
+ "name": "helper-text",
2862
3128
  "type": {
2863
3129
  "text": "string"
2864
3130
  },
@@ -2866,7 +3132,7 @@
2866
3132
  "fieldName": "helperText"
2867
3133
  },
2868
3134
  {
2869
- "name": "errortext",
3135
+ "name": "error-text",
2870
3136
  "type": {
2871
3137
  "text": "string"
2872
3138
  },
@@ -2907,7 +3173,7 @@
2907
3173
  "declarations": [
2908
3174
  {
2909
3175
  "kind": "class",
2910
- "description": "",
3176
+ "description": "A \"skip to content\" link that lets keyboard users jump past repeated content, such as navigation.\n\n**Use it for** the first focusable element on every page, pointing at the\nmain content. Add more for other landmarks (search results, footer) if\nuseful. **Don't use it for** in-page navigation that everyone sees (use\n`oh-link`).\n\n**Parts:** `href` is the target (defaults to `#main`); `text` is the label\n(defaults to \"Skip to main content\").\n\n**Behaviour:** hidden until it receives keyboard focus, then shown fixed at\nthe top-left of the viewport, above other content. Enter follows the link.\nTransitions are cut short under `prefers-reduced-motion`.\n\n**Accessibility:** screen readers can read it at all times. Put it first in\nthe page, and give the target an `id` and `tabindex=\"-1\"` so focus moves to\nit.\n\n**Look:** set by tokens — `color.surface.base`, `color.border.emphasis` and\n`color.text.link` at rest; `color.surface.raised`, `color.text.linkRaised`\nand `color.brand.primary` (border) on focus; `stroke.control` the border,\n`shape.control` the corners; `elevation.offset.lg` with `elevation.color.neutral`\n(`elevation.color.primary` on focus) the shadow; `typography.body.*` and\n`typography.label.base.fontWeight` the text; `spacing.*` the padding and\nposition; `motion.gentle`, `motion.quick` and `motion.snappy` the\ntransitions.",
2911
3177
  "name": "OhSkipLink",
2912
3178
  "members": [
2913
3179
  {
@@ -2980,8 +3246,14 @@
2980
3246
  "declarations": [
2981
3247
  {
2982
3248
  "kind": "class",
2983
- "description": "",
3249
+ "description": "A vertical layout that spaces its children evenly, top to bottom.\n\n**Use it for** consistent vertical rhythm without margins on children.\n**Don't use it for** items in a row (use `oh-cluster`) or a grid of cards\n(use `oh-grid`).\n\n**Gaps:** `gap` is `none`, `xs` (`spacing.1`), `sm` (`spacing.2`), `md`\n(default, `spacing.4`), `lg` (`spacing.6`), `xl` (`spacing.8`) or `2xl`\n(`spacing.12`). `align` sets horizontal alignment: `start`, `center`,\n`end` or `stretch` (default).",
2984
3250
  "name": "OhStack",
3251
+ "slots": [
3252
+ {
3253
+ "description": "The items to stack.",
3254
+ "name": ""
3255
+ }
3256
+ ],
2985
3257
  "members": [
2986
3258
  {
2987
3259
  "kind": "field",
@@ -3055,28 +3327,28 @@
3055
3327
  "declarations": [
3056
3328
  {
3057
3329
  "kind": "class",
3058
- "description": "",
3330
+ "description": "A set of tabs that switches between panels of related content in the same place.\n\n**Use it for** a few peer sections of content where only one needs to be\nseen at a time. **Don't use it for** navigating between pages (use links\nor `oh-navbar`), or for content people need to compare side by side.\n\n**Parts:** pass `items`, an array of `{ id, label, content? }`. A panel\nshows `content` as text, or else the light-DOM element with\n`slot=\"<id>\"`. `value` is the selected tab's `id` (defaults to the first).\n\n**States:** each tab is selected or not; unselected tabs show an underline\non hover.\n\n**Behaviour:** click selects a tab. Arrow keys move focus between tabs and\nwrap (Left/Right, or Up/Down when `orientation=\"vertical\"`; orientation\nchanges the keys only, not the layout); Home/End jump to the first/last.\nEnter or Space selects the focused tab and moves focus to its panel.\nSelecting a different tab fires `oh-change`. Transitions are cut short\nunder `prefers-reduced-motion`.\n\n**Accessibility:** tablist/tab/tabpanel roles with `aria-selected`,\n`aria-controls` and `aria-labelledby`; one tab is in the tab order at a\ntime; inactive panels are `hidden`; the active panel is focusable. Keyboard\nfocus shows a solid underline on the tab label and an outline on the panel.\nKeep labels short.\n\n**Look:** set by tokens — `color.brand.primary` the unselected tabs and\ntheir hover underline (`decoration.underlineThickness`,\n`decoration.underlineDash`, `decoration.underlinePeriod`);\n`color.text.primary`, `color.surface.base` and `color.border.emphasis` the\nselected tab and panel; `stroke.control` the borders; `shape.control` the\ntab corners and `shape.container` the panel corners;\n`typography.body.*` and `typography.label.base.fontWeight` the text;\n`spacing.*` the padding; `motion.snappy` and `motion.relaxed` the\ntransitions.",
3059
3331
  "name": "OhTabs",
3060
3332
  "members": [
3061
3333
  {
3062
3334
  "kind": "field",
3063
- "name": "tabs",
3335
+ "name": "items",
3064
3336
  "type": {
3065
3337
  "text": "TabItem[]"
3066
3338
  },
3067
3339
  "default": "[]",
3068
- "description": "Array of tab items with id, label, and optional content",
3069
- "attribute": "tabs"
3340
+ "description": "The tabs: `{ id, label, content? }`. In HTML, a JSON array",
3341
+ "attribute": "items"
3070
3342
  },
3071
3343
  {
3072
3344
  "kind": "field",
3073
- "name": "selected",
3345
+ "name": "value",
3074
3346
  "type": {
3075
3347
  "text": "string"
3076
3348
  },
3077
3349
  "default": "\"\"",
3078
- "description": "ID of the currently selected tab",
3079
- "attribute": "selected",
3350
+ "description": "The selected tab's `id`. Defaults to the first tab",
3351
+ "attribute": "value",
3080
3352
  "reflects": true
3081
3353
  },
3082
3354
  {
@@ -3092,30 +3364,28 @@
3092
3364
  ],
3093
3365
  "events": [
3094
3366
  {
3095
- "name": "tab-change",
3096
- "type": {
3097
- "text": "CustomEvent"
3098
- }
3367
+ "description": "When a different tab is selected. `detail: { value }`, the tab's `id`.",
3368
+ "name": "oh-change"
3099
3369
  }
3100
3370
  ],
3101
3371
  "attributes": [
3102
3372
  {
3103
- "name": "tabs",
3373
+ "name": "items",
3104
3374
  "type": {
3105
3375
  "text": "TabItem[]"
3106
3376
  },
3107
3377
  "default": "[]",
3108
- "description": "Array of tab items with id, label, and optional content",
3109
- "fieldName": "tabs"
3378
+ "description": "The tabs: `{ id, label, content? }`. In HTML, a JSON array",
3379
+ "fieldName": "items"
3110
3380
  },
3111
3381
  {
3112
- "name": "selected",
3382
+ "name": "value",
3113
3383
  "type": {
3114
3384
  "text": "string"
3115
3385
  },
3116
3386
  "default": "\"\"",
3117
- "description": "ID of the currently selected tab",
3118
- "fieldName": "selected"
3387
+ "description": "The selected tab's `id`. Defaults to the first tab",
3388
+ "fieldName": "value"
3119
3389
  },
3120
3390
  {
3121
3391
  "name": "orientation",
@@ -3154,13 +3424,348 @@
3154
3424
  }
3155
3425
  ]
3156
3426
  },
3427
+ {
3428
+ "kind": "javascript-module",
3429
+ "path": "src/oh-textarea.ts",
3430
+ "declarations": [
3431
+ {
3432
+ "kind": "class",
3433
+ "description": "A multi-line text field that submits with a native form.\n\n**Use it for** messages, comments, feedback: text that may run to several\nlines. **Don't use it for** a single line of text (use `oh-input`).\n\n**States:** rest, hover, focus, error (set `error-text`), disabled,\nrequired. `rows` sets the visible lines (default 4); people can drag it\ntaller. `maxlength` limits the length.\n\n**Behaviour:** form-associated. Give it a `name` and it submits with the\nform. `required` stops the form submitting while it's empty, with the\nbrowser's own message. A form reset restores its starting text, and a\ndisabled `<fieldset>` disables it. Fires `oh-input` on every keystroke and\n`oh-change` when the value is committed. Its line height is 1.5 times the\ntext size, rounded up to `grid.unit`, so long messages stay on the grid.\n\n**Accessibility:** always set `label`: it names the field. A placeholder\nisn't a label. Helper and error text are linked to the field with\n`aria-describedby`, so screen readers read them. Errors come before the\nfield, with an icon, set `aria-invalid`, and are announced only when they\nappear after the page has loaded. Focus is a solid inset ring. Use\n`autocomplete` when the field asks for something a browser can fill in,\nsuch as an address (WCAG 1.3.5).\n\n**Look:** set by tokens — `stroke.control` in `color.border.emphasis`\n(border), `shape.control` (corners), `typography.control.*` (type),\n`elevation.offset.md` and `elevation.color.field` (inset shadow),\n`color.border.hover` (hover), `focus.ringColor` and\n`color.surface.highlight` (focus), `color.feedback.error`,\n`color.feedback.errorSubtle` and `elevation.color.error` (error),\n`color.surface.disabled`, `color.border.disabled` and\n`color.text.disabled` (disabled).",
3434
+ "name": "OhTextarea",
3435
+ "cssParts": [
3436
+ {
3437
+ "description": "The visible label",
3438
+ "name": "label"
3439
+ },
3440
+ {
3441
+ "description": "The text field",
3442
+ "name": "textarea"
3443
+ },
3444
+ {
3445
+ "description": "The helper text",
3446
+ "name": "helper"
3447
+ },
3448
+ {
3449
+ "description": "The error message",
3450
+ "name": "error"
3451
+ }
3452
+ ],
3453
+ "members": [
3454
+ {
3455
+ "kind": "field",
3456
+ "name": "formAssociated",
3457
+ "type": {
3458
+ "text": "boolean"
3459
+ },
3460
+ "static": true,
3461
+ "default": "true"
3462
+ },
3463
+ {
3464
+ "kind": "field",
3465
+ "name": "label",
3466
+ "type": {
3467
+ "text": "string"
3468
+ },
3469
+ "default": "\"\"",
3470
+ "description": "The visible label. Always set one: it names the field.",
3471
+ "attribute": "label"
3472
+ },
3473
+ {
3474
+ "kind": "field",
3475
+ "name": "value",
3476
+ "type": {
3477
+ "text": "string"
3478
+ },
3479
+ "default": "\"\"",
3480
+ "description": "The text in the field",
3481
+ "attribute": "value"
3482
+ },
3483
+ {
3484
+ "kind": "field",
3485
+ "name": "placeholder",
3486
+ "type": {
3487
+ "text": "string"
3488
+ },
3489
+ "default": "\"\"",
3490
+ "description": "Example text shown while the field is empty. Not a replacement for the label",
3491
+ "attribute": "placeholder"
3492
+ },
3493
+ {
3494
+ "kind": "field",
3495
+ "name": "helperText",
3496
+ "type": {
3497
+ "text": "string"
3498
+ },
3499
+ "default": "\"\"",
3500
+ "description": "Help shown under the field and linked to it",
3501
+ "attribute": "helper-text"
3502
+ },
3503
+ {
3504
+ "kind": "field",
3505
+ "name": "errorText",
3506
+ "type": {
3507
+ "text": "string"
3508
+ },
3509
+ "default": "\"\"",
3510
+ "description": "Error shown before the field and linked to it. Setting it puts the field in its error state",
3511
+ "attribute": "error-text"
3512
+ },
3513
+ {
3514
+ "kind": "field",
3515
+ "name": "name",
3516
+ "type": {
3517
+ "text": "string"
3518
+ },
3519
+ "default": "\"\"",
3520
+ "description": "The name the value is submitted under",
3521
+ "attribute": "name",
3522
+ "reflects": true
3523
+ },
3524
+ {
3525
+ "kind": "field",
3526
+ "name": "required",
3527
+ "type": {
3528
+ "text": "boolean"
3529
+ },
3530
+ "default": "false",
3531
+ "description": "Must be filled in before the form submits",
3532
+ "attribute": "required",
3533
+ "reflects": true
3534
+ },
3535
+ {
3536
+ "kind": "field",
3537
+ "name": "disabled",
3538
+ "type": {
3539
+ "text": "boolean"
3540
+ },
3541
+ "default": "false",
3542
+ "description": "Not editable, and left out of the form's data",
3543
+ "attribute": "disabled",
3544
+ "reflects": true
3545
+ },
3546
+ {
3547
+ "kind": "field",
3548
+ "name": "rows",
3549
+ "type": {
3550
+ "text": "number"
3551
+ },
3552
+ "default": "4",
3553
+ "description": "Visible lines of text before the field scrolls (people can drag it taller)",
3554
+ "attribute": "rows"
3555
+ },
3556
+ {
3557
+ "kind": "field",
3558
+ "name": "maxlength",
3559
+ "type": {
3560
+ "text": "number | undefined"
3561
+ },
3562
+ "description": "Longest allowed text, in characters",
3563
+ "attribute": "maxlength"
3564
+ },
3565
+ {
3566
+ "kind": "field",
3567
+ "name": "autocomplete",
3568
+ "type": {
3569
+ "text": "string | undefined"
3570
+ },
3571
+ "description": "The field's purpose for autofill and assistive tech (WCAG 1.3.5), e.g. \"street-address\"",
3572
+ "attribute": "autocomplete"
3573
+ },
3574
+ {
3575
+ "kind": "field",
3576
+ "name": "form",
3577
+ "description": "The form this field belongs to",
3578
+ "readonly": true
3579
+ },
3580
+ {
3581
+ "kind": "method",
3582
+ "name": "focus",
3583
+ "parameters": [
3584
+ {
3585
+ "name": "options",
3586
+ "optional": true,
3587
+ "type": {
3588
+ "text": "FocusOptions"
3589
+ }
3590
+ }
3591
+ ]
3592
+ },
3593
+ {
3594
+ "kind": "method",
3595
+ "name": "blur"
3596
+ },
3597
+ {
3598
+ "kind": "method",
3599
+ "name": "formResetCallback"
3600
+ },
3601
+ {
3602
+ "kind": "method",
3603
+ "name": "formDisabledCallback",
3604
+ "parameters": [
3605
+ {
3606
+ "name": "disabled",
3607
+ "type": {
3608
+ "text": "boolean"
3609
+ }
3610
+ }
3611
+ ]
3612
+ },
3613
+ {
3614
+ "kind": "method",
3615
+ "name": "formStateRestoreCallback",
3616
+ "parameters": [
3617
+ {
3618
+ "name": "state",
3619
+ "type": {
3620
+ "text": "string | File | FormData | null"
3621
+ }
3622
+ }
3623
+ ]
3624
+ }
3625
+ ],
3626
+ "events": [
3627
+ {
3628
+ "description": "On every keystroke. detail: { value, originalEvent }",
3629
+ "name": "oh-input"
3630
+ },
3631
+ {
3632
+ "description": "When the value is committed (on blur). detail: { value, originalEvent }",
3633
+ "name": "oh-change"
3634
+ }
3635
+ ],
3636
+ "attributes": [
3637
+ {
3638
+ "name": "label",
3639
+ "type": {
3640
+ "text": "string"
3641
+ },
3642
+ "default": "\"\"",
3643
+ "description": "The visible label. Always set one: it names the field.",
3644
+ "fieldName": "label"
3645
+ },
3646
+ {
3647
+ "name": "value",
3648
+ "type": {
3649
+ "text": "string"
3650
+ },
3651
+ "default": "\"\"",
3652
+ "description": "The text in the field",
3653
+ "fieldName": "value"
3654
+ },
3655
+ {
3656
+ "name": "placeholder",
3657
+ "type": {
3658
+ "text": "string"
3659
+ },
3660
+ "default": "\"\"",
3661
+ "description": "Example text shown while the field is empty. Not a replacement for the label",
3662
+ "fieldName": "placeholder"
3663
+ },
3664
+ {
3665
+ "name": "helper-text",
3666
+ "type": {
3667
+ "text": "string"
3668
+ },
3669
+ "default": "\"\"",
3670
+ "description": "Help shown under the field and linked to it",
3671
+ "fieldName": "helperText"
3672
+ },
3673
+ {
3674
+ "name": "error-text",
3675
+ "type": {
3676
+ "text": "string"
3677
+ },
3678
+ "default": "\"\"",
3679
+ "description": "Error shown before the field and linked to it. Setting it puts the field in its error state",
3680
+ "fieldName": "errorText"
3681
+ },
3682
+ {
3683
+ "name": "name",
3684
+ "type": {
3685
+ "text": "string"
3686
+ },
3687
+ "default": "\"\"",
3688
+ "description": "The name the value is submitted under",
3689
+ "fieldName": "name"
3690
+ },
3691
+ {
3692
+ "name": "required",
3693
+ "type": {
3694
+ "text": "boolean"
3695
+ },
3696
+ "default": "false",
3697
+ "description": "Must be filled in before the form submits",
3698
+ "fieldName": "required"
3699
+ },
3700
+ {
3701
+ "name": "disabled",
3702
+ "type": {
3703
+ "text": "boolean"
3704
+ },
3705
+ "default": "false",
3706
+ "description": "Not editable, and left out of the form's data",
3707
+ "fieldName": "disabled"
3708
+ },
3709
+ {
3710
+ "name": "rows",
3711
+ "type": {
3712
+ "text": "number"
3713
+ },
3714
+ "default": "4",
3715
+ "description": "Visible lines of text before the field scrolls (people can drag it taller)",
3716
+ "fieldName": "rows"
3717
+ },
3718
+ {
3719
+ "name": "maxlength",
3720
+ "type": {
3721
+ "text": "number | undefined"
3722
+ },
3723
+ "description": "Longest allowed text, in characters",
3724
+ "fieldName": "maxlength"
3725
+ },
3726
+ {
3727
+ "name": "autocomplete",
3728
+ "type": {
3729
+ "text": "string | undefined"
3730
+ },
3731
+ "description": "The field's purpose for autofill and assistive tech (WCAG 1.3.5), e.g. \"street-address\"",
3732
+ "fieldName": "autocomplete"
3733
+ }
3734
+ ],
3735
+ "superclass": {
3736
+ "name": "OhElement",
3737
+ "module": "/src/base.js"
3738
+ },
3739
+ "tagName": "oh-textarea",
3740
+ "customElement": true
3741
+ }
3742
+ ],
3743
+ "exports": [
3744
+ {
3745
+ "kind": "js",
3746
+ "name": "OhTextarea",
3747
+ "declaration": {
3748
+ "name": "OhTextarea",
3749
+ "module": "src/oh-textarea.ts"
3750
+ }
3751
+ },
3752
+ {
3753
+ "kind": "custom-element-definition",
3754
+ "name": "oh-textarea",
3755
+ "declaration": {
3756
+ "name": "OhTextarea",
3757
+ "module": "src/oh-textarea.ts"
3758
+ }
3759
+ }
3760
+ ]
3761
+ },
3157
3762
  {
3158
3763
  "kind": "javascript-module",
3159
3764
  "path": "src/oh-toggle.ts",
3160
3765
  "declarations": [
3161
3766
  {
3162
3767
  "kind": "class",
3163
- "description": "",
3768
+ "description": "A switch that turns a setting on or off.\n\n**Use it for** a setting that takes effect straight away, such as turning\nnotifications on. **Don't use it for** a choice that's only applied when a\nform is submitted, or one that must be agreed to (use `oh-checkbox`), or\na choice between more than two options (use `oh-radio-group`).\n\n**States:** off, on, hover, active, focus.\n\n**Behaviour:** clicking the switch or its label, or pressing Space or\nEnter while it's focused, flips `checked` and fires `oh-change` with\n`{ checked }`. `name` and `value` are stored but it isn't form-associated,\nso it doesn't submit with a native form: listen for `oh-change`. It has no\n`disabled` property. Under `prefers-reduced-motion` it doesn't animate.\n\n**Accessibility:** `role=\"switch\"` with `aria-checked`, in the tab order.\nSet `label` (a visible label, linked with `aria-labelledby`), or\n`accessible-label` when there's no visible label (not `aria-label`, which\nisn't forwarded into the shadow root). Focus is a solid outline in\n`focus.ringColor`.\n\n**Look:** set by tokens — `shape.pill` (track), `color.surface.raised` /\n`color.brand.primary` (track off / on), `color.surface.base`,\n`stroke.control` and `color.border.emphasis` (thumb),\n`elevation.offset.*` with `elevation.color.secondary` / `elevation.color.primary` (thumb\nshadow off / on), `lift.hoverSm` / `lift.pressSm` (movement on hover and\npress), `focus.ringColor` and `focus.glowColor` (focus),\n`typography.body.*` (label).",
3164
3769
  "name": "OhToggle",
3165
3770
  "members": [
3166
3771
  {
@@ -3217,7 +3822,8 @@
3217
3822
  "name": "oh-change",
3218
3823
  "type": {
3219
3824
  "text": "CustomEvent"
3220
- }
3825
+ },
3826
+ "description": "Fired when the toggle state changes. detail: { checked }"
3221
3827
  }
3222
3828
  ],
3223
3829
  "attributes": [