@htmlbricks/hb-messages-topics-card 0.71.35 → 0.71.37

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.
package/README.md CHANGED
@@ -1,49 +1,137 @@
1
- # hb-messages-topics-card
1
+ # `hb-messages-topics-card`
2
+
3
+ **Category:** messaging · **Tags:** messaging, chat · **Package:** `@htmlbricks/hb-messages-topics-card`
2
4
 
3
5
  ## Description
4
6
 
5
- Lists chat or channel previews from `chats`: avatar, title, last message snippet, derived time label, and unread `counter` as a Bulma tag. Clicking a row marks it selected (`_selected`) and dispatches `select` with that chat payload for opening a thread or switching context.
7
+ Renders a vertical list of chat or channel previews from a **`chats`** collection. Each row shows a rounded avatar, a title, a short message preview, a time label, and an unread counter rendered as a Bulma tag. Clicking a row updates internal selection state (`_selected`), highlights the row, and dispatches a **`select`** custom event with the clicked chat object so the host can open a thread or switch context.
6
8
 
7
9
  ## Styling (Bulma)
8
10
 
9
- The component bundles **Bulma 1.x** in the shadow root: **`elements/tag`** (unread counter), with theme defaults on `:host` (`--bulma-hb-def-*`). Set public **`--bulma-*`** on `body` or `:root` so they inherit onto the host. Row hover and selected backgrounds default from **`--bulma-scheme-main-bis`** and **`--bulma-scheme-main-ter`**; override with **`--hb-topics-card-hover-background-color`** and **`--hb-topics-card-selected-background-color`** if needed. See [Bulma CSS variables](https://bulma.io/documentation/features/css-variables/).
11
+ The component bundles **Bulma 1.x** inside the shadow root: **`layout/media`**, **`layout/level`**, **`elements/image`**, **`elements/tag`**, and typography / spacing helpers, with the light theme applied on `:host`. Public **`--bulma-*`** variables can be set on `body`, `:root`, or the host so they cascade consistently with the rest of the app see [Bulma CSS variables](https://bulma.io/documentation/features/css-variables/) and the `styleSetup.vars` entries in `extra/docs.ts`.
12
+
13
+ | Variable | Purpose |
14
+ |----------|---------|
15
+ | `--bulma-text` | Title and preview snippet text. |
16
+ | `--bulma-text-strong` | Strong title weight color (falls back to `--bulma-text`). |
17
+ | `--bulma-text-weak` | Muted time label beside each preview. |
18
+ | `--bulma-border` | Divider between rows. |
19
+ | `--bulma-scheme-main-bis` | Hover background for rows that are not selected. |
20
+ | `--bulma-scheme-main-ter` | Selected row background. |
21
+ | `--bulma-radius-rounded` | Pill shape for the unread counter tag. |
10
22
 
11
23
  **Shadow markup (simplified):**
12
24
 
13
- - **`div.grid`** — one row per chat (click selects).
14
- - **`img`**, **`div.header`** (title + time), **`div.details`** (snippet + **`span.tag.is-light.is-rounded`** counter).
25
+ - **`article.media.hb-topics-item`** — clickable row; **`hb-topics-item--selected`** when that chat is selected.
26
+ - **`figure.media-left`** + **`p.image.is-64x64`** + **`img.is-rounded`** — avatar from `img_uri`.
27
+ - **`div.media-content`** — Bulma **`level`** rows for title + time, then preview + counter tag.
28
+
29
+ ## CSS parts
30
+
31
+ None.
32
+
33
+ ## HTML slots
34
+
35
+ None.
36
+
37
+ ## Custom element
38
+
39
+ `hb-messages-topics-card`
40
+
41
+ ## Attributes (snake_case; string values in HTML)
42
+
43
+ Per the web component contract, attributes are strings. The primary payload is JSON on **`chats`**.
44
+
45
+ | Attribute | Required | Description |
46
+ |-----------|----------|-------------|
47
+ | `id` | No | Optional host identifier. |
48
+ | `style` | No | Optional inline host styles (typed on the component surface). |
49
+ | `chats` | No* | JSON string: array of chat objects (`IChat[]`). Defaults to an empty list if omitted. |
50
+
51
+ \* In markup you may omit **`chats`** until you set the attribute; the component defaults to an empty list.
52
+
53
+ ### `chats` JSON shape (`IChat`)
54
+
55
+ Fields used for layout and labels in the current implementation:
56
+
57
+ | Field | Role |
58
+ |-------|------|
59
+ | `chat_id` | Stable key for each row (also used in `{#each}` keyed updates). |
60
+ | `title` | Primary line (semibold). |
61
+ | `text` | Preview line under the title. |
62
+ | `img_uri` | Avatar URL (`img` `src`). |
63
+ | `time` | Source for the time label when `localeTimeString` is not set; use an **ISO 8601** string in JSON so it parses as a date. |
64
+ | `localeTimeString` | If set, shown as-is instead of deriving `HH:MM` from `time`. |
65
+ | `counter` | Unread count; rendered in the tag (missing or falsy shows **`0`**). |
66
+ | `_selected` | When `true`, that row starts selected and receives the selected background. |
15
67
 
16
- **Host-level tokens (existing):** `--hb-topics-card-size`, `--hb-topics-card-padding`, derived `--hb-topics-card-double-*`, plus the selected/hover background variables above.
68
+ Additional optional fields (`is_group`, `chat_name`, `chat_img`, `last_message_*`, and so on) are part of the **`IChat`** type so you can carry richer metadata; they are not read by the template today but are still present on objects emitted by **`select`**.
69
+
70
+ If the **`chats`** prop arrives as a string (for example from an HTML attribute), the component parses it with **`JSON.parse`**; invalid JSON is logged to the console and parsing is skipped.
71
+
72
+ ## Events
73
+
74
+ | Event | `detail` |
75
+ |-------|----------|
76
+ | `select` | The clicked **`IChat`** object (same reference the list uses after selection is updated). |
77
+
78
+ Listen in plain JavaScript:
79
+
80
+ ```javascript
81
+ const el = document.querySelector("hb-messages-topics-card");
82
+ el.addEventListener("select", (e) => {
83
+ const chat = e.detail;
84
+ console.log(chat.chat_id, chat.title);
85
+ });
86
+ ```
87
+
88
+ ## Usage notes
89
+
90
+ - **Initial selection:** set **`_selected`** on at most one item in the JSON if you want a default active row.
91
+ - **Time display:** without **`localeTimeString`**, the component fills it from **`time`** using the **local** hours and minutes (`HH:MM`). Provide **`localeTimeString`** yourself for relative times or locale-specific formatting.
92
+ - **Unread badge:** the tag always shows a value; **`0`** is shown when there is no positive counter.
93
+ - **Avatars:** the template sets **`alt=""`** on images; if you need accessible names, extend your integration (for example wrapping context or contributing upstream) because the component does not derive labels from `title` today.
17
94
 
18
95
  ## Types
19
96
 
20
97
  ```typescript
21
98
  export type IChat = {
22
- time: Date;
23
- title: string;
24
- text: string;
25
- img_uri: string;
26
- is_group?: boolean;
27
- chat_name?: string;
28
- chat_img?: string;
29
- chat_id: string;
30
- last_message_author?: string;
31
- last_message_author_img?: string;
32
- last_message_time?: Date;
33
- last_message_text?: string;
34
- counter?: number;
35
- localeTimeString?: string;
36
- _selected?: boolean;
99
+ time: Date;
100
+ title: string;
101
+ text: string;
102
+ img_uri: string;
103
+ is_group?: boolean;
104
+ chat_name?: string;
105
+ chat_img?: string;
106
+ chat_id: string;
107
+ last_message_author?: string;
108
+ last_message_author_img?: string;
109
+ last_message_time?: Date;
110
+ last_message_text?: string;
111
+ counter?: number;
112
+ localeTimeString?: string;
113
+ _selected?: boolean;
37
114
  };
38
115
 
39
116
  export type Component = {
40
- id?: string;
41
- style?: string;
42
-
43
- chats: IChat[];
117
+ id?: string;
118
+ style?: string;
119
+ chats?: IChat[];
44
120
  };
45
121
 
46
122
  export type Events = {
47
- select: IChat;
123
+ select: IChat;
48
124
  };
49
125
  ```
126
+
127
+ ## Minimal HTML example
128
+
129
+ ```html
130
+ <hb-messages-topics-card
131
+ chats='[{"chat_id":"1","title":"Team","text":"Hello","time":"2026-01-01T12:00:00.000Z","img_uri":"https://example.com/a.png","counter":2}]'
132
+ ></hb-messages-topics-card>
133
+ ```
134
+
135
+ ## Storybook / metadata
136
+
137
+ Argument controls and additional named examples (selected row, unread badges, single chat) live in `extra/docs.ts`.
package/manifest.json CHANGED
@@ -86,6 +86,7 @@
86
86
  "additionalProperties": false,
87
87
  "properties": {
88
88
  "chats": {
89
+ "description": "Parsed from a JSON attribute when omitted in HTML.",
89
90
  "items": {
90
91
  "$ref": "#/definitions/IChat"
91
92
  },
@@ -98,9 +99,6 @@
98
99
  "type": "string"
99
100
  }
100
101
  },
101
- "required": [
102
- "chats"
103
- ],
104
102
  "type": "object"
105
103
  },
106
104
  "IChat": {
@@ -183,67 +181,43 @@
183
181
  "name": "--bulma-text",
184
182
  "valueType": "color",
185
183
  "defaultValue": "#363636",
186
- "description": "Body and description text."
184
+ "description": "Title and preview snippet text."
187
185
  },
188
186
  {
189
187
  "name": "--bulma-text-strong",
190
188
  "valueType": "color",
191
189
  "defaultValue": "#363636",
192
- "description": "Title emphasis (falls back to `--bulma-text`)."
190
+ "description": "Strong title weight color (falls back to `--bulma-text`)."
193
191
  },
194
192
  {
195
193
  "name": "--bulma-text-weak",
196
194
  "valueType": "color",
197
195
  "defaultValue": "#7a7a7a",
198
- "description": "Muted time label."
196
+ "description": "Muted foreground for the timestamp or relative time shown beside each chat preview."
197
+ },
198
+ {
199
+ "name": "--bulma-border",
200
+ "valueType": "color",
201
+ "defaultValue": "#dbdbdb",
202
+ "description": "Row divider between chat previews."
199
203
  },
200
204
  {
201
205
  "name": "--bulma-scheme-main-bis",
202
206
  "valueType": "color",
203
- "defaultValue": "hsl(0, 0%, 98%)",
204
- "description": "Hover row background (default for `--hb-topics-card-hover-background-color`)."
207
+ "defaultValue": "#fafafa",
208
+ "description": "Hover background for non-selected rows."
205
209
  },
206
210
  {
207
211
  "name": "--bulma-scheme-main-ter",
208
212
  "valueType": "color",
209
- "defaultValue": "hsl(0, 0%, 96%)",
210
- "description": "Selected row background (default for `--hb-topics-card-selected-background-color`)."
213
+ "defaultValue": "#f5f5f5",
214
+ "description": "Selected row background."
211
215
  },
212
216
  {
213
217
  "name": "--bulma-radius-rounded",
214
218
  "valueType": "number",
215
219
  "defaultValue": "9999px",
216
220
  "description": "Pill shape for the unread counter tag."
217
- },
218
- {
219
- "name": "--hb-topics-card-double-padding",
220
- "valueType": "string",
221
- "defaultValue": ""
222
- },
223
- {
224
- "name": "--hb-topics-card-double-size",
225
- "valueType": "number",
226
- "defaultValue": ""
227
- },
228
- {
229
- "name": "--hb-topics-card-hover-background-color",
230
- "valueType": "color",
231
- "defaultValue": ""
232
- },
233
- {
234
- "name": "--hb-topics-card-padding",
235
- "valueType": "string",
236
- "defaultValue": ""
237
- },
238
- {
239
- "name": "--hb-topics-card-selected-background-color",
240
- "valueType": "color",
241
- "defaultValue": ""
242
- },
243
- {
244
- "name": "--hb-topics-card-size",
245
- "valueType": "number",
246
- "defaultValue": ""
247
221
  }
248
222
  ],
249
223
  "parts": []
@@ -261,7 +235,7 @@
261
235
  "counter": 0,
262
236
  "text": "Hello 0",
263
237
  "title": "Hello0",
264
- "time": "2026-04-16T23:22:53.482Z",
238
+ "time": "2026-04-17T00:28:42.015Z",
265
239
  "img_uri": "https://www.w3schools.com/howto/img_avatar.png"
266
240
  },
267
241
  {
@@ -269,7 +243,7 @@
269
243
  "counter": 0,
270
244
  "text": "Hello 1",
271
245
  "title": "Hello1",
272
- "time": "2026-04-16T23:22:53.482Z",
246
+ "time": "2026-04-17T00:28:42.015Z",
273
247
  "img_uri": "https://www.w3schools.com/howto/img_avatar.png"
274
248
  },
275
249
  {
@@ -277,7 +251,7 @@
277
251
  "counter": 0,
278
252
  "text": "Hello 2",
279
253
  "title": "Hello2",
280
- "time": "2026-04-16T23:22:53.482Z",
254
+ "time": "2026-04-17T00:28:42.015Z",
281
255
  "img_uri": "https://www.w3schools.com/howto/img_avatar.png"
282
256
  }
283
257
  ]
@@ -292,7 +266,7 @@
292
266
  "counter": 0,
293
267
  "text": "Hello 0",
294
268
  "title": "Hello0",
295
- "time": "2026-04-16T23:22:53.482Z",
269
+ "time": "2026-04-17T00:28:42.015Z",
296
270
  "img_uri": "https://www.w3schools.com/howto/img_avatar.png"
297
271
  },
298
272
  {
@@ -300,7 +274,7 @@
300
274
  "counter": 0,
301
275
  "text": "Hello 1",
302
276
  "title": "Hello1",
303
- "time": "2026-04-16T23:22:53.482Z",
277
+ "time": "2026-04-17T00:28:42.015Z",
304
278
  "img_uri": "https://www.w3schools.com/howto/img_avatar.png",
305
279
  "_selected": true
306
280
  },
@@ -309,7 +283,7 @@
309
283
  "counter": 0,
310
284
  "text": "Hello 2",
311
285
  "title": "Hello2",
312
- "time": "2026-04-16T23:22:53.482Z",
286
+ "time": "2026-04-17T00:28:42.015Z",
313
287
  "img_uri": "https://www.w3schools.com/howto/img_avatar.png"
314
288
  }
315
289
  ]
@@ -325,7 +299,7 @@
325
299
  "counter": 3,
326
300
  "text": "Can you review the PR?",
327
301
  "title": "Engineering",
328
- "time": "2026-04-16T23:22:53.482Z",
302
+ "time": "2026-04-17T00:28:42.015Z",
329
303
  "img_uri": "https://www.w3schools.com/howto/img_avatar.png"
330
304
  },
331
305
  {
@@ -333,7 +307,7 @@
333
307
  "counter": 12,
334
308
  "text": "Contract signed",
335
309
  "title": "Sales",
336
- "time": "2026-04-16T23:22:53.482Z",
310
+ "time": "2026-04-17T00:28:42.015Z",
337
311
  "img_uri": "https://www.w3schools.com/howto/img_avatar.png"
338
312
  },
339
313
  {
@@ -341,7 +315,7 @@
341
315
  "counter": 1,
342
316
  "text": "Ticket #4421 updated",
343
317
  "title": "Support",
344
- "time": "2026-04-16T23:22:53.482Z",
318
+ "time": "2026-04-17T00:28:42.015Z",
345
319
  "img_uri": "https://www.w3schools.com/howto/img_avatar.png"
346
320
  }
347
321
  ]
@@ -357,7 +331,7 @@
357
331
  "counter": 0,
358
332
  "text": "Only conversation in the list",
359
333
  "title": "Direct message",
360
- "time": "2026-04-16T23:22:53.482Z",
334
+ "time": "2026-04-17T00:28:42.015Z",
361
335
  "img_uri": "https://www.w3schools.com/howto/img_avatar.png",
362
336
  "_selected": true
363
337
  }
@@ -386,5 +360,5 @@
386
360
  "size": {},
387
361
  "iifePath": "main.iife.js",
388
362
  "repoName": "@htmlbricks/hb-messages-topics-card",
389
- "version": "0.71.35"
363
+ "version": "0.71.37"
390
364
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htmlbricks/hb-messages-topics-card",
3
- "version": "0.71.35",
3
+ "version": "0.71.37",
4
4
  "contributors": [],
5
5
  "description": "Lists chat or channel previews from `chats`: avatar, title, last message snippet, derived time label, and unread `counter` badge. Clicking a row marks it selected (`_selected`) and dispatches `select` with that chat payload for opening a thread or switching context.",
6
6
  "licenses": [
@@ -6,6 +6,7 @@
6
6
  "additionalProperties": false,
7
7
  "properties": {
8
8
  "chats": {
9
+ "description": "Parsed from a JSON attribute when omitted in HTML.",
9
10
  "items": {
10
11
  "$ref": "#/definitions/IChat"
11
12
  },
@@ -18,9 +19,6 @@
18
19
  "type": "string"
19
20
  }
20
21
  },
21
- "required": [
22
- "chats"
23
- ],
24
22
  "type": "object"
25
23
  },
26
24
  "IChat": {
@@ -19,8 +19,8 @@ export type IChat = {
19
19
  export type Component = {
20
20
  id?: string;
21
21
  style?: string;
22
-
23
- chats: IChat[];
22
+ /** Parsed from a JSON attribute when omitted in HTML. */
23
+ chats?: IChat[];
24
24
  };
25
25
 
26
26
  export type Events = {