@f-ewald/components 1.6.0 → 1.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.
@@ -11390,7 +11390,7 @@
11390
11390
  "declarations": [
11391
11391
  {
11392
11392
  "kind": "class",
11393
- "description": "One event on a `timeline-container`: a dot on the vertical line, an optional\nheadline, a relative timestamp (\"3 hours ago\"), and freely nested content.\nThe connecting line is drawn here — its segment above the dot is hidden on\nthe first entry and the segment below is hidden on the last, so the line caps\nexactly at the first and last dots. Only meaningful inside a\n`timeline-container`; demonstrated through it.\n\n`datetime` is the entry's one timestamp. A nested element that has its own\ntimestamp prop (e.g. `chat-message`'s `timestamp`) should leave it unset —\nsetting both renders the same time twice.",
11393
+ "description": "One event on a `timeline-container`: a dot on the vertical line, an optional\nheadline, a relative timestamp (\"3 hours ago\"), and freely nested content.\nThe connecting line is drawn here — its segment above the dot is hidden on\nthe first entry and the segment below is hidden on the last, so the line caps\nexactly at the first and last dots. Only meaningful inside a\n`timeline-container`; demonstrated through it.\n\n`datetime` is the entry's one timestamp. A nested element that has its own\ntimestamp prop (e.g. `chat-message`'s `timestamp`) should leave it unset —\nsetting both renders the same time twice.\n\nThe dot's `color` types the entry using the shared status-pill palette —\n`primary` by default, plus `neutral`, `info`, `success`, `warning`, and\n`danger`.",
11394
11394
  "name": "TimelineEntry",
11395
11395
  "slots": [
11396
11396
  {
@@ -11413,6 +11413,16 @@
11413
11413
  "description": "ISO 8601 or SQLite datetime string, rendered as a relative time.",
11414
11414
  "attribute": "datetime"
11415
11415
  },
11416
+ {
11417
+ "kind": "field",
11418
+ "name": "color",
11419
+ "type": {
11420
+ "text": "StatusPillColor"
11421
+ },
11422
+ "default": "\"primary\"",
11423
+ "description": "Visual type of the entry's dot, from the shared status-pill palette:\n`primary` (default), `neutral`, `info`, `success`, `warning`, or `danger`.",
11424
+ "attribute": "color"
11425
+ },
11416
11426
  {
11417
11427
  "kind": "field",
11418
11428
  "name": "_hasHeadline",
@@ -11452,6 +11462,15 @@
11452
11462
  "default": "null",
11453
11463
  "description": "ISO 8601 or SQLite datetime string, rendered as a relative time.",
11454
11464
  "fieldName": "datetime"
11465
+ },
11466
+ {
11467
+ "name": "color",
11468
+ "type": {
11469
+ "text": "StatusPillColor"
11470
+ },
11471
+ "default": "\"primary\"",
11472
+ "description": "Visual type of the entry's dot, from the shared status-pill palette:\n`primary` (default), `neutral`, `info`, `success`, `warning`, or `danger`.",
11473
+ "fieldName": "color"
11455
11474
  }
11456
11475
  ],
11457
11476
  "superclass": {
@@ -1,5 +1,6 @@
1
1
  import { LitElement } from "lit";
2
2
  import "./relative-time.js";
3
+ import type { StatusPillColor } from "./status-pill.js";
3
4
  /**
4
5
  * One event on a `timeline-container`: a dot on the vertical line, an optional
5
6
  * headline, a relative timestamp ("3 hours ago"), and freely nested content.
@@ -12,6 +13,10 @@ import "./relative-time.js";
12
13
  * timestamp prop (e.g. `chat-message`'s `timestamp`) should leave it unset —
13
14
  * setting both renders the same time twice.
14
15
  *
16
+ * The dot's `color` types the entry using the shared status-pill palette —
17
+ * `primary` by default, plus `neutral`, `info`, `success`, `warning`, and
18
+ * `danger`.
19
+ *
15
20
  * @element timeline-entry
16
21
  * @slot headline - Optional headline/title for the event.
17
22
  * @slot - The event content; nest any elements here.
@@ -19,6 +24,11 @@ import "./relative-time.js";
19
24
  export declare class TimelineEntry extends LitElement {
20
25
  /** ISO 8601 or SQLite datetime string, rendered as a relative time. */
21
26
  datetime: string | null;
27
+ /**
28
+ * Visual type of the entry's dot, from the shared status-pill palette:
29
+ * `primary` (default), `neutral`, `info`, `success`, `warning`, or `danger`.
30
+ */
31
+ color: StatusPillColor;
22
32
  /** Whether the headline slot currently has assigned content. */
23
33
  private _hasHeadline;
24
34
  static styles: import("lit").CSSResult[];
@@ -1 +1 @@
1
- {"version":3,"file":"timeline-entry.d.ts","sourceRoot":"","sources":["../src/timeline-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAErD,OAAO,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;GAeG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C,uEAAuE;IAC3D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE3C,gEAAgE;IACvD,OAAO,CAAC,YAAY,CAAS;IAEtC,OAAgB,MAAM,4BAgGpB;IAEO,iBAAiB,IAAI,IAAI,CAGjC;IAED,6EAA6E;IAC7E,OAAO,CAAC,qBAAqB;IAIpB,MAAM,yCAqBd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,aAAa,CAAC;KACjC;CACF"}
1
+ {"version":3,"file":"timeline-entry.d.ts","sourceRoot":"","sources":["../src/timeline-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAErD,OAAO,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C,uEAAuE;IAC3D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE3C;;;OAGG;IACS,KAAK,EAAE,eAAe,CAAa;IAE/C,gEAAgE;IACvD,OAAO,CAAC,YAAY,CAAS;IAEtC,OAAgB,MAAM,4BAoHpB;IAEO,iBAAiB,IAAI,IAAI,CAGjC;IAED,6EAA6E;IAC7E,OAAO,CAAC,qBAAqB;IAIpB,MAAM,yCAqBd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,aAAa,CAAC;KACjC;CACF"}
@@ -20,6 +20,10 @@ import { tokens } from "./tokens.js";
20
20
  * timestamp prop (e.g. `chat-message`'s `timestamp`) should leave it unset —
21
21
  * setting both renders the same time twice.
22
22
  *
23
+ * The dot's `color` types the entry using the shared status-pill palette —
24
+ * `primary` by default, plus `neutral`, `info`, `success`, `warning`, and
25
+ * `danger`.
26
+ *
23
27
  * @element timeline-entry
24
28
  * @slot headline - Optional headline/title for the event.
25
29
  * @slot - The event content; nest any elements here.
@@ -29,6 +33,11 @@ let TimelineEntry = class TimelineEntry extends LitElement {
29
33
  super(...arguments);
30
34
  /** ISO 8601 or SQLite datetime string, rendered as a relative time. */
31
35
  this.datetime = null;
36
+ /**
37
+ * Visual type of the entry's dot, from the shared status-pill palette:
38
+ * `primary` (default), `neutral`, `info`, `success`, `warning`, or `danger`.
39
+ */
40
+ this.color = "primary";
32
41
  /** Whether the headline slot currently has assigned content. */
33
42
  this._hasHeadline = false;
34
43
  }
@@ -80,13 +89,33 @@ let TimelineEntry = class TimelineEntry extends LitElement {
80
89
  height: 0.75rem;
81
90
  transform: translateX(-50%);
82
91
  border-radius: 9999px;
83
- /* Same primary-token gradient as map-circle/user-avatar, lighter on top. */
92
+ /* Same lighter-on-top token gradient as map-circle/user-avatar; the
93
+ base color is swapped per the color property via the private
94
+ --_dot var. */
84
95
  background: linear-gradient(
85
96
  to bottom,
86
- color-mix(in srgb, var(--ui-primary, #4f46e5) 70%, #ffffff) 0%,
87
- color-mix(in srgb, var(--ui-primary, #4f46e5) 70%, #000000) 100%
97
+ color-mix(in srgb, var(--_dot, var(--ui-primary, #4f46e5)) 70%, #ffffff) 0%,
98
+ color-mix(in srgb, var(--_dot, var(--ui-primary, #4f46e5)) 70%, #000000) 100%
88
99
  );
89
100
  }
101
+ .dot.neutral {
102
+ --_dot: var(--ui-text-muted, #64748b);
103
+ }
104
+ .dot.info {
105
+ --_dot: var(--ui-info, #0ea5e9);
106
+ }
107
+ .dot.primary {
108
+ --_dot: var(--ui-primary, #4f46e5);
109
+ }
110
+ .dot.success {
111
+ --_dot: var(--ui-success, #16a34a);
112
+ }
113
+ .dot.warning {
114
+ --_dot: var(--ui-warning, #d97706);
115
+ }
116
+ .dot.danger {
117
+ --_dot: var(--ui-danger, #dc2626);
118
+ }
90
119
  :host(:first-child) .line-top {
91
120
  display: none;
92
121
  }
@@ -144,7 +173,7 @@ let TimelineEntry = class TimelineEntry extends LitElement {
144
173
  <div class="rail" aria-hidden="true">
145
174
  <span class="line line-top"></span>
146
175
  <span class="line line-bottom"></span>
147
- <span class="dot"></span>
176
+ <span class="dot ${this.color}"></span>
148
177
  </div>
149
178
  <div class="body">
150
179
  <div class="head">
@@ -164,6 +193,9 @@ let TimelineEntry = class TimelineEntry extends LitElement {
164
193
  __decorate([
165
194
  property()
166
195
  ], TimelineEntry.prototype, "datetime", void 0);
196
+ __decorate([
197
+ property()
198
+ ], TimelineEntry.prototype, "color", void 0);
167
199
  __decorate([
168
200
  state()
169
201
  ], TimelineEntry.prototype, "_hasHeadline", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"timeline-entry.js","sourceRoot":"","sources":["../src/timeline-entry.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;;;;;;GAeG;AAEI,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,UAAU;IAAtC;;QACL,uEAAuE;QAC3D,aAAQ,GAAkB,IAAI,CAAC;QAE3C,gEAAgE;QAC/C,iBAAY,GAAG,KAAK,CAAC;IAoIxC,CAAC;aAlIiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6FF;KACF,AAhGqB,CAgGpB;IAEO,iBAAiB;QACxB,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;YAAE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxE,CAAC;IAED,6EAA6E;IACrE,qBAAqB,CAAC,KAAY;QACxC,IAAI,CAAC,YAAY,GAAI,KAAK,CAAC,MAA0B,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACpG,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA;;;;;;;;;oCASqB,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO;kDAClB,IAAI,CAAC,qBAAqB;;cAE9D,IAAI,CAAC,QAAQ;YACb,CAAC,CAAC,IAAI,CAAA,wCAAwC,IAAI,CAAC,QAAQ,mBAAmB;YAC9E,CAAC,CAAC,OAAO;;;;;KAKlB,CAAC;IACJ,CAAC;CACF,CAAA;AAvIa;IAAX,QAAQ,EAAE;+CAAgC;AAG1B;IAAhB,KAAK,EAAE;mDAA8B;AAL3B,aAAa;IADzB,aAAa,CAAC,gBAAgB,CAAC;GACnB,aAAa,CAyIzB","sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport \"./relative-time.js\";\nimport { tokens } from \"./tokens.js\";\n\n/**\n * One event on a `timeline-container`: a dot on the vertical line, an optional\n * headline, a relative timestamp (\"3 hours ago\"), and freely nested content.\n * The connecting line is drawn here — its segment above the dot is hidden on\n * the first entry and the segment below is hidden on the last, so the line caps\n * exactly at the first and last dots. Only meaningful inside a\n * `timeline-container`; demonstrated through it.\n *\n * `datetime` is the entry's one timestamp. A nested element that has its own\n * timestamp prop (e.g. `chat-message`'s `timestamp`) should leave it unset —\n * setting both renders the same time twice.\n *\n * @element timeline-entry\n * @slot headline - Optional headline/title for the event.\n * @slot - The event content; nest any elements here.\n */\n@customElement(\"timeline-entry\")\nexport class TimelineEntry extends LitElement {\n /** ISO 8601 or SQLite datetime string, rendered as a relative time. */\n @property() datetime: string | null = null;\n\n /** Whether the headline slot currently has assigned content. */\n @state() private _hasHeadline = false;\n\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n }\n .entry {\n display: flex;\n gap: 0.75rem;\n }\n .rail {\n position: relative;\n flex: 0 0 auto;\n width: 0.75rem;\n }\n .line {\n position: absolute;\n left: 50%;\n width: 2px;\n transform: translateX(-50%);\n background: var(--ui-border, #e2e8f0);\n }\n .line-top {\n top: 0;\n height: 0.5rem;\n }\n .line-bottom {\n top: 0.5rem;\n bottom: 0;\n }\n .dot {\n position: absolute;\n top: 0.125rem;\n left: 50%;\n width: 0.75rem;\n height: 0.75rem;\n transform: translateX(-50%);\n border-radius: 9999px;\n /* Same primary-token gradient as map-circle/user-avatar, lighter on top. */\n background: linear-gradient(\n to bottom,\n color-mix(in srgb, var(--ui-primary, #4f46e5) 70%, #ffffff) 0%,\n color-mix(in srgb, var(--ui-primary, #4f46e5) 70%, #000000) 100%\n );\n }\n :host(:first-child) .line-top {\n display: none;\n }\n :host(:last-child) .line-bottom {\n display: none;\n }\n .body {\n flex: 1 1 auto;\n min-width: 0;\n padding-bottom: 1.5rem;\n }\n :host(:last-child) .body {\n padding-bottom: 0;\n }\n .head {\n display: flex;\n align-items: baseline;\n gap: 0.5rem;\n flex-wrap: wrap;\n }\n .headline {\n font-weight: var(--ui-font-weight-semibold, 600);\n font-size: var(--ui-font-size, 0.875rem);\n line-height: var(--ui-line-height-tight, 1.25);\n color: var(--ui-text, #0f172a);\n }\n .headline.empty {\n display: none;\n }\n .time {\n font-size: var(--ui-font-size-sm, 0.75rem);\n line-height: var(--ui-line-height-tight, 1.25);\n color: var(--ui-text-muted, #64748b);\n }\n .content {\n margin-top: 0.25rem;\n font-size: var(--ui-font-size, 0.875rem);\n line-height: var(--ui-line-height-normal, 1.5);\n color: var(--ui-text, #0f172a);\n }\n `,\n ];\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (!this.hasAttribute(\"role\")) this.setAttribute(\"role\", \"listitem\");\n }\n\n /** Collapses the headline when nothing is slotted so the time sits alone. */\n private _onHeadlineSlotChange(event: Event): void {\n this._hasHeadline = (event.target as HTMLSlotElement).assignedNodes({ flatten: true }).length > 0;\n }\n\n override render() {\n return html`\n <div class=\"entry\">\n <div class=\"rail\" aria-hidden=\"true\">\n <span class=\"line line-top\"></span>\n <span class=\"line line-bottom\"></span>\n <span class=\"dot\"></span>\n </div>\n <div class=\"body\">\n <div class=\"head\">\n <span class=\"headline ${this._hasHeadline ? \"\" : \"empty\"}\">\n <slot name=\"headline\" @slotchange=${this._onHeadlineSlotChange}></slot>\n </span>\n ${this.datetime\n ? html`<relative-time class=\"time\" datetime=${this.datetime}></relative-time>`\n : nothing}\n </div>\n <div class=\"content\"><slot></slot></div>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"timeline-entry\": TimelineEntry;\n }\n}\n"]}
1
+ {"version":3,"file":"timeline-entry.js","sourceRoot":"","sources":["../src/timeline-entry.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC;;;;;;;;;;;;;;;;;;;GAmBG;AAEI,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,UAAU;IAAtC;;QACL,uEAAuE;QAC3D,aAAQ,GAAkB,IAAI,CAAC;QAE3C;;;WAGG;QACS,UAAK,GAAoB,SAAS,CAAC;QAE/C,gEAAgE;QAC/C,iBAAY,GAAG,KAAK,CAAC;IAwJxC,CAAC;aAtJiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAiHF;KACF,AApHqB,CAoHpB;IAEO,iBAAiB;QACxB,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;YAAE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxE,CAAC;IAED,6EAA6E;IACrE,qBAAqB,CAAC,KAAY;QACxC,IAAI,CAAC,YAAY,GAAI,KAAK,CAAC,MAA0B,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACpG,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA;;;;;6BAKc,IAAI,CAAC,KAAK;;;;oCAIH,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO;kDAClB,IAAI,CAAC,qBAAqB;;cAE9D,IAAI,CAAC,QAAQ;YACb,CAAC,CAAC,IAAI,CAAA,wCAAwC,IAAI,CAAC,QAAQ,mBAAmB;YAC9E,CAAC,CAAC,OAAO;;;;;KAKlB,CAAC;IACJ,CAAC;CACF,CAAA;AAjKa;IAAX,QAAQ,EAAE;+CAAgC;AAM/B;IAAX,QAAQ,EAAE;4CAAoC;AAG9B;IAAhB,KAAK,EAAE;mDAA8B;AAX3B,aAAa;IADzB,aAAa,CAAC,gBAAgB,CAAC;GACnB,aAAa,CAmKzB","sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport \"./relative-time.js\";\nimport { tokens } from \"./tokens.js\";\nimport type { StatusPillColor } from \"./status-pill.js\";\n\n/**\n * One event on a `timeline-container`: a dot on the vertical line, an optional\n * headline, a relative timestamp (\"3 hours ago\"), and freely nested content.\n * The connecting line is drawn here — its segment above the dot is hidden on\n * the first entry and the segment below is hidden on the last, so the line caps\n * exactly at the first and last dots. Only meaningful inside a\n * `timeline-container`; demonstrated through it.\n *\n * `datetime` is the entry's one timestamp. A nested element that has its own\n * timestamp prop (e.g. `chat-message`'s `timestamp`) should leave it unset —\n * setting both renders the same time twice.\n *\n * The dot's `color` types the entry using the shared status-pill palette —\n * `primary` by default, plus `neutral`, `info`, `success`, `warning`, and\n * `danger`.\n *\n * @element timeline-entry\n * @slot headline - Optional headline/title for the event.\n * @slot - The event content; nest any elements here.\n */\n@customElement(\"timeline-entry\")\nexport class TimelineEntry extends LitElement {\n /** ISO 8601 or SQLite datetime string, rendered as a relative time. */\n @property() datetime: string | null = null;\n\n /**\n * Visual type of the entry's dot, from the shared status-pill palette:\n * `primary` (default), `neutral`, `info`, `success`, `warning`, or `danger`.\n */\n @property() color: StatusPillColor = \"primary\";\n\n /** Whether the headline slot currently has assigned content. */\n @state() private _hasHeadline = false;\n\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n }\n .entry {\n display: flex;\n gap: 0.75rem;\n }\n .rail {\n position: relative;\n flex: 0 0 auto;\n width: 0.75rem;\n }\n .line {\n position: absolute;\n left: 50%;\n width: 2px;\n transform: translateX(-50%);\n background: var(--ui-border, #e2e8f0);\n }\n .line-top {\n top: 0;\n height: 0.5rem;\n }\n .line-bottom {\n top: 0.5rem;\n bottom: 0;\n }\n .dot {\n position: absolute;\n top: 0.125rem;\n left: 50%;\n width: 0.75rem;\n height: 0.75rem;\n transform: translateX(-50%);\n border-radius: 9999px;\n /* Same lighter-on-top token gradient as map-circle/user-avatar; the\n base color is swapped per the color property via the private\n --_dot var. */\n background: linear-gradient(\n to bottom,\n color-mix(in srgb, var(--_dot, var(--ui-primary, #4f46e5)) 70%, #ffffff) 0%,\n color-mix(in srgb, var(--_dot, var(--ui-primary, #4f46e5)) 70%, #000000) 100%\n );\n }\n .dot.neutral {\n --_dot: var(--ui-text-muted, #64748b);\n }\n .dot.info {\n --_dot: var(--ui-info, #0ea5e9);\n }\n .dot.primary {\n --_dot: var(--ui-primary, #4f46e5);\n }\n .dot.success {\n --_dot: var(--ui-success, #16a34a);\n }\n .dot.warning {\n --_dot: var(--ui-warning, #d97706);\n }\n .dot.danger {\n --_dot: var(--ui-danger, #dc2626);\n }\n :host(:first-child) .line-top {\n display: none;\n }\n :host(:last-child) .line-bottom {\n display: none;\n }\n .body {\n flex: 1 1 auto;\n min-width: 0;\n padding-bottom: 1.5rem;\n }\n :host(:last-child) .body {\n padding-bottom: 0;\n }\n .head {\n display: flex;\n align-items: baseline;\n gap: 0.5rem;\n flex-wrap: wrap;\n }\n .headline {\n font-weight: var(--ui-font-weight-semibold, 600);\n font-size: var(--ui-font-size, 0.875rem);\n line-height: var(--ui-line-height-tight, 1.25);\n color: var(--ui-text, #0f172a);\n }\n .headline.empty {\n display: none;\n }\n .time {\n font-size: var(--ui-font-size-sm, 0.75rem);\n line-height: var(--ui-line-height-tight, 1.25);\n color: var(--ui-text-muted, #64748b);\n }\n .content {\n margin-top: 0.25rem;\n font-size: var(--ui-font-size, 0.875rem);\n line-height: var(--ui-line-height-normal, 1.5);\n color: var(--ui-text, #0f172a);\n }\n `,\n ];\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (!this.hasAttribute(\"role\")) this.setAttribute(\"role\", \"listitem\");\n }\n\n /** Collapses the headline when nothing is slotted so the time sits alone. */\n private _onHeadlineSlotChange(event: Event): void {\n this._hasHeadline = (event.target as HTMLSlotElement).assignedNodes({ flatten: true }).length > 0;\n }\n\n override render() {\n return html`\n <div class=\"entry\">\n <div class=\"rail\" aria-hidden=\"true\">\n <span class=\"line line-top\"></span>\n <span class=\"line line-bottom\"></span>\n <span class=\"dot ${this.color}\"></span>\n </div>\n <div class=\"body\">\n <div class=\"head\">\n <span class=\"headline ${this._hasHeadline ? \"\" : \"empty\"}\">\n <slot name=\"headline\" @slotchange=${this._onHeadlineSlotChange}></slot>\n </span>\n ${this.datetime\n ? html`<relative-time class=\"time\" datetime=${this.datetime}></relative-time>`\n : nothing}\n </div>\n <div class=\"content\"><slot></slot></div>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"timeline-entry\": TimelineEntry;\n }\n}\n"]}
@@ -20,7 +20,7 @@ import "@f-ewald/components/timeline-container.js";
20
20
  <span slot="headline">Deployment started</span>
21
21
  Release v1.4.0 is rolling out.
22
22
  </timeline-entry>
23
- <timeline-entry datetime="2026-07-23T08:45:00Z">
23
+ <timeline-entry datetime="2026-07-23T08:45:00Z" color="success">
24
24
  <span slot="headline">Review approved</span>
25
25
  <status-pill label="In Review" color="info"></status-pill>
26
26
  </timeline-entry>
@@ -11,6 +11,10 @@ exactly at the first and last dots. Only meaningful inside a
11
11
  timestamp prop (e.g. `chat-message`'s `timestamp`) should leave it unset —
12
12
  setting both renders the same time twice.
13
13
 
14
+ The dot's `color` types the entry using the shared status-pill palette —
15
+ `primary` by default, plus `neutral`, `info`, `success`, `warning`, and
16
+ `danger`.
17
+
14
18
  ## Install
15
19
 
16
20
  ```js
@@ -20,9 +24,9 @@ import "@f-ewald/components/timeline-entry.js";
20
24
  ## Usage
21
25
 
22
26
  ```html
23
- <timeline-entry datetime="2026-07-23T09:00:00Z">
24
- <span slot="headline">Deployment started</span>
25
- Release v1.4.0 is rolling out to production.
27
+ <timeline-entry datetime="2026-07-23T09:00:00Z" color="danger">
28
+ <span slot="headline">Build failed</span>
29
+ The release pipeline halted on the test stage.
26
30
  </timeline-entry>
27
31
  ```
28
32
 
@@ -31,6 +35,7 @@ import "@f-ewald/components/timeline-entry.js";
31
35
  | Property | Attribute | Type | Default | Description |
32
36
  | --- | --- | --- | --- | --- |
33
37
  | `datetime` | `datetime` | `string | null` | `null` | ISO 8601 or SQLite datetime string, rendered as a relative time. |
38
+ | `color` | `color` | `StatusPillColor` | `"primary"` | Visual type of the entry's dot, from the shared status-pill palette: `primary` (default), `neutral`, `info`, `success`, `warning`, or `danger`. |
34
39
 
35
40
  ## Events
36
41
 
@@ -45,12 +50,16 @@ _None._
45
50
  | Custom property |
46
51
  | --- |
47
52
  | `--ui-border` |
53
+ | `--ui-danger` |
48
54
  | `--ui-font` |
49
55
  | `--ui-font-size` |
50
56
  | `--ui-font-size-sm` |
51
57
  | `--ui-font-weight-semibold` |
58
+ | `--ui-info` |
52
59
  | `--ui-line-height-normal` |
53
60
  | `--ui-line-height-tight` |
54
61
  | `--ui-primary` |
62
+ | `--ui-success` |
55
63
  | `--ui-text` |
56
64
  | `--ui-text-muted` |
65
+ | `--ui-warning` |
package/llms.txt CHANGED
@@ -1341,7 +1341,7 @@ Example:
1341
1341
  <span slot="headline">Deployment started</span>
1342
1342
  Release v1.4.0 is rolling out.
1343
1343
  </timeline-entry>
1344
- <timeline-entry datetime="2026-07-23T08:45:00Z">
1344
+ <timeline-entry datetime="2026-07-23T08:45:00Z" color="success">
1345
1345
  <span slot="headline">Review approved</span>
1346
1346
  <status-pill label="In Review" color="info"></status-pill>
1347
1347
  </timeline-entry>
@@ -1365,17 +1365,21 @@ exactly at the first and last dots. Only meaningful inside a
1365
1365
  timestamp prop (e.g. `chat-message`'s `timestamp`) should leave it unset —
1366
1366
  setting both renders the same time twice.
1367
1367
 
1368
+ The dot's `color` types the entry using the shared status-pill palette —
1369
+ `primary` by default, plus `neutral`, `info`, `success`, `warning`, and
1370
+ `danger`.
1371
+
1368
1372
  Import: `import "@f-ewald/components/timeline-entry.js";`
1369
1373
 
1370
- Properties: `datetime` (attribute `datetime`) : string | null, default null
1374
+ Properties: `datetime` (attribute `datetime`) : string | null, default null; `color` (attribute `color`) : StatusPillColor, default "primary"
1371
1375
  Events: none
1372
- 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`
1376
+ CSS custom properties: `--ui-border`, `--ui-danger`, `--ui-font`, `--ui-font-size`, `--ui-font-size-sm`, `--ui-font-weight-semibold`, `--ui-info`, `--ui-line-height-normal`, `--ui-line-height-tight`, `--ui-primary`, `--ui-success`, `--ui-text`, `--ui-text-muted`, `--ui-warning`
1373
1377
 
1374
1378
  Example:
1375
1379
  ```html
1376
- <timeline-entry datetime="2026-07-23T09:00:00Z">
1377
- <span slot="headline">Deployment started</span>
1378
- Release v1.4.0 is rolling out to production.
1380
+ <timeline-entry datetime="2026-07-23T09:00:00Z" color="danger">
1381
+ <span slot="headline">Build failed</span>
1382
+ The release pipeline halted on the test stage.
1379
1383
  </timeline-entry>
1380
1384
  ```
1381
1385
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@f-ewald/components",
3
3
  "private": false,
4
- "version": "1.6.0",
4
+ "version": "1.7.0",
5
5
  "description": "A collection of universally usable web components for various tasks.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",