@f-ewald/components 0.5.0 → 0.7.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 (101) hide show
  1. package/README.md +61 -0
  2. package/custom-elements.json +3808 -930
  3. package/dist/chat-message.d.ts +39 -0
  4. package/dist/chat-message.d.ts.map +1 -0
  5. package/dist/chat-message.js +155 -0
  6. package/dist/chat-message.js.map +1 -0
  7. package/dist/data-table.d.ts +39 -0
  8. package/dist/data-table.d.ts.map +1 -0
  9. package/dist/data-table.js +119 -0
  10. package/dist/data-table.js.map +1 -0
  11. package/dist/dropdown-button.d.ts +37 -0
  12. package/dist/dropdown-button.d.ts.map +1 -0
  13. package/dist/dropdown-button.js +219 -0
  14. package/dist/dropdown-button.js.map +1 -0
  15. package/dist/editable-text.d.ts +52 -0
  16. package/dist/editable-text.d.ts.map +1 -0
  17. package/dist/editable-text.js +224 -0
  18. package/dist/editable-text.js.map +1 -0
  19. package/dist/form-select.d.ts +46 -0
  20. package/dist/form-select.d.ts.map +1 -0
  21. package/dist/form-select.js +245 -0
  22. package/dist/form-select.js.map +1 -0
  23. package/dist/frame-box.d.ts +22 -0
  24. package/dist/frame-box.d.ts.map +1 -0
  25. package/dist/frame-box.js +68 -0
  26. package/dist/frame-box.js.map +1 -0
  27. package/dist/gallery-item-variant.d.ts +21 -0
  28. package/dist/gallery-item-variant.d.ts.map +1 -0
  29. package/dist/gallery-item-variant.js +44 -0
  30. package/dist/gallery-item-variant.js.map +1 -0
  31. package/dist/gallery-item.d.ts +28 -0
  32. package/dist/gallery-item.d.ts.map +1 -0
  33. package/dist/gallery-item.js +54 -0
  34. package/dist/gallery-item.js.map +1 -0
  35. package/dist/icon-button.d.ts +27 -0
  36. package/dist/icon-button.d.ts.map +1 -0
  37. package/dist/icon-button.js +83 -0
  38. package/dist/icon-button.js.map +1 -0
  39. package/dist/icons.d.ts +8 -0
  40. package/dist/icons.d.ts.map +1 -1
  41. package/dist/icons.js +8 -0
  42. package/dist/icons.js.map +1 -1
  43. package/dist/index.d.ts +16 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +16 -1
  46. package/dist/index.js.map +1 -1
  47. package/dist/live-timer.d.ts +31 -0
  48. package/dist/live-timer.d.ts.map +1 -0
  49. package/dist/live-timer.js +78 -0
  50. package/dist/live-timer.js.map +1 -0
  51. package/dist/mcp-server.d.ts +3 -0
  52. package/dist/mcp-server.d.ts.map +1 -0
  53. package/dist/mcp-server.js +82 -0
  54. package/dist/mcp-server.js.map +1 -0
  55. package/dist/photo-gallery.d.ts +117 -0
  56. package/dist/photo-gallery.d.ts.map +1 -0
  57. package/dist/photo-gallery.js +620 -0
  58. package/dist/photo-gallery.js.map +1 -0
  59. package/dist/popover-panel.d.ts +37 -0
  60. package/dist/popover-panel.d.ts.map +1 -0
  61. package/dist/popover-panel.js +184 -0
  62. package/dist/popover-panel.js.map +1 -0
  63. package/dist/status-pill.d.ts +24 -0
  64. package/dist/status-pill.d.ts.map +1 -0
  65. package/dist/status-pill.js +101 -0
  66. package/dist/status-pill.js.map +1 -0
  67. package/dist/tile-grid.d.ts +32 -0
  68. package/dist/tile-grid.d.ts.map +1 -0
  69. package/dist/tile-grid.js +102 -0
  70. package/dist/tile-grid.js.map +1 -0
  71. package/dist/tokens.css +39 -0
  72. package/dist/tokens.d.ts +28 -3
  73. package/dist/tokens.d.ts.map +1 -1
  74. package/dist/tokens.js +42 -43
  75. package/dist/tokens.js.map +1 -1
  76. package/dist/user-avatar.d.ts +5 -2
  77. package/dist/user-avatar.d.ts.map +1 -1
  78. package/dist/user-avatar.js +22 -6
  79. package/dist/user-avatar.js.map +1 -1
  80. package/dist/utils/duration.d.ts +12 -0
  81. package/dist/utils/duration.d.ts.map +1 -0
  82. package/dist/utils/duration.js +27 -0
  83. package/dist/utils/duration.js.map +1 -0
  84. package/docs/chat-message.md +59 -0
  85. package/docs/data-table.md +63 -0
  86. package/docs/dropdown-button.md +61 -0
  87. package/docs/editable-text.md +51 -0
  88. package/docs/form-select.md +70 -0
  89. package/docs/frame-box.md +43 -0
  90. package/docs/gallery-item-variant.md +37 -0
  91. package/docs/gallery-item.md +47 -0
  92. package/docs/icon-button.md +52 -0
  93. package/docs/live-timer.md +39 -0
  94. package/docs/mcp-evaluation.md +18 -11
  95. package/docs/photo-gallery.md +77 -0
  96. package/docs/popover-panel.md +70 -0
  97. package/docs/status-pill.md +43 -0
  98. package/docs/tile-grid.md +58 -0
  99. package/docs/user-avatar.md +1 -1
  100. package/llms.txt +357 -1
  101. package/package.json +10 -3
@@ -0,0 +1,70 @@
1
+ # `<form-select>`
2
+
3
+ A styled dropdown select: a trigger button showing the current option's
4
+ label, opening a listbox popover on click. Drop-in generic replacement for
5
+ a native `<select>` wherever consistent cross-browser styling and a
6
+ `change` event carrying `{ value }` are wanted (e.g. a task's status
7
+ picker).
8
+
9
+ The trigger fills its host's width (`justify-content: space-between`
10
+ pushes the chevron to the far edge), but the host itself stays
11
+ `display: inline-block` — so usages that never size the host (a filter
12
+ bar, a status picker) keep shrink-to-fit auto-width unchanged. To make an
13
+ instance full-width, size the host itself: `form-select { width: 100%; }`.
14
+
15
+ ## Install
16
+
17
+ ```js
18
+ import "@f-ewald/components/form-select.js";
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```html
24
+ <form-select label="Task state"></form-select>
25
+ <script type="module">
26
+ const select = document.querySelector("form-select");
27
+ select.options = [
28
+ { value: "open", label: "Open" },
29
+ { value: "in_progress", label: "In progress" },
30
+ { value: "done", label: "Done" },
31
+ ];
32
+ select.value = "open";
33
+ select.addEventListener("change", (e) => console.log(e.detail.value));
34
+ </script>
35
+ ```
36
+
37
+ ## Attributes / properties
38
+
39
+ | Property | Attribute | Type | Default | Description |
40
+ | --- | --- | --- | --- | --- |
41
+ | `options` | _(JS property only)_ | `SelectOption[]` | `[]` | The full list of selectable options. |
42
+ | `value` | `value` | `string` | `""` | Currently selected value; must match one of `options[].value`. |
43
+ | `label` | `label` | `string` | `""` | `aria-label` applied to the trigger button. |
44
+ | `disabled` | `disabled` | `boolean` | `false` | Disables the trigger, preventing the popover from opening. |
45
+
46
+ ## Events
47
+
48
+ | Event | Description |
49
+ | --- | --- |
50
+ | `change` | Fired with `{ value: string }` when a different option is picked. |
51
+
52
+ ## Slots
53
+
54
+ _None._
55
+
56
+ ## CSS custom properties
57
+
58
+ | Custom property |
59
+ | --- |
60
+ | `--ui-border` |
61
+ | `--ui-focus-ring` |
62
+ | `--ui-font` |
63
+ | `--ui-font-size-sm` |
64
+ | `--ui-primary` |
65
+ | `--ui-radius-sm` |
66
+ | `--ui-shadow` |
67
+ | `--ui-surface` |
68
+ | `--ui-surface-muted` |
69
+ | `--ui-text` |
70
+ | `--ui-text-muted` |
@@ -0,0 +1,43 @@
1
+ # `<frame-box>`
2
+
3
+ A titled frame around a slot: a gray border with a small uppercase,
4
+ muted label overlapping the top edge (fieldset/legend-style). Generic —
5
+ the label text is entirely up to the consumer (e.g. "Debug" to visually
6
+ fence off dev-only chrome from the product UI).
7
+
8
+ ## Install
9
+
10
+ ```js
11
+ import "@f-ewald/components/frame-box.js";
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```html
17
+ <frame-box label="Debug">
18
+ Framed content goes here.
19
+ </frame-box>
20
+ ```
21
+
22
+ ## Attributes / properties
23
+
24
+ | Property | Attribute | Type | Default | Description |
25
+ | --- | --- | --- | --- | --- |
26
+ | `label` | `label` | `string` | `""` | The overlapping title label, e.g. "Debug". |
27
+
28
+ ## Events
29
+
30
+ _None._
31
+
32
+ ## Slots
33
+
34
+ _None._
35
+
36
+ ## CSS custom properties
37
+
38
+ | Custom property |
39
+ | --- |
40
+ | `--ui-border` |
41
+ | `--ui-radius-sm` |
42
+ | `--ui-surface` |
43
+ | `--ui-text-muted` |
@@ -0,0 +1,37 @@
1
+ # `<gallery-item-variant>`
2
+
3
+ Responsive image source metadata for a parent `gallery-item`.
4
+
5
+ ## Install
6
+
7
+ ```js
8
+ import "@f-ewald/components/gallery-item-variant.js";
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```html
14
+ <gallery-item-variant
15
+ media="(max-width: 640px)"
16
+ srcset="/photos/coast-portrait.jpg"
17
+ ></gallery-item-variant>
18
+ ```
19
+
20
+ ## Attributes / properties
21
+
22
+ | Property | Attribute | Type | Default | Description |
23
+ | --- | --- | --- | --- | --- |
24
+ | `media` | `media` | `string | undefined` | `—` | Optional media query that controls when this source is selected. |
25
+ | `srcset` | `srcset` | `string` | `""` | Responsive image candidate string passed to a generated `<source>`. |
26
+
27
+ ## Events
28
+
29
+ _None._
30
+
31
+ ## Slots
32
+
33
+ _None._
34
+
35
+ ## CSS custom properties
36
+
37
+ _None._
@@ -0,0 +1,47 @@
1
+ # `<gallery-item>`
2
+
3
+ Declarative image metadata consumed by a parent `photo-gallery`.
4
+
5
+ ## Install
6
+
7
+ ```js
8
+ import "@f-ewald/components/gallery-item.js";
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```html
14
+ <gallery-item
15
+ src="/photos/coast.jpg"
16
+ alt="Rocky California coastline"
17
+ caption="California coast"
18
+ >
19
+ <gallery-item-variant
20
+ media="(max-width: 640px)"
21
+ srcset="/photos/coast-portrait.jpg"
22
+ ></gallery-item-variant>
23
+ </gallery-item>
24
+ ```
25
+
26
+ ## Attributes / properties
27
+
28
+ | Property | Attribute | Type | Default | Description |
29
+ | --- | --- | --- | --- | --- |
30
+ | `src` | `src` | `string` | `""` | URL of the fallback image. |
31
+ | `alt` | `alt` | `string` | `""` | Required alternative text for the image. |
32
+ | `caption` | `caption` | `string | undefined` | `—` | Optional visible caption rendered below the image. |
33
+ | `variants` | _(JS property only)_ | `GalleryItemVariant[]` | `—` | Responsive source variants declared inside this item. _(read-only)_ |
34
+
35
+ ## Events
36
+
37
+ _None._
38
+
39
+ ## Slots
40
+
41
+ | Slot | Description |
42
+ | --- | --- |
43
+ | `(default)` | Optional `gallery-item-variant` responsive image sources. |
44
+
45
+ ## CSS custom properties
46
+
47
+ _None._
@@ -0,0 +1,52 @@
1
+ # `<icon-button>`
2
+
3
+ A borderless button wrapping a passed-in icon, with a rounded
4
+ hover-highlight background. Use for a low-emphasis affordance next to
5
+ content it acts on (e.g. an "Edit" pencil at the end of a table row)
6
+ where a bordered `ui-button` would be too heavy.
7
+
8
+ ## Install
9
+
10
+ ```js
11
+ import "@f-ewald/components/icon-button.js";
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```html
17
+ <icon-button label="Edit"></icon-button>
18
+ <script type="module">
19
+ import { iconPencil } from "@f-ewald/components/icons.js";
20
+ const btn = document.querySelector("icon-button");
21
+ btn.icon = iconPencil(16);
22
+ btn.addEventListener("click", () => console.log("edit clicked"));
23
+ </script>
24
+ ```
25
+
26
+ ## Attributes / properties
27
+
28
+ | Property | Attribute | Type | Default | Description |
29
+ | --- | --- | --- | --- | --- |
30
+ | `icon` | _(JS property only)_ | `TemplateResult | null` | `null` | Pre-rendered icon template, e.g. `iconPencil(16)` from this package's icon set. |
31
+ | `label` | `label` | `string` | `""` | Required accessible label, applied as `aria-label`/`title`. |
32
+ | `disabled` | `disabled` | `boolean` | `false` | Disables the button and dims it. |
33
+
34
+ ## Events
35
+
36
+ | Event | Description |
37
+ | --- | --- |
38
+ | `click` | Native click, bubbling as usual — listen on the element itself. |
39
+
40
+ ## Slots
41
+
42
+ _None._
43
+
44
+ ## CSS custom properties
45
+
46
+ | Custom property |
47
+ | --- |
48
+ | `--ui-focus-ring` |
49
+ | `--ui-radius-sm` |
50
+ | `--ui-surface-muted` |
51
+ | `--ui-text` |
52
+ | `--ui-text-muted` |
@@ -0,0 +1,39 @@
1
+ # `<live-timer>`
2
+
3
+ Per-second ticking count-up timer, e.g. a live "running for 12s" or
4
+ "Sleeping for 3 seconds" indicator. Renders nothing while `since` is unset
5
+ or unparseable.
6
+
7
+ ## Install
8
+
9
+ ```js
10
+ import "@f-ewald/components/live-timer.js";
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```html
16
+ <live-timer since="2026-07-19T12:00:00Z" prefix="Sleeping for "></live-timer>
17
+ <live-timer since="2026-07-19T12:00:00Z" format="compact" prefix="running for "></live-timer>
18
+ ```
19
+
20
+ ## Attributes / properties
21
+
22
+ | Property | Attribute | Type | Default | Description |
23
+ | --- | --- | --- | --- | --- |
24
+ | `since` | `since` | `string | null` | `null` | ISO-8601 start instant; elapsed time is measured from here. |
25
+ | `format` | `format` | `DurationFormat` | `"seconds"` | `"seconds"` -> "1 second", "12 seconds"; `"compact"` -> "12s", "3m 12s", "1h 03m 12s". |
26
+ | `prefix` | `prefix` | `string` | `""` | Text rendered before the formatted value. |
27
+ | `suffix` | `suffix` | `string` | `""` | Text rendered after the formatted value. |
28
+
29
+ ## Events
30
+
31
+ _None._
32
+
33
+ ## Slots
34
+
35
+ _None._
36
+
37
+ ## CSS custom properties
38
+
39
+ _None._
@@ -1,31 +1,38 @@
1
1
  # MCP server evaluation
2
2
 
3
- **Recommendation: do not build an MCP server for this package now.**
3
+ **Update (0.6.0 era, 34 components): built.** The catalog crossed the ~30+
4
+ revisit threshold below, so the upgrade path described here was implemented
5
+ as `src/mcp-server.ts`. See the "MCP server" section in the root `CLAUDE.md`
6
+ for the current tools, build step, and how consuming projects wire it up.
7
+ The original evaluation is kept below for the reasoning that justified
8
+ waiting until this point.
9
+
10
+ ## Original recommendation (superseded): do not build an MCP server yet
4
11
 
5
12
  ## Rationale
6
13
 
7
- The component catalog is small (14 tags). `llms.txt` ships in the npm
14
+ The component catalog was small (14 tags). `llms.txt` ships in the npm
8
15
  package and is fetchable directly from unpkg or GitHub raw, so any LLM or
9
16
  agent can load the full API surface — every component's attributes,
10
17
  properties, events, slots, tokens, and a usage example — in one small file,
11
18
  with no server, process, or additional versioning/packaging burden. An MCP
12
19
  server would duplicate that same data behind a stdio process that needs its
13
20
  own install, auth-free-but-still-a-process lifecycle, and release cadence
14
- kept in sync with the package — for zero functional gain at this scale.
21
+ kept in sync with the package — for zero functional gain at that scale.
15
22
 
16
- ## When to revisit
23
+ ## When to revisit (met)
17
24
 
18
25
  - The catalog grows past a size where `llms.txt` stops being comfortable to
19
- load into a single context window (rule of thumb: ~30+ components).
26
+ load into a single context window (rule of thumb: ~30+ components).
27
+ **met at 34 components.**
20
28
  - Consumers want live search, fuzzy matching, or filtered/paginated results
21
29
  instead of "load everything."
22
30
  - Consumers want examples or docs that go beyond what's derivable from
23
31
  `custom-elements.json` (e.g. runnable playground snippets, live preview).
24
32
 
25
- ## Upgrade path
33
+ ## Upgrade path (implemented)
26
34
 
27
- If/when it's warranted, a thin stdio MCP server exposing two tools —
28
- `list_components` and `get_component_docs(tag)` — backed by the same
29
- `custom-elements.json` this package already generates and ships. No new
30
- data source would be needed; the server would just be a different transport
31
- over data that already exists.
35
+ A thin stdio MCP server exposing two tools — `list_components` and
36
+ `get_component_docs(tag)` — backed by the same `custom-elements.json` this
37
+ package already generates and ships. No new data source was needed; the
38
+ server is just a different transport over data that already existed.
@@ -0,0 +1,77 @@
1
+ # `<photo-gallery>`
2
+
3
+ Responsive, accessible image carousel composed from declarative
4
+ `gallery-item` children.
5
+
6
+ ## Install
7
+
8
+ ```js
9
+ import "@f-ewald/components/photo-gallery.js";
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ```html
15
+ <photo-gallery delay="5000" show-counter show-indicators>
16
+ <gallery-item
17
+ src="/photos/coast.jpg"
18
+ alt="Rocky California coastline"
19
+ caption="California coast"
20
+ >
21
+ <gallery-item-variant
22
+ media="(max-width: 640px)"
23
+ srcset="/photos/coast-portrait.jpg"
24
+ ></gallery-item-variant>
25
+ </gallery-item>
26
+ <gallery-item src="/photos/bridge.jpg" alt="Golden Gate Bridge"></gallery-item>
27
+ </photo-gallery>
28
+ <script type="module">
29
+ document.querySelector("photo-gallery").addEventListener("slide-change", (event) => {
30
+ console.log(event.detail.currentIndex);
31
+ });
32
+ </script>
33
+ ```
34
+
35
+ ## Attributes / properties
36
+
37
+ | Property | Attribute | Type | Default | Description |
38
+ | --- | --- | --- | --- | --- |
39
+ | `currentIndex` | `current-index` | `number` | `0` | Zero-based active image index. |
40
+ | `delay` | `delay` | `number` | `0` | Autoplay interval in milliseconds. Set to zero to disable autoplay. |
41
+ | `showControls` | `show-controls` | `boolean` | `true` | Whether previous and next buttons are shown. |
42
+ | `showCounter` | `show-counter` | `boolean` | `false` | Whether a current/total counter is shown. |
43
+ | `showIndicators` | `show-indicators` | `boolean` | `false` | Whether clickable slide indicators are shown. |
44
+ | `showAutoplayControl` | `show-autoplay-control` | `boolean` | `true` | Whether autoplay includes a built-in pause/play control. |
45
+ | `paused` | `paused` | `boolean` | `false` | Whether autoplay is explicitly paused. |
46
+ | `aspectRatio` | `aspect-ratio` | `string` | `"16 / 9"` | CSS aspect ratio used by the image viewport. |
47
+ | `objectFit` | `object-fit` | `PhotoGalleryObjectFit` | `"cover"` | How images fit within the stable viewport. |
48
+
49
+ ## Events
50
+
51
+ | Event | Description |
52
+ | --- | --- |
53
+ | `slide-change` | The active image changed. |
54
+
55
+ ## Slots
56
+
57
+ | Slot | Description |
58
+ | --- | --- |
59
+ | `(default)` | Declarative `gallery-item` elements rendered as slides. |
60
+
61
+ ## CSS custom properties
62
+
63
+ | Custom property |
64
+ | --- |
65
+ | `--ui-border` |
66
+ | `--ui-focus-ring` |
67
+ | `--ui-font` |
68
+ | `--ui-font-size` |
69
+ | `--ui-font-size-sm` |
70
+ | `--ui-overlay` |
71
+ | `--ui-primary` |
72
+ | `--ui-radius` |
73
+ | `--ui-radius-sm` |
74
+ | `--ui-surface` |
75
+ | `--ui-surface-muted` |
76
+ | `--ui-text` |
77
+ | `--ui-text-muted` |
@@ -0,0 +1,70 @@
1
+ # `<popover-panel>`
2
+
3
+ Generic anchored popover shell: a floating card positioned relative to its
4
+ nearest `position: relative` ancestor (place it next to its trigger button
5
+ inside such a wrapper), as opposed to `slide-panel`'s fixed screen-edge
6
+ drawer. Closes on outside click or Escape. Header chrome and close button
7
+ match `slide-panel`'s API (`heading`, `panel-close`) so either can be
8
+ swapped in for the other with no consumer-side changes beyond the wrapper.
9
+
10
+ Set `centered` to render as a screen-centered modal with a translucent
11
+ backdrop instead of the default anchored placement.
12
+
13
+ ## Install
14
+
15
+ ```js
16
+ import "@f-ewald/components/popover-panel.js";
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```html
22
+ <div style="position: relative; display: inline-block;">
23
+ <button id="new-task-btn">New task</button>
24
+ <popover-panel heading="New task">
25
+ Popover body content goes here.
26
+ </popover-panel>
27
+ </div>
28
+ <script type="module">
29
+ const popover = document.querySelector("popover-panel");
30
+ document.querySelector("#new-task-btn").addEventListener("click", () => (popover.open = true));
31
+ popover.addEventListener("panel-close", () => (popover.open = false));
32
+ </script>
33
+ ```
34
+
35
+ ## Attributes / properties
36
+
37
+ | Property | Attribute | Type | Default | Description |
38
+ | --- | --- | --- | --- | --- |
39
+ | `open` | `open` | `boolean` | `false` | Whether the popover is currently visible. |
40
+ | `heading` | `heading` | `string` | `""` | Title text shown in the popover header. |
41
+ | `centered` | `centered` | `boolean` | `false` | Render as a screen-centered modal with a backdrop instead of anchored placement. |
42
+
43
+ ## Events
44
+
45
+ | Event | Description |
46
+ | --- | --- |
47
+ | `panel-close` | User clicked the close (✕) button, pressed Escape, or clicked outside/the backdrop. |
48
+
49
+ ## Slots
50
+
51
+ | Slot | Description |
52
+ | --- | --- |
53
+ | `(default)` | Popover body content. |
54
+ | `title` | Overrides the plain `heading` text with custom markup. |
55
+ | `actions` | Extra header controls (e.g. an icon+label link) rendered between the title and the close button. |
56
+
57
+ ## CSS custom properties
58
+
59
+ | Custom property |
60
+ | --- |
61
+ | `--ui-border` |
62
+ | `--ui-font` |
63
+ | `--ui-font-size` |
64
+ | `--ui-radius` |
65
+ | `--ui-radius-sm` |
66
+ | `--ui-shadow-lg` |
67
+ | `--ui-surface` |
68
+ | `--ui-surface-muted` |
69
+ | `--ui-text` |
70
+ | `--ui-text-muted` |
@@ -0,0 +1,43 @@
1
+ # `<status-pill>`
2
+
3
+ Small colored status pill, optionally with a spinning icon — for task/run
4
+ states ("Open", "Blocked", "Done") and live-activity indicators ("Running").
5
+
6
+ ## Install
7
+
8
+ ```js
9
+ import "@f-ewald/components/status-pill.js";
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ```html
15
+ <status-pill label="Running" color="primary" spinner></status-pill>
16
+ <status-pill label="Blocked" color="danger"></status-pill>
17
+ ```
18
+
19
+ ## Attributes / properties
20
+
21
+ | Property | Attribute | Type | Default | Description |
22
+ | --- | --- | --- | --- | --- |
23
+ | `label` | `label` | `string` | `""` | Text shown inside the pill. |
24
+ | `color` | `color` | `StatusPillColor` | `"neutral"` | Color variant. |
25
+ | `spinner` | `spinner` | `boolean` | `false` | Renders a small spinning icon before the label. |
26
+
27
+ ## Events
28
+
29
+ _None._
30
+
31
+ ## Slots
32
+
33
+ _None._
34
+
35
+ ## CSS custom properties
36
+
37
+ | Custom property |
38
+ | --- |
39
+ | `--ui-danger` |
40
+ | `--ui-font` |
41
+ | `--ui-primary` |
42
+ | `--ui-success` |
43
+ | `--ui-text-muted` |
@@ -0,0 +1,58 @@
1
+ # `<tile-grid>`
2
+
3
+ A generic, presentational grid shell: renders one bordered card per entry
4
+ in `items`, with each tile's content produced by `renderTile` (default:
5
+ stringify). Knows nothing about what an "item" means — callers own the
6
+ data shape entirely. Modeled directly on `data-table`'s headless pattern.
7
+
8
+ Optional `itemHref` makes whole tiles clickable (navigating via
9
+ `location.hash`), without hijacking clicks on nested interactive elements
10
+ (links/buttons) a tile's rendered content might contain.
11
+
12
+ ## Install
13
+
14
+ ```js
15
+ import "@f-ewald/components/tile-grid.js";
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```html
21
+ <tile-grid></tile-grid>
22
+ <script type="module">
23
+ const grid = document.querySelector("tile-grid");
24
+ grid.items = [
25
+ { name: "notes.txt" },
26
+ { name: "photo.jpg" },
27
+ ];
28
+ grid.renderTile = (item) => item.name;
29
+ </script>
30
+ ```
31
+
32
+ ## Attributes / properties
33
+
34
+ | Property | Attribute | Type | Default | Description |
35
+ | --- | --- | --- | --- | --- |
36
+ | `items` | _(JS property only)_ | `unknown[]` | `[]` | Tile data; opaque to this component beyond what `renderTile` does with it. |
37
+ | `itemKey` | _(JS property only)_ | `(item: unknown, index: number) => string | number` | `—` | Stable identity for `items[i]`, used as the repeat-directive key. Defaults to the item's index. |
38
+ | `renderTile` | _(JS property only)_ | `(item: unknown) => unknown` | `—` | Produces a tile's rendered content for `item`. Default: stringify. |
39
+ | `itemHref` | _(JS property only)_ | `((item: unknown) => string | null) | null` | `null` | When set, clicking a tile (outside any nested link/button) navigates to this hash. |
40
+
41
+ ## Events
42
+
43
+ _None._
44
+
45
+ ## Slots
46
+
47
+ _None._
48
+
49
+ ## CSS custom properties
50
+
51
+ | Custom property |
52
+ | --- |
53
+ | `--ui-border` |
54
+ | `--ui-font` |
55
+ | `--ui-font-size-sm` |
56
+ | `--ui-radius` |
57
+ | `--ui-surface-muted` |
58
+ | `--ui-text` |
@@ -24,7 +24,7 @@ import "@f-ewald/components/user-avatar.js";
24
24
  | --- | --- | --- | --- | --- |
25
25
  | `src` | `src` | `string | null` | `null` | Image URL to show. Falls back to initials/icon if unset or it fails to load. |
26
26
  | `name` | `name` | `string | null` | `null` | Source string for the fallback initial (e.g. a display name or email) — first character, uppercased. |
27
- | `size` | `size` | `number` | `32` | Diameter in CSS pixels. |
27
+ | `size` | `size` | `string | number` | `32` | Diameter in CSS pixels, or a preset name (`xs`=18, `sm`=24, `md`=32, `lg`=48). |
28
28
 
29
29
  ## Events
30
30