@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
@@ -0,0 +1,52 @@
1
+ # Form page
2
+
3
+ A create/edit form: navigation, a titled header, a single form grouped into
4
+ framed sections, and a `form-actions` bar with the fixed button order.
5
+
6
+ **When to use:** creating or editing one record. Keep the form in a single
7
+ column so the eye tracks one field to the next.
8
+
9
+ ## Shell slots
10
+
11
+ - `sidebar` → `app-sidebar`.
12
+ - `topbar` → `page-header` with a `breadcrumb`.
13
+ - default (`main`) → one `<form>`; group fields with `frame-box` and end with
14
+ `form-actions`.
15
+
16
+ ## Markup
17
+
18
+ ```html
19
+ <app-shell style="height: 100vh">
20
+ <app-sidebar slot="sidebar"><!-- nav items --></app-sidebar>
21
+
22
+ <page-header slot="topbar" heading="Invite member">
23
+ <nav slot="breadcrumb" aria-label="Breadcrumb">Members / Invite</nav>
24
+ </page-header>
25
+
26
+ <form style="max-width: 40rem;">
27
+ <frame-box label="Details"><!-- name, email fields --></frame-box>
28
+ <frame-box label="Role"><!-- role field --></frame-box>
29
+
30
+ <form-actions>
31
+ <ui-button slot="secondary" variant="secondary">Cancel</ui-button>
32
+ <ui-button slot="primary" type="submit" variant="primary">Send invite</ui-button>
33
+ </form-actions>
34
+ </form>
35
+ </app-shell>
36
+ ```
37
+
38
+ ## Notes
39
+
40
+ - Button order is fixed and enforced by `form-actions`: primary/submit rightmost,
41
+ secondary/cancel to its left, any destructive action pinned far left. Never
42
+ hand-place form buttons in a different order.
43
+ - Constrain the form with a `max-width` (about `40rem`); a full-width form on a
44
+ wide dashboard is hard to scan.
45
+ - Group related fields with `frame-box`; keep one field per row in a single
46
+ column.
47
+ - `ui-button type="submit"` associates with the ancestor `<form>` even from
48
+ inside `form-actions`.
49
+
50
+ **Live demo:** `demo/layouts/form-page.html`
51
+
52
+ **Components:** app-shell, app-sidebar, page-header, frame-box, form-actions, ui-button
@@ -0,0 +1,52 @@
1
+ # List + detail page
2
+
3
+ A master-detail dashboard: the list-only page plus a right-hand detail column.
4
+ Selecting a row shows its detail beside the list on desktop and as an overlay on
5
+ narrow screens.
6
+
7
+ **When to use:** triaging or editing records where keeping the list visible
8
+ while inspecting one item speeds up the workflow (inbox-style screens, admin
9
+ record management).
10
+
11
+ ## Shell slots
12
+
13
+ - `sidebar` → `app-sidebar`.
14
+ - `topbar` → `page-header`.
15
+ - default (`main`) → `action-bar` + `data-table`.
16
+ - `detail` → the selected record's detail; shown when `detail-open` is set.
17
+ - `footer` → `pagination-nav`.
18
+
19
+ ## Markup
20
+
21
+ ```html
22
+ <app-shell detail-width="comfortable" style="height: 100vh">
23
+ <app-sidebar slot="sidebar"><!-- nav items --></app-sidebar>
24
+ <page-header slot="topbar" heading="Members"></page-header>
25
+
26
+ <div>
27
+ <action-bar>
28
+ <autocomplete-input slot="start" placeholder="Search…"></autocomplete-input>
29
+ <ui-button slot="end" variant="primary">Create</ui-button>
30
+ </action-bar>
31
+ <data-table style="margin-top: 0.5rem; display: block;"></data-table>
32
+ </div>
33
+
34
+ <div slot="detail" style="padding: 1rem;"><!-- selected record --></div>
35
+
36
+ <pagination-nav slot="footer" current-page="1" total-pages="6"></pagination-nav>
37
+ </app-shell>
38
+ ```
39
+
40
+ ## Notes
41
+
42
+ - Set `detail-open` on `app-shell` to reveal the detail column; clear it (or
43
+ listen for the `detail-close` event, fired when the mobile scrim/Escape
44
+ dismisses the overlay) to hide it.
45
+ - Wire a row selection (e.g. `data-table`'s `rowHref` + a hash listener, or your
46
+ router) to populate the detail slot and open it.
47
+ - `detail-width` is `compact` (20rem) or `comfortable` (25rem); below 48rem the
48
+ detail becomes an overlay regardless.
49
+
50
+ **Live demo:** `demo/layouts/list-detail.html`
51
+
52
+ **Components:** app-shell, app-sidebar, page-header, action-bar, data-table, pagination-nav
@@ -0,0 +1,50 @@
1
+ # List-only page
2
+
3
+ A full-width list/table view: a collapsible sidebar, a top bar, an action row,
4
+ the list, and pagination. The default internal-dashboard "index" screen.
5
+
6
+ **When to use:** browsing or managing a collection of records where a row does
7
+ not need a side-by-side detail pane (rows link to their own detail page). If you
8
+ want an inline detail pane, use the list + detail template instead.
9
+
10
+ ## Shell slots
11
+
12
+ - `sidebar` → `app-sidebar` with the app's navigation.
13
+ - `topbar` → `page-header` with the collection title (and optional actions).
14
+ - default (`main`) → an `action-bar` above a `data-table`.
15
+ - `footer` → `pagination-nav`.
16
+
17
+ ## Markup
18
+
19
+ ```html
20
+ <app-shell style="height: 100vh">
21
+ <app-sidebar slot="sidebar"><!-- nav items --></app-sidebar>
22
+
23
+ <page-header slot="topbar" heading="Members"></page-header>
24
+
25
+ <div>
26
+ <action-bar>
27
+ <autocomplete-input slot="start" placeholder="Search…"></autocomplete-input>
28
+ <ui-button slot="end" variant="secondary">Filter</ui-button>
29
+ <ui-button slot="end" variant="primary">Create</ui-button>
30
+ </action-bar>
31
+ <data-table style="margin-top: 1rem; display: block;"></data-table>
32
+ </div>
33
+
34
+ <pagination-nav slot="footer" current-page="1" total-pages="6"></pagination-nav>
35
+ </app-shell>
36
+ ```
37
+
38
+ ## Notes
39
+
40
+ - Give `app-shell` a height (e.g. `100vh`) so the sidebar and main can size and
41
+ scroll independently.
42
+ - `pagination-nav` is controlled: set `current-page`/`total-pages` and re-render
43
+ in response to its `page-change` event, the same way `data-table` leaves the
44
+ rows to you.
45
+ - Put search and filters in the action bar's `start` slot and record actions
46
+ (create, delete) in `end`.
47
+
48
+ **Live demo:** `demo/layouts/list-only.html`
49
+
50
+ **Components:** app-shell, app-sidebar, page-header, action-bar, data-table, pagination-nav
@@ -0,0 +1,88 @@
1
+ # Record + metadata rail page
2
+
3
+ A record's read view with the main content on the left and a persistent
4
+ metadata/detail rail on the right — the Jira/Linear issue layout (description +
5
+ status, assignee, labels, priority).
6
+
7
+ **When to use:** viewing one rich record whose metadata (status, owner, labels,
8
+ progress) should stay visible alongside the content, and where that metadata is
9
+ mostly a static display of components rather than a transient selection.
10
+
11
+ ## Layout
12
+
13
+ The rail is a **two-column CSS grid inside the `main` slot**, not the shell's
14
+ `detail` slot:
15
+
16
+ - `sidebar` → `app-sidebar`.
17
+ - `topbar` → `page-header` with a linked `breadcrumb` and record `actions`
18
+ (primary Edit rightmost).
19
+ - default (`main`) → a grid: the body (description, activity) on the left, an
20
+ `<aside>` metadata rail on the right. It collapses to one column at the shared
21
+ 48rem breakpoint so the metadata **stacks below** the content on narrow
22
+ screens instead of hiding.
23
+
24
+ The metadata rail is composed from existing components: `frame-box` to group,
25
+ `status-pill` for status/priority/labels, `user-avatar` for people, and
26
+ `stat-meter` for progress. Activity uses `chat-message`.
27
+
28
+ ## Markup
29
+
30
+ ```html
31
+ <app-shell style="height: 100vh">
32
+ <app-sidebar slot="sidebar"><!-- nav items --></app-sidebar>
33
+
34
+ <page-header slot="topbar" heading="Fix flaky login redirect">
35
+ <nav slot="breadcrumb" aria-label="Breadcrumb"><a href="/board">Board</a> / PROJ-142</nav>
36
+ <ui-button slot="actions" variant="primary">Edit</ui-button>
37
+ </page-header>
38
+
39
+ <div class="ticket">
40
+ <div class="ticket-body">
41
+ <h3>Description</h3>
42
+ <p>…</p>
43
+ <frame-box label="Activity">
44
+ <chat-message role="user" author="Ada Lovelace">…</chat-message>
45
+ </frame-box>
46
+ </div>
47
+
48
+ <aside class="ticket-meta" aria-label="Issue details">
49
+ <frame-box label="Details">
50
+ <dl class="meta">
51
+ <div class="meta-row"><dt>Status</dt><dd><status-pill label="In Progress" color="info"></status-pill></dd></div>
52
+ <div class="meta-row"><dt>Assignee</dt><dd><user-avatar name="Ada Lovelace" size="24"></user-avatar> Ada Lovelace</dd></div>
53
+ <div class="meta-row"><dt>Priority</dt><dd><status-pill label="High" color="warning"></status-pill></dd></div>
54
+ </dl>
55
+ <stat-meter label="Progress" percent="60"></stat-meter>
56
+ </frame-box>
57
+ </aside>
58
+ </div>
59
+ </app-shell>
60
+ ```
61
+
62
+ ```css
63
+ .ticket {
64
+ display: grid;
65
+ grid-template-columns: minmax(0, 1fr) 18rem;
66
+ gap: 1.5rem;
67
+ align-items: start;
68
+ }
69
+ @media (max-width: 48rem) {
70
+ .ticket { grid-template-columns: minmax(0, 1fr); }
71
+ }
72
+ ```
73
+
74
+ ## Notes
75
+
76
+ - Use the two-column grid inside `main` (not the shell `detail` slot) when the
77
+ metadata is **persistent** and should stack on mobile. The shell's `detail`
78
+ slot is for a **transient master-detail selection** (list + selected item): on
79
+ mobile it becomes a dismissible overlay, which hides persistent record
80
+ metadata. Reach for it in the list + detail template, not here.
81
+ - Editable metadata is a drop-in swap: replace a `status-pill` with a
82
+ `form-select`, or the label pills with a `multi-select`.
83
+ - Keep the record actions in the header (primary Edit); there is no
84
+ `form-actions` footer on a read view.
85
+
86
+ **Live demo:** `demo/layouts/record-detail.html`
87
+
88
+ **Components:** app-shell, app-sidebar, page-header, frame-box, status-pill, user-avatar, stat-meter, chat-message
@@ -36,3 +36,24 @@ A thin stdio MCP server exposing two tools — `list_components` and
36
36
  `get_component_docs(tag)` — backed by the same `custom-elements.json` this
37
37
  package already generates and ships. No new data source was needed; the
38
38
  server is just a different transport over data that already existed.
39
+
40
+ ## Update (layout system): added `list_layouts` / `get_layout`
41
+
42
+ The dashboard layout system introduced cross-component knowledge — which
43
+ components compose into which page templates, the slot recipes, and the
44
+ button-placement rule — that no single component's generated doc captures. Two
45
+ thin tools, `list_layouts` and `get_layout(name)`, expose it.
46
+
47
+ This stays true to the server's founding principle: **no new data source.** The
48
+ tools read the authored `docs/layouts/*.md` recipes (which also ship in the npm
49
+ package and render on the docs site), not a bespoke structure invented for MCP.
50
+ The individual layout components still flow through `list_components` /
51
+ `get_component_docs` automatically.
52
+
53
+ **Is MCP the right fit here?** It's a reasonable, not slam-dunk, fit. The
54
+ justification is discoverability and targeted retrieval — an agent can list the
55
+ templates and pull just the one it needs, rather than loading everything. If the
56
+ guidance stayed tiny, `llms.txt` alone could carry it; the tools earn their keep
57
+ by making the "preferred layout" explicitly enumerable and by matching the
58
+ per-component tools consumers already call. The cost to watch is keeping the
59
+ recipes, the `demo/layouts/` demos, and the tool output in sync.
@@ -0,0 +1,47 @@
1
+ # `<page-header>`
2
+
3
+ Page title block for the top of a dashboard view: an optional breadcrumb
4
+ trail, the page heading, and a right-aligned cluster of page-level actions.
5
+ It only lays these out — the breadcrumb links and action buttons are entirely
6
+ the consumer's, so it stays framework- and router-agnostic.
7
+
8
+ ## Install
9
+
10
+ ```js
11
+ import "@f-ewald/components/page-header.js";
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```html
17
+ <page-header heading="Team members">
18
+ <nav slot="breadcrumb" aria-label="Breadcrumb">Home / Settings / Members</nav>
19
+ <ui-button slot="actions" variant="primary">Invite</ui-button>
20
+ </page-header>
21
+ ```
22
+
23
+ ## Attributes / properties
24
+
25
+ | Property | Attribute | Type | Default | Description |
26
+ | --- | --- | --- | --- | --- |
27
+ | `heading` | `heading` | `string` | `""` | The page heading text. |
28
+
29
+ ## Events
30
+
31
+ _None._
32
+
33
+ ## Slots
34
+
35
+ _None._
36
+
37
+ ## CSS custom properties
38
+
39
+ | Custom property |
40
+ | --- |
41
+ | `--ui-font` |
42
+ | `--ui-font-size-lg` |
43
+ | `--ui-font-size-sm` |
44
+ | `--ui-font-weight-semibold` |
45
+ | `--ui-line-height-tight` |
46
+ | `--ui-text` |
47
+ | `--ui-text-muted` |
@@ -0,0 +1,54 @@
1
+ # `<pagination-nav>`
2
+
3
+ Minimal, controlled pager for list/table views: a previous/next control pair
4
+ around a "Page N of M" status. It owns no data — the consumer sets
5
+ `current-page` / `total-pages` and moves the page in response to the
6
+ `page-change` event (typically alongside its own data fetch), exactly like
7
+ `data-table` leaves the row data to the caller.
8
+
9
+ Previous is disabled on the first page and next on the last; neither fires an
10
+ event when there is nowhere to go.
11
+
12
+ ## Install
13
+
14
+ ```js
15
+ import "@f-ewald/components/pagination-nav.js";
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```html
21
+ <pagination-nav current-page="1" total-pages="5"></pagination-nav>
22
+ ```
23
+
24
+ ## Attributes / properties
25
+
26
+ | Property | Attribute | Type | Default | Description |
27
+ | --- | --- | --- | --- | --- |
28
+ | `currentPage` | `current-page` | `number` | `1` | The 1-based current page. |
29
+ | `totalPages` | `total-pages` | `number` | `1` | The total number of pages (minimum 1). |
30
+
31
+ ## Events
32
+
33
+ | Event | Description |
34
+ | --- | --- |
35
+ | `page-change` | The user picked a new page (`detail: { page }`). |
36
+
37
+ ## Slots
38
+
39
+ _None._
40
+
41
+ ## CSS custom properties
42
+
43
+ | Custom property |
44
+ | --- |
45
+ | `--ui-border` |
46
+ | `--ui-focus-ring` |
47
+ | `--ui-font` |
48
+ | `--ui-font-size-sm` |
49
+ | `--ui-font-weight-medium` |
50
+ | `--ui-line-height-tight` |
51
+ | `--ui-radius-sm` |
52
+ | `--ui-surface-muted` |
53
+ | `--ui-text` |
54
+ | `--ui-text-muted` |
@@ -0,0 +1,44 @@
1
+ # `<timeline-container>`
2
+
3
+ Vertical timeline: a single connecting line runs down the left edge and each
4
+ slotted `timeline-entry` places a dot on it. This is a thin layout and
5
+ semantics wrapper — the entries draw the line segments and dots themselves,
6
+ so the container adds no gap between them (a gap would break the line).
7
+ Exposed to assistive technology as a list of events.
8
+
9
+ ## Install
10
+
11
+ ```js
12
+ import "@f-ewald/components/timeline-container.js";
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```html
18
+ <timeline-container>
19
+ <timeline-entry datetime="2026-07-23T09:00:00Z">
20
+ <span slot="headline">Deployment started</span>
21
+ Release v1.4.0 is rolling out.
22
+ </timeline-entry>
23
+ <timeline-entry datetime="2026-07-23T08:45:00Z">
24
+ <span slot="headline">Review approved</span>
25
+ <status-pill label="In Review" color="info"></status-pill>
26
+ </timeline-entry>
27
+ </timeline-container>
28
+ ```
29
+
30
+ ## Attributes / properties
31
+
32
+ _None._
33
+
34
+ ## Events
35
+
36
+ _None._
37
+
38
+ ## Slots
39
+
40
+ _None._
41
+
42
+ ## CSS custom properties
43
+
44
+ _None._
@@ -0,0 +1,52 @@
1
+ # `<timeline-entry>`
2
+
3
+ One event on a `timeline-container`: a dot on the vertical line, an optional
4
+ headline, a relative timestamp ("3 hours ago"), and freely nested content.
5
+ The connecting line is drawn here — its segment above the dot is hidden on
6
+ the first entry and the segment below is hidden on the last, so the line caps
7
+ exactly at the first and last dots. Only meaningful inside a
8
+ `timeline-container`; demonstrated through it.
9
+
10
+ ## Install
11
+
12
+ ```js
13
+ import "@f-ewald/components/timeline-entry.js";
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```html
19
+ <timeline-entry datetime="2026-07-23T09:00:00Z">
20
+ <span slot="headline">Deployment started</span>
21
+ Release v1.4.0 is rolling out to production.
22
+ </timeline-entry>
23
+ ```
24
+
25
+ ## Attributes / properties
26
+
27
+ | Property | Attribute | Type | Default | Description |
28
+ | --- | --- | --- | --- | --- |
29
+ | `datetime` | `datetime` | `string | null` | `null` | ISO 8601 or SQLite datetime string, rendered as a relative time. |
30
+
31
+ ## Events
32
+
33
+ _None._
34
+
35
+ ## Slots
36
+
37
+ _None._
38
+
39
+ ## CSS custom properties
40
+
41
+ | Custom property |
42
+ | --- |
43
+ | `--ui-border` |
44
+ | `--ui-font` |
45
+ | `--ui-font-size` |
46
+ | `--ui-font-size-sm` |
47
+ | `--ui-font-weight-semibold` |
48
+ | `--ui-line-height-normal` |
49
+ | `--ui-line-height-tight` |
50
+ | `--ui-primary` |
51
+ | `--ui-text` |
52
+ | `--ui-text-muted` |