@lmfaole/basics 0.3.0 → 0.5.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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +78 -350
  3. package/basic-components/basic-accordion/README.md +53 -0
  4. package/{components → basic-components}/basic-accordion/index.d.ts +5 -5
  5. package/basic-components/basic-accordion/index.js +413 -0
  6. package/basic-components/basic-alert/README.md +48 -0
  7. package/basic-components/basic-alert/index.d.ts +53 -0
  8. package/basic-components/basic-alert/index.js +189 -0
  9. package/basic-components/basic-alert/register.js +3 -0
  10. package/basic-components/basic-carousel/README.md +108 -0
  11. package/basic-components/basic-carousel/index.d.ts +73 -0
  12. package/basic-components/basic-carousel/index.js +255 -0
  13. package/basic-components/basic-carousel/register.js +3 -0
  14. package/basic-components/basic-dialog/README.md +57 -0
  15. package/basic-components/basic-popover/README.md +56 -0
  16. package/basic-components/basic-summary-table/README.md +93 -0
  17. package/{components → basic-components}/basic-summary-table/index.js +188 -42
  18. package/basic-components/basic-table/README.md +89 -0
  19. package/{components → basic-components}/basic-table/index.js +203 -145
  20. package/basic-components/basic-tabs/README.md +63 -0
  21. package/basic-components/basic-tabs/register.d.ts +1 -0
  22. package/basic-components/basic-toast/README.md +62 -0
  23. package/basic-components/basic-toast/index.d.ts +68 -0
  24. package/basic-components/basic-toast/index.js +690 -0
  25. package/basic-components/basic-toast/register.d.ts +1 -0
  26. package/basic-components/basic-toast/register.js +3 -0
  27. package/basic-components/basic-toc/README.md +43 -0
  28. package/basic-components/basic-toc/register.d.ts +1 -0
  29. package/basic-styling/components/basic-accordion.css +99 -0
  30. package/basic-styling/components/basic-alert.css +27 -0
  31. package/basic-styling/components/basic-carousel.css +183 -0
  32. package/basic-styling/components/basic-dialog.css +41 -0
  33. package/basic-styling/components/basic-popover.css +52 -0
  34. package/basic-styling/components/basic-summary-table.css +98 -0
  35. package/basic-styling/components/basic-table.css +66 -0
  36. package/basic-styling/components/basic-tabs.css +61 -0
  37. package/basic-styling/components/basic-toast.css +102 -0
  38. package/basic-styling/components/basic-toc.css +30 -0
  39. package/basic-styling/components.css +11 -0
  40. package/basic-styling/forms.css +55 -0
  41. package/basic-styling/global.css +62 -0
  42. package/basic-styling/index.css +2 -0
  43. package/basic-styling/interaction.css +90 -0
  44. package/basic-styling/tokens/base.css +19 -0
  45. package/basic-styling/tokens/palette.css +229 -0
  46. package/basic-styling/tokens/palette.tokens.json +1787 -0
  47. package/index.d.ts +10 -7
  48. package/index.js +10 -7
  49. package/package.json +61 -76
  50. package/components/basic-accordion/index.js +0 -387
  51. package/readme.mdx +0 -6
  52. /package/{components → basic-components}/basic-accordion/register.d.ts +0 -0
  53. /package/{components → basic-components}/basic-accordion/register.js +0 -0
  54. /package/{components/basic-dialog → basic-components/basic-alert}/register.d.ts +0 -0
  55. /package/{components/basic-popover → basic-components/basic-carousel}/register.d.ts +0 -0
  56. /package/{components → basic-components}/basic-dialog/index.d.ts +0 -0
  57. /package/{components → basic-components}/basic-dialog/index.js +0 -0
  58. /package/{components/basic-summary-table → basic-components/basic-dialog}/register.d.ts +0 -0
  59. /package/{components → basic-components}/basic-dialog/register.js +0 -0
  60. /package/{components → basic-components}/basic-popover/index.d.ts +0 -0
  61. /package/{components → basic-components}/basic-popover/index.js +0 -0
  62. /package/{components/basic-table → basic-components/basic-popover}/register.d.ts +0 -0
  63. /package/{components → basic-components}/basic-popover/register.js +0 -0
  64. /package/{components → basic-components}/basic-summary-table/index.d.ts +0 -0
  65. /package/{components/basic-tabs → basic-components/basic-summary-table}/register.d.ts +0 -0
  66. /package/{components → basic-components}/basic-summary-table/register.js +0 -0
  67. /package/{components → basic-components}/basic-table/index.d.ts +0 -0
  68. /package/{components/basic-toc → basic-components/basic-table}/register.d.ts +0 -0
  69. /package/{components → basic-components}/basic-table/register.js +0 -0
  70. /package/{components → basic-components}/basic-tabs/index.d.ts +0 -0
  71. /package/{components → basic-components}/basic-tabs/index.js +0 -0
  72. /package/{components → basic-components}/basic-tabs/register.js +0 -0
  73. /package/{components → basic-components}/basic-toc/index.d.ts +0 -0
  74. /package/{components → basic-components}/basic-toc/index.js +0 -0
  75. /package/{components → basic-components}/basic-toc/register.js +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ole Jorgen Bakken
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # `@lmfaole/basics`
2
2
 
3
- Simple unstyled custom elements and DOM helpers.
3
+ Unstyled custom elements for common UI patterns, with an optional starter CSS layer.
4
4
 
5
5
  ## Install
6
6
 
@@ -8,116 +8,18 @@ Simple unstyled custom elements and DOM helpers.
8
8
  pnpm add @lmfaole/basics
9
9
  ```
10
10
 
11
- ## Storybook
12
-
13
- ```sh
14
- pnpm storybook
15
- ```
16
-
17
- ```sh
18
- pnpm build-storybook
19
- ```
20
-
21
- ```sh
22
- pnpm test:storybook
23
- ```
24
-
25
- ```sh
26
- pnpm test:storybook:coverage
27
- ```
28
-
29
- Autodocs is enabled globally for the package stories, and the Docs page includes Storybook's built-in Code panel for rendered examples.
30
- Storybook Test coverage is enabled through the Vitest addon. In the Storybook UI, turn coverage on in the testing panel to see the summary and open the full report at `/coverage/index.html`. From the CLI, `test:storybook:coverage` writes reports to `coverage/storybook/`.
31
-
32
- The Visual Tests panel is provided by `@chromatic-com/storybook`. To run cloud visual checks, connect the addon to a Chromatic project from the Storybook UI.
33
-
34
- GitHub Actions now splits Storybook automation by purpose:
35
-
36
- - `CI` runs the browser-backed Storybook test suite on pull requests and pushes to `main`.
37
- - `Storybook Preview` builds Storybook for pull requests and uploads `storybook-static` as an artifact.
38
- - `Storybook Pages` deploys the built Storybook from `main` to GitHub Pages.
39
- - `Chromatic` publishes Storybook builds on branch pushes when the `CHROMATIC_PROJECT_TOKEN` repository secret is configured.
40
-
41
- ## Changesets
42
-
43
- For changes that affect the published package, run:
44
-
45
- ```sh
46
- pnpm changeset
47
- ```
11
+ ## Quick Start
48
12
 
49
- Commit the generated Markdown file under `.changeset/` with the rest of your work. If a change is repo-only and does not affect the published package, no changeset file is needed.
50
-
51
- ## Releasing
52
-
53
- Merging changesets into `main` causes the `Release` workflow to open or update a `chore: release` pull request. Merging that release pull request will:
54
-
55
- 1. run `pnpm release`
56
- 2. publish the package to npm with trusted publishing from GitHub Actions
57
- 3. create the matching `vX.Y.Z` git tag and GitHub Release
58
- 4. attach the packed tarball to the GitHub Release
59
-
60
- Trusted publishing must be configured on npm for `@lmfaole/basics` against the GitHub Actions workflow file `.github/workflows/release.yml` in the `lmfaole/basics` repository. No `NPM_TOKEN` repository secret is needed once trusted publishing is active.
61
-
62
- If a release needs to be retried after the workflow changes land, use the `Release` workflow's `publish_current_version` manual input to publish the current `package.json` version from `main` when it is still unpublished.
63
-
64
- ## Commits
65
-
66
- Use Conventional Commits for commit messages and pull request titles. The GitHub workflow accepts `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, and `test`, with an optional scope such as `feat(tabs): add keyboard support`.
67
-
68
- ## Basic Popover
69
-
70
- ```html
71
- <basic-popover data-label="Filtre" data-anchor-trigger data-position-area="bottom">
72
- <button type="button" data-popover-open>Toggle popover</button>
73
-
74
- <section data-popover-panel>
75
- <h2 data-popover-title>Filtre</h2>
76
- <p>Popover body.</p>
77
- <button type="button" data-popover-close>Close</button>
78
- </section>
79
- </basic-popover>
80
-
81
- <script type="module">
82
- import "@lmfaole/basics/components/basic-popover/register";
83
- </script>
84
- ```
85
-
86
- The element upgrades popover trigger-and-panel markup into an accessible non-modal overlay without adding any styles of its own.
87
-
88
- ### Attributes
89
-
90
- - `data-label`: fallback accessible name when the popover has no `aria-label`, `aria-labelledby`, or `[data-popover-title]`.
91
- - `data-anchor-trigger`: uses the opener as the popover's implicit anchor so consumer CSS can position the panel relative to the trigger.
92
- - `data-position-area`: sets the CSS anchor-positioning area used when `data-anchor-trigger` is enabled. Defaults to `bottom`.
93
- - `data-position-try-fallbacks`: optional comma-separated fallback list used when the default anchored placement would overflow. By default the component derives a sensible sequence from `data-position-area`.
94
-
95
- ### Behavior
96
-
97
- - Uses the native Popover API in auto mode for outside-click and `Esc` dismissal.
98
- - Syncs `aria-expanded`, `aria-controls`, and `data-open` between the trigger and panel.
99
- - Restores focus to the opener when dismissal should return to it, while preserving focus on an outside control the user explicitly clicked.
100
- - When `data-anchor-trigger` is set, opening the popover passes the trigger as the Popover API `source`, establishes the panel's implicit anchor, and applies the configured `position-area`.
101
- - When `data-anchor-trigger` is set and `data-position-try-fallbacks` is not provided, the component derives a fallback sequence from the default placement:
102
- `bottom` or `top` start with `flip-block`, while `left` or `right` start with `flip-inline`.
103
- - `[data-popover-close]` controls can dismiss the panel from inside the overlay.
104
-
105
- ### Markup Contract
106
-
107
- - Provide one descendant `[data-popover-panel]`.
108
- - Use `[data-popover-open]` on buttons that should toggle the panel.
109
- - Use `[data-popover-title]` for the popover heading when you want it to become the accessible name.
110
- - If you set `data-anchor-trigger`, you can tune the default anchored placement with `data-position-area` and optionally override its overflow fallbacks with `data-position-try-fallbacks`.
111
- - Keep layout and styling outside the package; the component only manages semantics and open or close behavior.
112
-
113
- ## Basic Dialog
13
+ 1. Import the register module for the component you want to use.
14
+ 2. Render the expected HTML markup.
15
+ 3. Optionally import the starter styles.
114
16
 
115
17
  ```html
116
- <basic-dialog data-label="Bekreft handling" data-backdrop-close>
18
+ <basic-dialog data-label="Confirm action">
117
19
  <button type="button" data-dialog-open>Open dialog</button>
118
20
 
119
21
  <dialog data-dialog-panel>
120
- <h2 data-dialog-title>Bekreft handling</h2>
22
+ <h2 data-dialog-title>Confirm action</h2>
121
23
  <p>Dialog body.</p>
122
24
  <button type="button" data-dialog-close>Cancel</button>
123
25
  <button type="button" data-dialog-close data-dialog-close-value="confirmed">
@@ -127,285 +29,111 @@ The element upgrades popover trigger-and-panel markup into an accessible non-mod
127
29
  </basic-dialog>
128
30
 
129
31
  <script type="module">
130
- import "@lmfaole/basics/components/basic-dialog/register";
32
+ import "@lmfaole/basics/basic-components/basic-dialog/register";
131
33
  </script>
132
34
  ```
133
35
 
134
- The element upgrades native `<dialog>` markup into an accessible modal flow without adding any styles of its own.
135
-
136
- ### Attributes
36
+ Import register modules once in your app entry point. They define the custom element and leave styling to your application unless you also opt into `basic-styling`.
137
37
 
138
- - `data-label`: fallback accessible name when the dialog has no `aria-label`, `aria-labelledby`, or `[data-dialog-title]`.
139
- - `data-backdrop-close`: allows clicks on the dialog backdrop to close the modal.
38
+ ## Component Guides
140
39
 
141
- ### Behavior
40
+ Each component now has its own colocated README with markup, attributes, behavior, and usage notes:
142
41
 
143
- - Uses the native dialog element's modal behavior via `showModal()`.
144
- - Restores focus to the element that opened the dialog when the modal closes.
145
- - `Esc` closes the modal through the platform's dialog behavior.
146
- - `[data-dialog-close]` controls can optionally set `data-dialog-close-value` to pass a close value.
42
+ - [`basic-alert`](./basic-components/basic-alert/README.md): inline live-region alerts
43
+ - [`basic-accordion`](./basic-components/basic-accordion/README.md): single-open or multi-open disclosure sections
44
+ - [`basic-carousel`](./basic-components/basic-carousel/README.md): scroll-snap carousels with native CSS controls where supported
45
+ - [`basic-dialog`](./basic-components/basic-dialog/README.md): modal dialogs built on native `<dialog>`
46
+ - [`basic-popover`](./basic-components/basic-popover/README.md): non-modal overlays using the Popover API
47
+ - [`basic-summary-table`](./basic-components/basic-summary-table/README.md): tables with generated totals in `<tfoot>`
48
+ - [`basic-table`](./basic-components/basic-table/README.md): accessible table naming and header relationships
49
+ - [`basic-tabs`](./basic-components/basic-tabs/README.md): accessible tablists and panels
50
+ - [`basic-toast`](./basic-components/basic-toast/README.md): transient toast notifications
51
+ - [`basic-toc`](./basic-components/basic-toc/README.md): generated table-of-contents navigation
147
52
 
148
- ### Markup Contract
53
+ ## Optional Styling
149
54
 
150
- - Provide one descendant `<dialog data-dialog-panel>`.
151
- - Use `[data-dialog-open]` on buttons that should open the modal.
152
- - Use `[data-dialog-title]` for the dialog heading when you want it to become the accessible name.
153
- - Keep layout and styling outside the package; the component only manages semantics and open or close behavior.
55
+ The components are unstyled by default. To opt into the starter CSS:
154
56
 
155
- ## Basic Accordion
156
-
157
- ```html
158
- <basic-accordion>
159
- <h3><button type="button" data-accordion-trigger>Oversikt</button></h3>
160
- <section data-accordion-panel>
161
- <p>Viser en kort oppsummering.</p>
162
- </section>
163
-
164
- <h3><button type="button" data-accordion-trigger>Implementasjon</button></h3>
165
- <section data-accordion-panel>
166
- <p>Viser implementasjonsdetaljer.</p>
167
- </section>
168
- </basic-accordion>
169
-
170
- <script type="module">
171
- import "@lmfaole/basics/components/basic-accordion/register";
172
- </script>
57
+ ```css
58
+ @import "@lmfaole/basics/basic-styling";
173
59
  ```
174
60
 
175
- The element upgrades existing trigger-and-panel markup into an accessible accordion without adding any styles of its own.
176
-
177
- ### Attributes
178
-
179
- - `data-multiple`: allows multiple panels to stay open at the same time.
180
- - `data-collapsible`: allows the last open panel in single mode to close.
181
-
182
- ### Behavior
183
-
184
- - Missing trigger and panel ids are generated automatically.
185
- - `aria-expanded`, `aria-controls`, `aria-labelledby`, `hidden`, and `data-open` stay in sync with the current state.
186
- - `ArrowUp`, `ArrowDown`, `Home`, and `End` move focus between enabled triggers.
187
- - `Enter` and `Space` toggle the focused item.
188
- - Disabled triggers are skipped during keyboard navigation.
189
-
190
- ### Markup Contract
191
-
192
- - Provide matching counts of `[data-accordion-trigger]` and `[data-accordion-panel]` descendants in the same order.
193
- - Prefer `<button>` elements for triggers, usually inside your own heading elements.
194
- - Keep layout and styling outside the package; the component only manages semantics, state, and keyboard behavior.
195
-
196
- ## Basic Tabs
61
+ Or import the global layer and component layer separately:
197
62
 
198
- ```html
199
- <basic-tabs data-label="Eksempelkode">
200
- <div data-tabs-list>
201
- <button type="button" data-tab>Oversikt</button>
202
- <button type="button" data-tab>Implementasjon</button>
203
- <button type="button" data-tab>Tilgjengelighet</button>
204
- </div>
205
-
206
- <section data-tab-panel>
207
- <p>Viser en kort oppsummering.</p>
208
- </section>
209
- <section data-tab-panel>
210
- <p>Viser implementasjonsdetaljer.</p>
211
- </section>
212
- <section data-tab-panel>
213
- <p>Viser tilgjengelighetsnotater.</p>
214
- </section>
215
- </basic-tabs>
216
-
217
- <script type="module">
218
- import "@lmfaole/basics/components/basic-tabs/register";
219
- </script>
63
+ ```css
64
+ @import "@lmfaole/basics/basic-styling/global.css";
65
+ @import "@lmfaole/basics/basic-styling/components.css";
220
66
  ```
221
67
 
222
- The element upgrades existing markup into an accessible tab interface without adding any styles of its own.
223
-
224
- ### Attributes
225
-
226
- - `data-label`: sets the generated tablist's accessible name when the tablist does not already have `aria-label` or `aria-labelledby`. Defaults to `Faner`.
227
- - `data-activation`: chooses whether arrow-key focus changes also activate the panel. Supported values are `automatic` and `manual`.
228
- - `data-selected-index`: sets the initially selected tab by zero-based index. Defaults to the first enabled tab.
68
+ You can also import individual files from:
229
69
 
230
- ### Behavior
70
+ - `@lmfaole/basics/basic-styling/forms.css`
71
+ - `@lmfaole/basics/basic-styling/tokens/*`
72
+ - `@lmfaole/basics/basic-styling/components/basic-*.css`
231
73
 
232
- - Missing tab and panel ids are generated automatically.
233
- - `aria-selected`, `aria-controls`, `aria-labelledby`, `hidden`, and `data-selected` stay in sync with the active tab.
234
- - Click, `ArrowLeft`, `ArrowRight`, `Home`, and `End` move between tabs.
235
- - Disabled tabs are skipped during keyboard navigation.
236
- - In `manual` mode, arrow keys move focus and `Enter` or `Space` activates the focused tab.
74
+ The starter styling is intentionally minimal. It provides tokens, spacing, and baseline component styles without taking over your design system.
237
75
 
238
- ### Markup Contract
76
+ ### Selection Panels
239
77
 
240
- - Provide one descendant element with `data-tabs-list` to hold the interactive tab controls.
241
- - Provide matching counts of `[data-tab]` and `[data-tab-panel]` descendants in the same order.
242
- - Prefer `<button>` elements for tabs so click and keyboard activation stay native.
243
- - Keep layout and styling outside the package; the component only manages semantics, state, and keyboard behavior.
244
-
245
- ## Basic Table
78
+ The form layer can render a native checkbox or radio like a selectable panel by adding `data-panel` to the input.
246
79
 
247
80
  ```html
248
- <basic-table
249
- data-caption="Bemanning per sprint"
250
- data-description="Viser team, lokasjon og ledig kapasitet per sprint."
251
- data-row-headers
252
- data-row-header-column="2"
253
- >
254
- <table>
255
- <thead>
256
- <tr>
257
- <th>Statuskode</th>
258
- <th>Team</th>
259
- <th>Lokasjon</th>
260
- <th>Ledige timer</th>
261
- </tr>
262
- </thead>
263
- <tbody>
264
- <tr>
265
- <td>A1</td>
266
- <td>Plattform</td>
267
- <td>Oslo</td>
268
- <td>18</td>
269
- </tr>
270
- <tr>
271
- <td>B4</td>
272
- <td>Designsystem</td>
273
- <td>Trondheim</td>
274
- <td>10</td>
275
- </tr>
276
- </tbody>
277
- </table>
278
- </basic-table>
279
-
280
- <script type="module">
281
- import "@lmfaole/basics/components/basic-table/register";
282
- </script>
81
+ <label>
82
+ <input type="checkbox" name="days" value="day-1" data-panel checked />
83
+ <span>
84
+ <strong>Day 1: Product systems</strong>
85
+ <span>Keynotes, leadership sessions, and case studies.</span>
86
+ </span>
87
+ </label>
283
88
  ```
284
89
 
285
- The element upgrades a regular table with stronger accessible naming and header associations without imposing any styles.
90
+ Use the pattern like this:
286
91
 
287
- ### Attributes
92
+ - Import `@lmfaole/basics/basic-styling/forms.css`, `global.css`, or the full `basic-styling` entry point.
93
+ - Put `data-panel` on the native checkbox or radio, not on the label.
94
+ - Keep the control as a direct child of the label.
95
+ - Place the visible body copy after the input in a sibling `span` or `div`.
96
+ - Use native `fieldset` and `legend` when the choices belong to one group.
97
+ - Keep shared `name` values on radio groups so the browser preserves single-select behavior.
288
98
 
289
- - `data-caption`: generates a visible `<caption>` when the wrapped table does not already define one.
290
- - `data-column-headers`: promotes the first row to column headers when the author provides a plain table without a header row.
291
- - `data-description`: generates a hidden description and connects it with `aria-describedby`.
292
- - `data-label`: sets a fallback accessible name when the table has no caption, `aria-label`, or `aria-labelledby`. Defaults to `Tabell`.
293
- - `data-row-header-column`: sets which one-based body column should become the generated row header. Defaults to `1`.
294
- - `data-row-headers`: enables generated row headers in body rows. If `data-row-header-column` is present, row-header mode is enabled automatically.
99
+ This is still a native checkbox or radio. Keyboard behavior, form submission, validation, checked state, and radio-group semantics all stay browser-driven.
100
+ See Storybook `Native Elements/Forms` for live examples of the same markup.
295
101
 
296
- ### Behavior
102
+ ## Package Entry Points
297
103
 
298
- - Preserves author-provided captions and only generates one when needed.
299
- - Can generate hidden helper text for extra context without requiring a separate authored description element.
300
- - Can promote a plain first row to column headers when consumers start from simple body-only markup.
301
- - Infers common `scope` values for header cells and assigns missing header ids.
302
- - Populates each data cell's `headers` attribute from the matching row and column headers.
303
- - Re-runs automatically when the wrapped table changes.
104
+ - Register a custom element: `@lmfaole/basics/basic-components/<component>/register`
105
+ - Import a component module directly: `@lmfaole/basics/basic-components/<component>`
106
+ - Root module exports the component classes and helpers from `@lmfaole/basics`
107
+ - Legacy compatibility aliases remain available under `@lmfaole/basics/components/<component>`
304
108
 
305
- ### Markup Contract
109
+ ## Browser Support
306
110
 
307
- - Provide one descendant `<table>` inside the custom element.
308
- - Use real table sections and header cells where possible; the component strengthens semantics but does not replace the HTML table model.
309
- - Add `data-row-headers` when one body column identifies each row, and use `data-row-header-column` when that column is not the first one.
310
- - Add `data-column-headers` when you want the component to promote a plain first row instead of authoring a header row yourself.
311
- - Keep layout and styling outside the package; the component only manages semantics and accessibility metadata.
111
+ The package targets modern evergreen browsers. The live widgets below render in Storybook's Readme page via the official `<baseline-status>` custom element, and each line also links to the underlying feature page for plain Markdown viewers.
312
112
 
313
- ## Basic Summary Table
113
+ As of March 29, 2026, the biggest compatibility gaps are the shared style-query layer in Firefox and the native carousel marker/button controls outside Chromium-based browsers.
314
114
 
315
- ```html
316
- <basic-summary-table
317
- data-caption="Prosjektsammendrag"
318
- data-description="Viser timer og total kostnad for prosjektets leveranser."
319
- data-row-headers
320
- data-summary-columns="2,4"
321
- data-total-label="Totalt"
322
- >
323
- <table>
324
- <thead>
325
- <tr>
326
- <th>Post</th>
327
- <th>Timer</th>
328
- <th>Sats</th>
329
- <th>Kostnad</th>
330
- </tr>
331
- </thead>
332
- <tbody>
333
- <tr>
334
- <td>Analyse</td>
335
- <td>8</td>
336
- <td>100</td>
337
- <td>800</td>
338
- </tr>
339
- <tr>
340
- <td>Implementasjon</td>
341
- <td>12</td>
342
- <td>120</td>
343
- <td>1440</td>
344
- </tr>
345
- </tbody>
346
- </table>
347
- </basic-summary-table>
115
+ - Core custom elements (`basic-alert`, `basic-accordion`, `basic-carousel`, `basic-summary-table`, `basic-table`, `basic-tabs`, `basic-toc`, `basic-toast`): <baseline-status featureId="autonomous-custom-elements"></baseline-status> ([Autonomous custom elements](https://web-platform-dx.github.io/web-features-explorer/features/autonomous-custom-elements/))
116
+ - `basic-dialog` modal behavior: <baseline-status featureId="dialog"></baseline-status> ([`<dialog>`](https://web-platform-dx.github.io/web-features-explorer/features/dialog/))
117
+ - `basic-popover` overlays and `basic-toast` top-layer placement: <baseline-status featureId="popover"></baseline-status> ([Popover](https://web-platform-dx.github.io/web-features-explorer/features/popover/))
118
+ - `basic-carousel` scroll-snap foundation: <baseline-status featureId="scroll-snap"></baseline-status> ([Scroll snap](https://web-platform-dx.github.io/web-features-explorer/features/scroll-snap/))
119
+ - `basic-carousel` native marker and arrow controls: <baseline-status featureId="scroll-markers"></baseline-status> <baseline-status featureId="scroll-buttons"></baseline-status> ([Scroll markers](https://web-platform-dx.github.io/web-features-explorer/features/scroll-markers/), [`::scroll-button`](https://web-platform-dx.github.io/web-features-explorer/features/scroll-buttons/))
120
+ - Starter CSS color and selector baseline: <baseline-status featureId="nesting"></baseline-status> <baseline-status featureId="has"></baseline-status> <baseline-status featureId="light-dark"></baseline-status> <baseline-status featureId="oklab"></baseline-status> ([Nesting](https://web-platform-dx.github.io/web-features-explorer/features/nesting/), [`:has()`](https://web-platform-dx.github.io/web-features-explorer/features/has/), [`light-dark()`](https://web-platform-dx.github.io/web-features-explorer/features/light-dark/), [Oklab and OkLCh](https://web-platform-dx.github.io/web-features-explorer/features/oklab/))
121
+ - Shared interaction state layer and other style-query-driven refinements: <baseline-status featureId="container-style-queries"></baseline-status> ([Container style queries](https://web-platform-dx.github.io/web-features-explorer/features/container-style-queries/))
348
122
 
349
- <script type="module">
350
- import "@lmfaole/basics/components/basic-summary-table/register";
351
- </script>
352
- ```
353
-
354
- The element upgrades a calculation-heavy table with an automatically maintained totals row in `<tfoot>`.
355
-
356
- ### Attributes
357
-
358
- - `data-caption`: generates a visible `<caption>` when the wrapped table does not already define one.
359
- - `data-description`: generates hidden helper text and connects it with `aria-describedby`.
360
- - `data-label`: sets a fallback accessible name when the table has no caption, `aria-label`, or `aria-labelledby`. Defaults to `Tabell`.
361
- - `data-row-headers`: enables generated row headers in body rows.
362
- - `data-row-header-column`: sets which one-based body column should become the generated row header. Defaults to `1`.
363
- - `data-summary-columns`: chooses which one-based columns should be totalled in the generated footer row. If omitted, numeric body columns are inferred automatically.
364
- - `data-total-label`: sets the footer row label. Defaults to `Totalt`.
365
- - `data-locale`: passes a locale through to `Intl.NumberFormat` for generated footer totals.
366
-
367
- ### Behavior
368
-
369
- - Inherits caption, description, row-header, and `headers` association behavior from `basic-table`.
370
- - Parses numbers from cell text and supports raw calculation values through `data-value` on individual body cells.
371
- - Generates or updates a totals row in `<tfoot>` without requiring consumers to author the footer manually.
372
- - Recalculates totals automatically when body rows or `data-value` attributes change.
373
-
374
- ### Markup Contract
375
-
376
- - Provide one descendant `<table>` with line items in `<tbody>`.
377
- - Prefer a label column such as `Post` or `Kategori` and enable `data-row-headers` so each line item remains easy to navigate.
378
- - Use `data-value` on cells when the displayed text is formatted differently from the numeric value you want summed.
379
- - Keep layout and styling outside the package; the component only manages semantics, totals, and footer structure.
380
-
381
- ## Basic Toc
382
-
383
- ```html
384
- <basic-toc data-title="Innhold">
385
- <nav aria-label="Innhold" data-page-toc-nav></nav>
386
- </basic-toc>
123
+ ## Storybook
387
124
 
388
- <script type="module">
389
- import "@lmfaole/basics/components/basic-toc/register";
390
- </script>
125
+ ```sh
126
+ pnpm storybook
391
127
  ```
392
128
 
393
- The element reads headings from the nearest `<main>` and updates automatically when that content changes.
394
-
395
- ### Attributes
396
-
397
- - `data-title`: sets the generated nav's accessible label. Defaults to `Innhold`.
398
- - `data-heading-selector`: limits which headings are indexed. Defaults to `h1, h2, h3, h4, h5, h6`.
399
-
400
- ### Behavior
129
+ ```sh
130
+ pnpm build-storybook
131
+ ```
401
132
 
402
- - Missing heading ids are generated automatically.
403
- - Duplicate headings receive unique fragment ids.
404
- - Hidden headings are ignored.
405
- - The outline is rebuilt when matching headings are added or changed.
133
+ Storybook now focuses on package documentation pages such as the readme, changelog, contributing guide, security policy, and palette tokens.
406
134
 
407
- ### Markup Contract
135
+ ## More Docs
408
136
 
409
- - Render the element inside the same `<main>` that contains the content it should index.
410
- - Provide a descendant element with `data-page-toc-nav` for the generated links.
411
- - Keep layout and styling outside the package; the component only manages structure and link generation.
137
+ - [CHANGELOG.md](./CHANGELOG.md)
138
+ - [CONTRIBUTING.md](./CONTRIBUTING.md)
139
+ - [SECURITY.md](./SECURITY.md)
@@ -0,0 +1,53 @@
1
+ # `basic-accordion`
2
+
3
+ Coordinates direct child `<details>` items into an accordion.
4
+
5
+ ## Register
6
+
7
+ ```js
8
+ import "@lmfaole/basics/basic-components/basic-accordion/register";
9
+ ```
10
+
11
+ ## Example
12
+
13
+ ```html
14
+ <basic-accordion>
15
+ <details open>
16
+ <summary>Oversikt</summary>
17
+ <p>Viser en kort oppsummering.</p>
18
+ </details>
19
+
20
+ <details>
21
+ <summary>Implementasjon</summary>
22
+ <p>Viser implementasjonsdetaljer.</p>
23
+ </details>
24
+ </basic-accordion>
25
+ ```
26
+
27
+ ## Props
28
+
29
+ | Prop | Description | Type | Default | Options |
30
+ | --- | --- | --- | --- | --- |
31
+ | `data-multiple` | Allows more than one accordion item to stay open at the same time. | boolean attribute | off | `present`, `omitted` |
32
+ | `data-collapsible` | Allows the last open item in single-open mode to close. | boolean attribute | off | `present`, `omitted` |
33
+
34
+ ## Item Hooks
35
+
36
+ | Hook | Description | Type | Default | Options |
37
+ | --- | --- | --- | --- | --- |
38
+ | `open` on a child `<details>` | Sets an item's initial expanded state before the accordion normalizes it. | boolean attribute | closed | `present`, `omitted` |
39
+ | `data-disabled` on a child `<details>` | Removes the item from toggle behavior and arrow-key navigation. | boolean attribute | off | `present`, `omitted` |
40
+
41
+ ## Behavior
42
+
43
+ - Preserves native `details` and `summary` semantics
44
+ - Keeps `data-open` in sync with the normalized open state
45
+ - Supports `ArrowUp`, `ArrowDown`, `Home`, and `End` between enabled summaries
46
+ - In single-open mode, keeps one enabled item open unless `data-collapsible` is set
47
+
48
+ ## Markup Contract
49
+
50
+ - Provide direct child `<details>` items, each with a first-child `<summary>`
51
+ - Add `open` to any item that should start expanded
52
+ - Add `data-disabled` to a `<details>` item when it should be skipped by arrow-key navigation and blocked from toggling
53
+ - Keep layout and styling outside the package
@@ -21,7 +21,7 @@ export function getInitialOpenAccordionIndexes(
21
21
  ): number[];
22
22
 
23
23
  /**
24
- * Returns the next enabled accordion trigger index, wrapping around the list
24
+ * Returns the next enabled accordion item index, wrapping around the list
25
25
  * when needed.
26
26
  */
27
27
  export function findNextEnabledAccordionIndex(
@@ -31,12 +31,12 @@ export function findNextEnabledAccordionIndex(
31
31
  ): number;
32
32
 
33
33
  /**
34
- * Custom element that upgrades existing trigger-and-panel markup into an
35
- * accessible accordion interface.
34
+ * Custom element that coordinates direct child `details` items into an
35
+ * accordion interface.
36
36
  *
37
37
  * Attributes:
38
- * - `data-multiple`: allows multiple panels to stay open
39
- * - `data-collapsible`: allows the last open panel in single mode to close
38
+ * - `data-multiple`: allows multiple items to stay open
39
+ * - `data-collapsible`: allows the last open item in single mode to close
40
40
  */
41
41
  export class AccordionElement extends HTMLElement {
42
42
  static observedAttributes: string[];