@f-ewald/components 1.2.1 → 1.4.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 (62) hide show
  1. package/README.md +16 -2
  2. package/custom-elements.json +1071 -79
  3. package/dist/action-bar.d.ts +24 -0
  4. package/dist/action-bar.d.ts.map +1 -0
  5. package/dist/action-bar.js +67 -0
  6. package/dist/action-bar.js.map +1 -0
  7. package/dist/app-shell.d.ts +86 -0
  8. package/dist/app-shell.d.ts.map +1 -0
  9. package/dist/app-shell.js +460 -0
  10. package/dist/app-shell.js.map +1 -0
  11. package/dist/app-sidebar.d.ts +44 -0
  12. package/dist/app-sidebar.d.ts.map +1 -0
  13. package/dist/app-sidebar.js +211 -0
  14. package/dist/app-sidebar.js.map +1 -0
  15. package/dist/content-divider.d.ts +23 -0
  16. package/dist/content-divider.d.ts.map +1 -0
  17. package/dist/content-divider.js +86 -0
  18. package/dist/content-divider.js.map +1 -0
  19. package/dist/form-actions.d.ts +27 -0
  20. package/dist/form-actions.d.ts.map +1 -0
  21. package/dist/form-actions.js +65 -0
  22. package/dist/form-actions.js.map +1 -0
  23. package/dist/index.d.ts +9 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +9 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/mcp-server.js +82 -5
  28. package/dist/mcp-server.js.map +1 -1
  29. package/dist/page-header.d.ts +27 -0
  30. package/dist/page-header.d.ts.map +1 -0
  31. package/dist/page-header.js +106 -0
  32. package/dist/page-header.js.map +1 -0
  33. package/dist/pagination-nav.d.ts +34 -0
  34. package/dist/pagination-nav.d.ts.map +1 -0
  35. package/dist/pagination-nav.js +144 -0
  36. package/dist/pagination-nav.js.map +1 -0
  37. package/dist/timeline-container.d.ts +22 -0
  38. package/dist/timeline-container.d.ts.map +1 -0
  39. package/dist/timeline-container.js +42 -0
  40. package/dist/timeline-container.js.map +1 -0
  41. package/dist/timeline-entry.d.ts +31 -0
  42. package/dist/timeline-entry.d.ts.map +1 -0
  43. package/dist/timeline-entry.js +170 -0
  44. package/dist/timeline-entry.js.map +1 -0
  45. package/docs/action-bar.md +41 -0
  46. package/docs/app-shell.md +85 -0
  47. package/docs/app-sidebar.md +69 -0
  48. package/docs/content-divider.md +47 -0
  49. package/docs/design-language.md +74 -1
  50. package/docs/form-actions.md +43 -0
  51. package/docs/layouts/detail-only.md +52 -0
  52. package/docs/layouts/form-page.md +52 -0
  53. package/docs/layouts/list-detail.md +52 -0
  54. package/docs/layouts/list-only.md +50 -0
  55. package/docs/layouts/record-detail.md +88 -0
  56. package/docs/mcp-evaluation.md +21 -0
  57. package/docs/page-header.md +47 -0
  58. package/docs/pagination-nav.md +54 -0
  59. package/docs/timeline-container.md +44 -0
  60. package/docs/timeline-entry.md +52 -0
  61. package/llms.txt +251 -0
  62. package/package.json +1 -1
package/llms.txt CHANGED
@@ -16,6 +16,31 @@ render correctly with zero external CSS. Override any `--ui-*` property on
16
16
  `:root` (or an ancestor) to retheme, or import the optional
17
17
  `@f-ewald/components/tokens.css` stylesheet as a starting point.
18
18
 
19
+ ## <action-bar>
20
+
21
+ Toolbar that sits directly above a list or table: a left cluster for
22
+ search and filters and a right cluster for record actions (create, delete,
23
+ bulk actions). It's a presentational layout container only — drop any
24
+ controls (`autocomplete-input`, `multi-select`, `ui-button`, …) into the
25
+ `start` and `end` slots; the bar owns none of their behavior and adds no
26
+ search field of its own. The two clusters wrap onto separate rows when the
27
+ bar is too narrow.
28
+
29
+ Import: `import "@f-ewald/components/action-bar.js";`
30
+
31
+ Properties: none
32
+ Events: none
33
+ CSS custom properties: none
34
+
35
+ Example:
36
+ ```html
37
+ <action-bar>
38
+ <autocomplete-input slot="start" placeholder="Search…"></autocomplete-input>
39
+ <ui-button slot="end" variant="secondary">Delete</ui-button>
40
+ <ui-button slot="end" variant="primary">Create</ui-button>
41
+ </action-bar>
42
+ ```
43
+
19
44
  ## <address-autocomplete>
20
45
 
21
46
  Form-associated text input with a suggestion dropdown. Works as a
@@ -61,6 +86,89 @@ Example:
61
86
  <animate-confetti duration="6000"></animate-confetti>
62
87
  ```
63
88
 
89
+ ## <app-shell>
90
+
91
+ The dashboard page shell: a slot-based CSS-grid backbone that arranges a
92
+ full-height sidebar, a top bar, the main content, an optional right-hand
93
+ detail column, and an optional footer. It owns the responsive behavior so
94
+ consumers don't re-implement it — above the shared 48rem breakpoint the
95
+ sidebar collapses to an icon rail and the detail region is an inline column;
96
+ at or below it the sidebar becomes an off-canvas drawer and the detail region
97
+ an overlay, both dismissed by a scrim or Escape.
98
+
99
+ Widths are tunable per instance via `--component-sidebar-width` (16rem),
100
+ `--component-sidebar-rail-width` (3.5rem), and `--component-topbar-height`
101
+ (3rem); the detail column reuses the 20rem/25rem panel widths. The main
102
+ content area is white by default — override it with
103
+ `--component-main-background`. Give the shell a height (e.g. `height: 100vh`)
104
+ so the sidebar and main can size and scroll.
105
+
106
+ The built-in top-bar button toggles the sidebar, and so does pressing `[`
107
+ anywhere on the page (ignored while typing in a text field or with a
108
+ modifier held). Hovering or keyboard-focusing the toggle reveals a tooltip
109
+ naming the action and its `[` shortcut — the shortcut is not shown as
110
+ permanent chrome.
111
+
112
+ Import: `import "@f-ewald/components/app-shell.js";`
113
+
114
+ Properties: `sidebarCollapsed` (attribute `sidebar-collapsed`) : boolean, default false; `detailOpen` (attribute `detail-open`) : boolean, default false; `detailWidth` (attribute `detail-width`) : "compact" | "comfortable", default "compact"
115
+ Events: `sidebar-toggle`, `detail-close`
116
+ CSS custom properties: `--ui-border`, `--ui-focus-ring`, `--ui-font-size-sm`, `--ui-line-height-tight`, `--ui-on-accent`, `--ui-overlay`, `--ui-radius-sm`, `--ui-shadow`, `--ui-shadow-lg`, `--ui-surface`, `--ui-surface-muted`, `--ui-text-muted`, `--ui-tooltip`
117
+
118
+ Example:
119
+ ```html
120
+ <app-shell detail-open style="height: 100vh">
121
+ <app-sidebar slot="sidebar">
122
+ <a href="/dashboard" aria-current="page" aria-label="Dashboard">
123
+ <!-- icon --><span style="display: var(--app-sidebar-label, inline)">Dashboard</span>
124
+ </a>
125
+ </app-sidebar>
126
+ <page-header slot="topbar" heading="Members"></page-header>
127
+ <action-bar>
128
+ <autocomplete-input slot="start" placeholder="Search…"></autocomplete-input>
129
+ <ui-button slot="end" variant="primary">Create</ui-button>
130
+ </action-bar>
131
+ <data-table></data-table>
132
+ <div slot="detail">Selected record…</div>
133
+ <pagination-nav slot="footer" total-pages="5"></pagination-nav>
134
+ </app-shell>
135
+ ```
136
+
137
+ ## <app-sidebar>
138
+
139
+ Collapsible navigation sidebar for the `app-shell` sidebar slot. It is
140
+ deliberately presentational and router-agnostic: the consumer supplies the
141
+ nav items as plain `<a>`/`<button>` elements (each an icon followed by a
142
+ label), optional `<p>` group headings, and marks the active item with
143
+ `aria-current="page"`. The sidebar styles them, tracks hover/active/focus,
144
+ and — in collapsed "rail" mode — centers the icons and hides the labels.
145
+
146
+ Rail mode is driven by the `collapsed` attribute (the parent `app-shell`
147
+ toggles it). Labels are hidden by the inherited `--app-sidebar-label` custom
148
+ property, so each label element should read it, e.g.
149
+ `<span style="display: var(--app-sidebar-label, inline)">Reports</span>`;
150
+ keep an `aria-label` on the item so its accessible name survives collapse.
151
+ The sidebar fills the width and height of its container — `app-shell` owns
152
+ the actual rail/expanded width.
153
+
154
+ Import: `import "@f-ewald/components/app-sidebar.js";`
155
+
156
+ Properties: `collapsed` (attribute `collapsed`) : boolean, default false
157
+ Events: none
158
+ CSS custom properties: `--ui-border`, `--ui-focus-ring`, `--ui-font`, `--ui-font-size-sm`, `--ui-font-size-xs`, `--ui-font-weight-medium`, `--ui-font-weight-semibold`, `--ui-line-height-tight`, `--ui-primary`, `--ui-radius-sm`, `--ui-surface`, `--ui-surface-muted`, `--ui-text`, `--ui-text-muted`, `--ui-tracking-wide`
159
+
160
+ Example:
161
+ ```html
162
+ <app-sidebar>
163
+ <a href="/dashboard" aria-current="page" aria-label="Dashboard">
164
+ <!-- icon --><span style="display: var(--app-sidebar-label, inline)">Dashboard</span>
165
+ </a>
166
+ <a href="/members" aria-label="Members">
167
+ <!-- icon --><span style="display: var(--app-sidebar-label, inline)">Members</span>
168
+ </a>
169
+ </app-sidebar>
170
+ ```
171
+
64
172
  ## <autocomplete-input>
65
173
 
66
174
  Generic form-associated text input with a suggestion dropdown, for any
@@ -247,6 +355,28 @@ Example:
247
355
  </confirm-dialog>
248
356
  ```
249
357
 
358
+ ## <content-divider>
359
+
360
+ A horizontal divider: a thin rule that visually separates two pieces of
361
+ content that are not otherwise contained in a box or frame and would bleed
362
+ into each other. With a `label` it renders the common "─── OR ───"
363
+ pattern — text centered between two line segments; without one it is a
364
+ single full-width rule. Exposed to assistive technology as a horizontal
365
+ separator, so it renders correctly with zero external CSS.
366
+
367
+ Import: `import "@f-ewald/components/content-divider.js";`
368
+
369
+ Properties: `label` (attribute `label`) : string, default ""
370
+ Events: none
371
+ CSS custom properties: `--ui-border`, `--ui-font`, `--ui-font-size-sm`, `--ui-font-weight-medium`, `--ui-line-height-tight`, `--ui-text-muted`
372
+
373
+ Example:
374
+ ```html
375
+ <content-divider></content-divider>
376
+
377
+ <content-divider label="OR"></content-divider>
378
+ ```
379
+
250
380
  ## <copy-link-button>
251
381
 
252
382
  Small icon button that copies `value` to the clipboard and shows a toast
@@ -390,6 +520,33 @@ Example:
390
520
  <editable-text multiline placeholder="Add a description…" label="Description"></editable-text>
391
521
  ```
392
522
 
523
+ ## <form-actions>
524
+
525
+ Form footer button bar with a fixed action order for internal apps: the
526
+ primary (submit) button is always rightmost, the secondary (cancel) button
527
+ sits to its immediate left, and an optional tertiary/destructive action is
528
+ pinned to the far left. The order is enforced by the component regardless of
529
+ the source order the buttons are authored in, so every form in a product
530
+ reads the same way.
531
+
532
+ Purely presentational: it lays out whatever controls (usually `ui-button`)
533
+ are slotted and never intercepts their clicks, `type="submit"`, or events.
534
+
535
+ Import: `import "@f-ewald/components/form-actions.js";`
536
+
537
+ Properties: none
538
+ Events: none
539
+ CSS custom properties: none
540
+
541
+ Example:
542
+ ```html
543
+ <form-actions>
544
+ <ui-button slot="start" variant="danger">Delete</ui-button>
545
+ <ui-button slot="secondary" variant="secondary">Cancel</ui-button>
546
+ <ui-button slot="primary" type="submit" variant="primary">Save</ui-button>
547
+ </form-actions>
548
+ ```
549
+
393
550
  ## <form-select>
394
551
 
395
552
  A styled dropdown select: a trigger button showing the current option's
@@ -780,6 +937,49 @@ Example:
780
937
  </script>
781
938
  ```
782
939
 
940
+ ## <page-header>
941
+
942
+ Page title block for the top of a dashboard view: an optional breadcrumb
943
+ trail, the page heading, and a right-aligned cluster of page-level actions.
944
+ It only lays these out — the breadcrumb links and action buttons are entirely
945
+ the consumer's, so it stays framework- and router-agnostic.
946
+
947
+ Import: `import "@f-ewald/components/page-header.js";`
948
+
949
+ Properties: `heading` (attribute `heading`) : string, default ""
950
+ Events: none
951
+ CSS custom properties: `--ui-font`, `--ui-font-size-lg`, `--ui-font-size-sm`, `--ui-font-weight-semibold`, `--ui-line-height-tight`, `--ui-text`, `--ui-text-muted`
952
+
953
+ Example:
954
+ ```html
955
+ <page-header heading="Team members">
956
+ <nav slot="breadcrumb" aria-label="Breadcrumb">Home / Settings / Members</nav>
957
+ <ui-button slot="actions" variant="primary">Invite</ui-button>
958
+ </page-header>
959
+ ```
960
+
961
+ ## <pagination-nav>
962
+
963
+ Minimal, controlled pager for list/table views: a previous/next control pair
964
+ around a "Page N of M" status. It owns no data — the consumer sets
965
+ `current-page` / `total-pages` and moves the page in response to the
966
+ `page-change` event (typically alongside its own data fetch), exactly like
967
+ `data-table` leaves the row data to the caller.
968
+
969
+ Previous is disabled on the first page and next on the last; neither fires an
970
+ event when there is nowhere to go.
971
+
972
+ Import: `import "@f-ewald/components/pagination-nav.js";`
973
+
974
+ Properties: `currentPage` (attribute `current-page`) : number, default 1; `totalPages` (attribute `total-pages`) : number, default 1
975
+ Events: `page-change`
976
+ CSS custom properties: `--ui-border`, `--ui-focus-ring`, `--ui-font`, `--ui-font-size-sm`, `--ui-font-weight-medium`, `--ui-line-height-tight`, `--ui-radius-sm`, `--ui-surface-muted`, `--ui-text`, `--ui-text-muted`
977
+
978
+ Example:
979
+ ```html
980
+ <pagination-nav current-page="1" total-pages="5"></pagination-nav>
981
+ ```
982
+
783
983
  ## <percent-bar-chart>
784
984
 
785
985
  Horizontal bar chart for labeled percentage rows, using D3's linear scale.
@@ -1095,6 +1295,57 @@ Example:
1095
1295
  </script>
1096
1296
  ```
1097
1297
 
1298
+ ## <timeline-container>
1299
+
1300
+ Vertical timeline: a single connecting line runs down the left edge and each
1301
+ slotted `timeline-entry` places a dot on it. This is a thin layout and
1302
+ semantics wrapper — the entries draw the line segments and dots themselves,
1303
+ so the container adds no gap between them (a gap would break the line).
1304
+ Exposed to assistive technology as a list of events.
1305
+
1306
+ Import: `import "@f-ewald/components/timeline-container.js";`
1307
+
1308
+ Properties: none
1309
+ Events: none
1310
+ CSS custom properties: none
1311
+
1312
+ Example:
1313
+ ```html
1314
+ <timeline-container>
1315
+ <timeline-entry datetime="2026-07-23T09:00:00Z">
1316
+ <span slot="headline">Deployment started</span>
1317
+ Release v1.4.0 is rolling out.
1318
+ </timeline-entry>
1319
+ <timeline-entry datetime="2026-07-23T08:45:00Z">
1320
+ <span slot="headline">Review approved</span>
1321
+ <status-pill label="In Review" color="info"></status-pill>
1322
+ </timeline-entry>
1323
+ </timeline-container>
1324
+ ```
1325
+
1326
+ ## <timeline-entry>
1327
+
1328
+ One event on a `timeline-container`: a dot on the vertical line, an optional
1329
+ headline, a relative timestamp ("3 hours ago"), and freely nested content.
1330
+ The connecting line is drawn here — its segment above the dot is hidden on
1331
+ the first entry and the segment below is hidden on the last, so the line caps
1332
+ exactly at the first and last dots. Only meaningful inside a
1333
+ `timeline-container`; demonstrated through it.
1334
+
1335
+ Import: `import "@f-ewald/components/timeline-entry.js";`
1336
+
1337
+ Properties: `datetime` (attribute `datetime`) : string | null, default null
1338
+ Events: none
1339
+ CSS custom properties: `--ui-border`, `--ui-font`, `--ui-font-size`, `--ui-font-size-sm`, `--ui-font-weight-semibold`, `--ui-line-height-normal`, `--ui-line-height-tight`, `--ui-primary`, `--ui-text`, `--ui-text-muted`
1340
+
1341
+ Example:
1342
+ ```html
1343
+ <timeline-entry datetime="2026-07-23T09:00:00Z">
1344
+ <span slot="headline">Deployment started</span>
1345
+ Release v1.4.0 is rolling out to production.
1346
+ </timeline-entry>
1347
+ ```
1348
+
1098
1349
  ## <toast-notification>
1099
1350
 
1100
1351
  Fixed-position stack of dismissible notifications, anchored top-right
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@f-ewald/components",
3
3
  "private": false,
4
- "version": "1.2.1",
4
+ "version": "1.4.0",
5
5
  "description": "A collection of universally usable web components for various tasks.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",