@felloinnovations/brand-kit 0.5.1 → 0.5.3

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 (104) hide show
  1. package/AGENTS.md +29 -9
  2. package/CHANGELOG.md +86 -0
  3. package/README.md +10 -4
  4. package/design-system/01-how-claude-decides.md +5 -3
  5. package/design-system/03-colour.md +19 -1
  6. package/design-system/05-space-and-layout.md +2 -1
  7. package/design-system/08-choosing-components.md +20 -4
  8. package/design-system/09-charts.md +6 -3
  9. package/design-system/11-page-recipes.md +40 -1
  10. package/design-system/13-motion.md +1 -1
  11. package/design-system/15-ai-experiences.md +11 -0
  12. package/design-system/17-decisions.md +41 -0
  13. package/design-system/components/AppShell/README.md +89 -21
  14. package/design-system/components/AppShell/preview.html +148 -3
  15. package/design-system/components/AppShell/style.css +47 -0
  16. package/design-system/components/Avatar/README.md +6 -3
  17. package/design-system/components/Avatar/preview.html +2 -1
  18. package/design-system/components/Avatar/style.css +3 -0
  19. package/design-system/components/Banner/README.md +9 -5
  20. package/design-system/components/Banner/preview.html +9 -0
  21. package/design-system/components/Banner/style.css +3 -0
  22. package/design-system/components/Button/README.md +29 -2
  23. package/design-system/components/Button/preview.html +33 -1
  24. package/design-system/components/Button/style.css +21 -0
  25. package/design-system/components/Calendar/README.md +148 -0
  26. package/design-system/components/Calendar/preview.html +449 -0
  27. package/design-system/components/Calendar/style.css +61 -0
  28. package/design-system/components/Card/README.md +13 -0
  29. package/design-system/components/Card/preview.html +23 -0
  30. package/design-system/components/Card/style.css +19 -0
  31. package/design-system/components/ChatCard/README.md +74 -3
  32. package/design-system/components/ChatCard/preview.html +126 -25
  33. package/design-system/components/ChatCard/style.css +6 -0
  34. package/design-system/components/Chip/README.md +16 -7
  35. package/design-system/components/Chip/preview.html +25 -1
  36. package/design-system/components/Chip/style.css +5 -0
  37. package/design-system/components/Combobox/README.md +10 -4
  38. package/design-system/components/Combobox/preview.html +19 -4
  39. package/design-system/components/Combobox/style.css +7 -1
  40. package/design-system/components/CommentThread/README.md +138 -0
  41. package/design-system/components/CommentThread/preview.html +134 -0
  42. package/design-system/components/CommentThread/style.css +41 -0
  43. package/design-system/components/DateInput/README.md +38 -4
  44. package/design-system/components/DateInput/preview.html +50 -2
  45. package/design-system/components/DateInput/style.css +6 -0
  46. package/design-system/components/Dialog/README.md +26 -3
  47. package/design-system/components/Dialog/preview.html +80 -0
  48. package/design-system/components/Dialog/style.css +28 -3
  49. package/design-system/components/EmptyState/README.md +1 -1
  50. package/design-system/components/Fold/README.md +21 -0
  51. package/design-system/components/Fold/preview.html +44 -1
  52. package/design-system/components/Fold/style.css +30 -0
  53. package/design-system/components/InlineEdit/README.md +116 -0
  54. package/design-system/components/InlineEdit/preview.html +135 -0
  55. package/design-system/components/InlineEdit/style.css +34 -0
  56. package/design-system/components/Input/README.md +20 -1
  57. package/design-system/components/Input/preview.html +24 -0
  58. package/design-system/components/Input/style.css +13 -1
  59. package/design-system/components/KanbanBoard/README.md +68 -4
  60. package/design-system/components/KanbanBoard/preview.html +129 -0
  61. package/design-system/components/KanbanBoard/style.css +31 -0
  62. package/design-system/components/PlanTimeline/README.md +144 -0
  63. package/design-system/components/PlanTimeline/preview.html +109 -0
  64. package/design-system/components/PlanTimeline/style.css +64 -0
  65. package/design-system/components/README.md +11 -6
  66. package/design-system/components/Skeleton/README.md +66 -2
  67. package/design-system/components/Skeleton/preview.html +83 -1
  68. package/design-system/components/Starter/README.md +1 -1
  69. package/design-system/components/Starter/preview.html +1 -1
  70. package/design-system/components/Stepper/README.md +81 -5
  71. package/design-system/components/Stepper/preview.html +64 -1
  72. package/design-system/components/Stepper/style.css +29 -0
  73. package/design-system/components/StreakCalendar/README.md +1 -0
  74. package/design-system/components/Table/README.md +7 -3
  75. package/design-system/components/Table/preview.html +15 -0
  76. package/design-system/components/Table/style.css +2 -0
  77. package/design-system/components/TextDiff/README.md +96 -0
  78. package/design-system/components/TextDiff/preview.html +42 -0
  79. package/design-system/components/TextDiff/style.css +21 -0
  80. package/design-system/components/Timeline/README.md +3 -1
  81. package/design-system/components/TrendLine/README.md +38 -7
  82. package/design-system/components/TrendLine/preview.html +140 -3
  83. package/design-system/components/TrendLine/style.css +12 -2
  84. package/design-system/components/bundle.css +483 -7
  85. package/design-system/tokens.json +15 -1
  86. package/dist/fello-core.css +2 -2
  87. package/dist/fello.css +2 -2
  88. package/dist/fello.scoped.css +2 -2
  89. package/dist/index.d.ts +1 -1
  90. package/dist/scoped.js +2 -2
  91. package/dist/tokens.d.ts +8 -0
  92. package/dist/tokens.js +8 -0
  93. package/package.json +7 -2
  94. package/scripts/check-drift.mjs +325 -0
  95. package/scripts/token-model.mjs +2 -1
  96. package/tokens/_dark.css +2 -0
  97. package/tokens/_product.css +2 -0
  98. package/tokens/palettes.ts +1 -1
  99. package/tokens/shadcn-compat.css +1 -1
  100. package/tokens/shadcn-compat.hsl.css +1 -1
  101. package/tokens/tokens.css +14 -1
  102. package/tokens/tokens.md +53 -46
  103. package/tokens/tokens.root.css +14 -1
  104. package/tokens/tokens.ts +9 -1
@@ -109,6 +109,29 @@
109
109
  </div>
110
110
  </div>
111
111
 
112
+ <div class="ws-stack" style="width: 420px;">
113
+ <div class="ws-stack">
114
+ <span class="ws-muted">Selected in a grid of image tiles (--ring): a flush 2 px navy ring and a tick on the picture, nothing under the card; the picture rounds its own corners, so the card is never clipped</span>
115
+ <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: var(--space-xs);" role="group" aria-label="Choose the listing photo">
116
+ <button type="button" class="ws-card ws-card--ring" aria-pressed="false">
117
+ <span class="ws-card__media" role="img" aria-label="Front of 12 Elm Street"></span>
118
+ <span class="ws-card__tick" aria-hidden="true"><svg viewBox="0 0 16 16" fill="none"><path d="M3.5 8.5l3 3 6-7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
119
+ <span class="ws-card__body ws-meta">2400 × 1600</span>
120
+ </button>
121
+ <button type="button" class="ws-card ws-card--ring ws-card--selected" aria-pressed="true">
122
+ <span class="ws-card__media" role="img" aria-label="Kitchen of 12 Elm Street"></span>
123
+ <span class="ws-card__tick" aria-hidden="true"><svg viewBox="0 0 16 16" fill="none"><path d="M3.5 8.5l3 3 6-7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
124
+ <span class="ws-card__body ws-meta">2400 × 1600</span>
125
+ </button>
126
+ <button type="button" class="ws-card ws-card--ring" aria-pressed="false">
127
+ <span class="ws-card__media" role="img" aria-label="Garden of 12 Elm Street"></span>
128
+ <span class="ws-card__tick" aria-hidden="true"><svg viewBox="0 0 16 16" fill="none"><path d="M3.5 8.5l3 3 6-7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
129
+ <span class="ws-card__body ws-meta">1200 × 800</span>
130
+ </button>
131
+ </div>
132
+ </div>
133
+ </div>
134
+
112
135
  <div class="ws-stack" style="width: 340px;">
113
136
  <span class="ws-muted">Snug: a card in a chat column, every part 12 in, the band 16 above and under</span>
114
137
  <section class="ws-card ws-card--compound ws-card--snug">
@@ -38,6 +38,25 @@ a.ws-card[aria-busy="true"]::before { content: ""; position: absolute; inset: ca
38
38
  /* Selected, in a row of cards (North): the rim darkens and a 2 px navy tab sits 8 under the card, 16 in from each side. */
39
39
  .ws-card--selected { position: relative; border-color: var(--ws-well-hover); box-shadow: none; }
40
40
  .ws-card--selected::after { content: ""; position: absolute; left: var(--space-md); right: var(--space-md); top: calc(100% + var(--ws-rim) + var(--space-xs)); height: var(--ws-ring); border-radius: var(--ws-radius-chip); background: var(--color-text-heading); }
41
+ /* A picture in a card (ws-card__media, its first part: an image tile, a template or asset choice): edge to edge, its top
42
+ corners rounded to the cream's own (7), so the card is never clipped (K9) and a menu, a tip or the selected tab still
43
+ shows. The sunk cream behind it while it loads; a logo on a checker is the app's own ground. */
44
+ :where(button).ws-card { padding: 0; } /* the browser's button padding is not the card's: a picture runs edge to edge; the padding steps below still win */
45
+ .ws-card__media ~ .ws-card__body { display: block; padding: var(--space-xs) var(--space-sm) var(--space-sm); } /* a caption under a picture: 8 above, 12 round */
46
+ .ws-card__media { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--ws-radius-card-inner) var(--ws-radius-card-inner) 0 0; background: var(--ws-surface-sunk); }
47
+ /* Selected in a grid, or on a card that clips its content (--ring): the tab under the card would fall in the gap above
48
+ the next row, so the choice is drawn on the card itself. The rim turns navy with a hairline more outside it, a 2 px
49
+ ring, flush (the focus ring stands 2 off, so the two never look alike), and a tick (ws-card__tick, in the markup at
50
+ rest and shown only when selected) sits on the top right corner, on a cream ring so it reads over a photo. */
51
+ .ws-card--ring { position: relative; }
52
+ .ws-card--ring.ws-card--selected, .ws-card--ring.ws-card--selected:hover { border-color: var(--color-text-heading); box-shadow: 0 0 0 calc(var(--ws-ring) - var(--ws-rim)) var(--color-text-heading); }
53
+ .ws-card--ring.ws-card--selected::after { content: none; }
54
+ .ws-card__tick { position: absolute; top: var(--space-xs); right: var(--space-xs); z-index: 1; display: grid; place-items: center; width: var(--space-lg); height: var(--space-lg); border-radius: var(--radius-full); background: var(--color-text-heading); color: var(--ws-on-act); box-shadow: 0 0 0 var(--ws-ring) var(--color-bg-page); opacity: 0; transform: scale(var(--ws-pop-scale)); pointer-events: none; }
55
+ .ws-card__tick svg { width: var(--ws-icon-sm); height: var(--ws-icon-sm); }
56
+ .ws-card--selected > .ws-card__tick { opacity: 1; transform: none; }
57
+ @media (prefers-reduced-motion: no-preference) {
58
+ .ws-card__tick { transition: opacity var(--ws-duration-instant) var(--ws-ease-soft), transform var(--ws-duration-settle) var(--ws-ease-pop); }
59
+ }
41
60
  /* The card's own padding steps. */
42
61
  .ws-card--pad-sm { padding: var(--ws-card-padding); }
43
62
  .ws-card--pad-md { padding: var(--ws-card-padding-lg); }
@@ -6,6 +6,9 @@ chart, one title, one sentence, its facts on a plate or a breakdown, and the tra
6
6
  - An agent brings something to act on: a suggestion, a task, a question, a plan offer, a receipt of what it did.
7
7
  - A reminder or a nudge is due and needs the person's attention now (a needs-you card, with a timer and a cross).
8
8
  - The chat needs to show a lead, a draft, a call or a number as a named kind, not as plain words.
9
+ - An email, a call or a text belongs in the thread because the person should read it or answer it now (an account's
10
+ thread, an agent's morning briefing).
11
+ - An account needs a decision: its standing, its few numbers and one act, in the chat about it.
9
12
 
10
13
  ## Not for
11
14
 
@@ -15,6 +18,8 @@ chart, one title, one sentence, its facts on a plate or a breakdown, and the tra
15
18
  anything wider opens in the card's own full screen or the side panel, with "Open" left in the chat.
16
19
  - A list of past suggestions: a card is for the one thing in front of the person now; Today's own list lives
17
20
  beside the chat, not repeated here.
21
+ - Every email or call on an account: the agent names the rest in its words, with the source ("From the 9 Nov call");
22
+ the full history is the account's `Timeline`.
18
23
 
19
24
  ## Anatomy
20
25
 
@@ -42,6 +47,16 @@ chart, one title, one sentence, its facts on a plate or a breakdown, and the tra
42
47
  medium tabular navy on the sunk cream, 2 px corners) and a cross (`ws-icon-btn ws-icon-btn--sm ws-chat-card__close`,
43
48
  a 40 px hit area on touch) in the top right corner, 8 px in, for "not now"; the head keeps 32 px clear of it, so the
44
49
  timer ends 16 px short of the cross.
50
+ - An email, a call or a text (the message kinds): the head's end says when (`ws-meta ws-chat-card__when`, one line,
51
+ tabular: "Nov 9, 4:12 PM", "Nov 9 &middot; 24 min"); the title is the subject, what came of the call, or who texted;
52
+ the one sentence says who wrote to whom, in words ("Jordan Lee wrote to you"), and why it is here. The message's own
53
+ words are quoted on a sunk plate (`blockquote.ws-plate.ws-chat-card__quote` holding a `p.ws-body`), never adopted:
54
+ at most three lines, the rest behind the door. A call has no quote; its sentence says who was on it and what was
55
+ agreed. One that waits on a reply from the team wears the salmon-tinted disc.
56
+ - An account: the head's end holds its standing as a rating `Chip` (healthy `ws-chip--live`, watch `ws-chip--middle`,
57
+ at risk `ws-chip--needs-work`: Colour's rating tones, never salmon); the title says what matters about it now, not
58
+ its name alone; its few numbers sit on a stats plate (`ws-plate` holding `ws-plate__stats`: sentiment, its yearly
59
+ value, when it renews), a change written in words ("32, up from 29"); the door opens the account.
45
60
  - 0.4 markup's act group, `ws-chat-card__acts`, still lays its buttons out at the band's end; new markup uses
46
61
  `ws-band__acts`.
47
62
 
@@ -54,11 +69,19 @@ chart, one title, one sentence, its facts on a plate or a breakdown, and the tra
54
69
  | Question | "Question" | Answered in place, no button | No |
55
70
  | Reminder, nudge | "Reminder" | Done, or its one act | Yes, with a timer |
56
71
  | Receipt | "Receipt" | Undo, while it still can | No |
72
+ | Email | "Email" | Reply; a draft the agent wrote is a Suggestion with a draft `Plate`, its act Send | No |
73
+ | Call | "Call" | Listen | No |
74
+ | Text | "Text" | Reply | No |
75
+ | Account | "Account" | The one decision it needs (Escalate, Book a call), Draft a reply secondary | No |
76
+
77
+ A message kind's head says what it is, never its direction ("Email", not "Inbound email"); the sentence says who wrote
78
+ to whom.
57
79
 
58
80
  ## States
59
81
 
60
82
  - **Default**: the card as drawn above.
61
- - **Waits on you**: the head's disc is salmon-tinted (`ws-chat-card__disc--needs`).
83
+ - **Waits on you**: the head's disc is salmon-tinted (`ws-chat-card__disc--needs`); an email or a text that the team
84
+ has not answered.
62
85
  - **Pending**: the pressed button keeps its colour and shows a working dot; the other buttons step out of the way
63
86
  while the tap is in flight.
64
87
  - **Done**: the band's primary becomes a quiet Undo for as long as the act can still be taken back.
@@ -66,6 +89,7 @@ chart, one title, one sentence, its facts on a plate or a breakdown, and the tra
66
89
  - **Empty**: a card whose data does not exist is never drawn, not even as a placeholder shell.
67
90
  - **Long title**: a question's title is never clamped (the yes it leads to is in it); other kinds clamp to two
68
91
  lines.
92
+ - **Long message**: a quote stops at three lines with an ellipsis; the door opens the whole message where it lives.
69
93
  - **Loading**: a `StatusLine` on top says what the agent is doing, the drawing is a `Skeleton` ghost, the tray holds a
70
94
  `LoadBar`; the card is `aria-busy`.
71
95
  - **Narrow**: under 470 px the tray goes to 64 px with its acts beside the title; nothing truncates.
@@ -100,6 +124,8 @@ chart, one title, one sentence, its facts on a plate or a breakdown, and the tra
100
124
  job).
101
125
  - The band's left side never repeats a fact the button already states; a door is left out when it would only
102
126
  repeat where the primary button goes.
127
+ - A message is the sender's words, quoted as they wrote them; the agent's own reading of it goes in the sentence, never
128
+ in the quote. The agent's sentence names people, never their email address or number (AI experiences, Trust).
103
129
  - No em dashes; sentence case throughout.
104
130
 
105
131
  ## Props
@@ -132,7 +158,8 @@ view.
132
158
 
133
159
  **Derived from**: North's chat chart card (Figma 733:325166 "card 556 · inset 20 · tray 80"; style1.css:688-733,
134
160
  :1154-1190, :2001-2004), the system's footer band for a door plus buttons, and the needs-you timer-and-cross pattern.
135
- **Precedent**: the first product built on the system.
161
+ **Precedent**: the first product built on the system. The message kinds (Email, Call, Text) and the Account kind:
162
+ Calvin's account threads in Customer Value (Hemanth, 10 Nov 2026), built from the kit's own head, plate, chip and band.
136
163
 
137
164
  ## Markup
138
165
 
@@ -188,10 +215,54 @@ view.
188
215
  <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Mark done</button></div>
189
216
  </div>
190
217
  </div>
218
+
219
+ <!-- An email that waits on a reply: when at the head's end, its words quoted (a call and a text are the same shape) -->
220
+ <div class="ws-card ws-chat-card">
221
+ <div class="ws-chat-card__head">
222
+ <span class="ws-chat-card__kind">
223
+ <span class="ws-disc ws-chat-card__disc ws-chat-card__disc--needs" aria-hidden="true"><svg viewBox="0 0 16 16" fill="none"><!-- an envelope --></svg></span>
224
+ <span class="ws-eyebrow">Email</span>
225
+ </span>
226
+ <span class="ws-meta ws-chat-card__when">Nov 9, 4:12 PM</span>
227
+ </div>
228
+ <p class="ws-section">Re: Next onboarding step</p>
229
+ <p class="ws-body">Jordan Lee wrote to you. It has waited two days for a reply.</p>
230
+ <blockquote class="ws-plate ws-chat-card__quote"><p class="ws-body">Before the follow-ups go out, can you confirm the hours they will send?</p></blockquote>
231
+ <div class="ws-band ws-chat-card__band">
232
+ <a class="ws-chat-card__door" href="/mail/thread/123">Open in Mail</a>
233
+ <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Reply</button></div>
234
+ </div>
235
+ </div>
236
+
237
+ <!-- An account: its standing as a rating chip, its numbers on a stats plate -->
238
+ <div class="ws-card ws-chat-card">
239
+ <div class="ws-chat-card__head">
240
+ <span class="ws-chat-card__kind">
241
+ <span class="ws-disc ws-chat-card__disc" aria-hidden="true"><svg viewBox="0 0 16 16" fill="none"><!-- a building --></svg></span>
242
+ <span class="ws-eyebrow">Account</span>
243
+ </span>
244
+ <span class="ws-chip ws-chip--needs-work">Risk</span>
245
+ </div>
246
+ <p class="ws-section">Harbor Point Realty asked to cancel</p>
247
+ <p class="ws-body">The ask is four days old and nobody owns it yet.</p>
248
+ <div class="ws-plate">
249
+ <div class="ws-plate__stats">
250
+ <div class="ws-plate__stat"><span class="ws-plate__label">Sentiment</span><span class="ws-plate__value">32, up from 29</span></div>
251
+ <div class="ws-plate__stat"><span class="ws-plate__label">Renews</span><span class="ws-plate__value">In 110 days</span></div>
252
+ </div>
253
+ </div>
254
+ <div class="ws-band ws-chat-card__band">
255
+ <a class="ws-chat-card__door" href="/accounts/harbor-point">Open the account</a>
256
+ <div class="ws-band__acts">
257
+ <button type="button" class="ws-btn ws-btn--secondary ws-btn--lg">Draft a reply</button>
258
+ <button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Escalate</button>
259
+ </div>
260
+ </div>
261
+ </div>
191
262
  ```
192
263
 
193
264
  ## Styles
194
265
 
195
- `ChatCard/style.css`; the band and its acts are `Card`'s, the plate `Plate`'s. Tokens: `--ws-chart-card-w`,
266
+ `ChatCard/style.css`; the band and its acts are `Card`'s, the plate `Plate`'s, the standing `Chip`'s. Tokens: `--ws-chart-card-w`,
196
267
  `--ws-card-inset`, `--ws-edge-card`, `--ws-edge-card-1x`, `--ws-edge-slot`, `--ws-radius-card-inner`, `--ws-tint-needs`,
197
268
  `--ws-surface-sunk`.
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Chat" height=1217 -->
1
+ <!-- @dsCard group="Chat" height=2240 -->
2
2
  <!doctype html>
3
3
  <html>
4
4
  <head>
@@ -88,34 +88,135 @@
88
88
  </div>
89
89
  </div>
90
90
  </div>
91
+
92
+ <div class="ws-stack">
93
+ <span class="ws-muted">An email that waits on a reply: when in the head, its words quoted on a plate, Reply</span>
94
+ <div class="ws-card ws-chat-card">
95
+ <div class="ws-chat-card__head">
96
+ <span class="ws-chat-card__kind">
97
+ <span class="ws-disc ws-chat-card__disc ws-chat-card__disc--needs" aria-hidden="true">
98
+ <svg viewBox="0 0 16 16" fill="none"><rect x="2.5" y="3.5" width="11" height="9" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M3 4.8l5 3.7 5-3.7" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
99
+ </span>
100
+ <span class="ws-eyebrow">Email</span>
101
+ </span>
102
+ <span class="ws-meta ws-chat-card__when">Nov 9, 4:12 PM</span>
103
+ </div>
104
+ <p class="ws-section">Re: Next onboarding step</p>
105
+ <p class="ws-body">Jordan Lee wrote to you. It has waited two days for a reply.</p>
106
+ <blockquote class="ws-plate ws-chat-card__quote">
107
+ <p class="ws-body">Thanks for the call on Friday. Before the follow-ups go out, can you confirm the hours they will send? Our broker wants nothing on Sundays, and two of our agents are part time, so weekday evenings matter too.</p>
108
+ </blockquote>
109
+ <div class="ws-band ws-chat-card__band">
110
+ <a class="ws-chat-card__door" href="#" onclick="return false;">
111
+ Open in Mail
112
+ <svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 12l8-8M7 4h5v5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
113
+ </a>
114
+ <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Reply</button></div>
115
+ </div>
116
+ </div>
117
+ </div>
118
+
119
+ <div class="ws-stack">
120
+ <span class="ws-muted">A call: what came of it as the title, who and how long under it, Listen</span>
121
+ <div class="ws-card ws-chat-card">
122
+ <div class="ws-chat-card__head">
123
+ <span class="ws-chat-card__kind">
124
+ <span class="ws-disc ws-chat-card__disc" aria-hidden="true">
125
+ <svg viewBox="0 0 16 16" fill="none"><path d="M4.4 2.8l2 .2 1 2.6-1.3 1a7.5 7.5 0 0 0 3.3 3.3l1-1.3 2.6 1 .2 2c0 .7-.6 1.2-1.3 1.2A10.4 10.4 0 0 1 3.2 4.1c0-.7.5-1.3 1.2-1.3z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
126
+ </span>
127
+ <span class="ws-eyebrow">Call</span>
128
+ </span>
129
+ <span class="ws-meta ws-chat-card__when">Nov 9 &middot; 24 min</span>
130
+ </div>
131
+ <p class="ws-section">Jordan asked to pause for six months</p>
132
+ <p class="ws-body">You and Jordan Lee. A pause and a lower price were turned down; training by Friday was promised instead.</p>
133
+ <div class="ws-band ws-chat-card__band">
134
+ <a class="ws-chat-card__door" href="#" onclick="return false;">Read the notes</a>
135
+ <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Listen</button></div>
136
+ </div>
137
+ </div>
138
+ </div>
139
+
140
+ <div class="ws-stack">
141
+ <span class="ws-muted">An account: its standing as a tag in the head, its numbers on a plate, one navy act</span>
142
+ <div class="ws-card ws-chat-card">
143
+ <div class="ws-chat-card__head">
144
+ <span class="ws-chat-card__kind">
145
+ <span class="ws-disc ws-chat-card__disc" aria-hidden="true">
146
+ <svg viewBox="0 0 16 16" fill="none"><path d="M3.5 13.5v-10h6v10M9.5 6.5h3v7M2.5 13.5h11M5.5 6h1.5M5.5 8.5h1.5M5.5 11h1.5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
147
+ </span>
148
+ <span class="ws-eyebrow">Account</span>
149
+ </span>
150
+ <span class="ws-chip ws-chip--needs-work">Risk</span>
151
+ </div>
152
+ <p class="ws-section">Harbor Point Realty asked to cancel</p>
153
+ <p class="ws-body">The ask is four days old and nobody owns it yet. Sentiment is up a little since Friday&rsquo;s call.</p>
154
+ <div class="ws-plate">
155
+ <div class="ws-plate__stats">
156
+ <div class="ws-plate__stat"><span class="ws-plate__label">Sentiment</span><span class="ws-plate__value">32, up from 29</span></div>
157
+ <div class="ws-plate__stat"><span class="ws-plate__label">Yearly value</span><span class="ws-plate__value">$36K</span></div>
158
+ <div class="ws-plate__stat"><span class="ws-plate__label">Renews</span><span class="ws-plate__value">In 110 days</span></div>
159
+ </div>
160
+ </div>
161
+ <div class="ws-band ws-chat-card__band">
162
+ <a class="ws-chat-card__door" href="#" onclick="return false;">Open the account</a>
163
+ <div class="ws-band__acts">
164
+ <button type="button" class="ws-btn ws-btn--secondary ws-btn--lg">Draft a reply</button>
165
+ <button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Escalate</button>
166
+ </div>
167
+ </div>
168
+ </div>
169
+ </div>
91
170
  </div>
92
171
 
93
- <div class="ws-stack" style="width: 400px;">
94
- <span class="ws-muted">Needs-you reminder in a narrow chat: a timer, a cross for not now; the tray goes to 64</span>
95
- <div class="ws-card ws-chat-card">
96
- <button type="button" class="ws-icon-btn ws-icon-btn--sm ws-chat-card__close" aria-label="Not now: Call Priya back before her offer expires" title="Not now">
97
- <svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
98
- </button>
99
- <div class="ws-chat-card__head">
100
- <span class="ws-chat-card__kind">
101
- <span class="ws-disc ws-chat-card__disc ws-chat-card__disc--needs" aria-hidden="true">
102
- <svg viewBox="0 0 16 16" fill="none"><path d="M4.5 11.5V7.8a3.5 3.5 0 0 1 7 0v3.7l1 1.2h-9z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M7 14a1.2 1.2 0 0 0 2 0" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
172
+ <div class="ws-stack ws-stack--group" style="width: 400px;">
173
+ <div class="ws-stack">
174
+ <span class="ws-muted">Needs-you reminder in a narrow chat: a timer, a cross for not now; the tray goes to 64</span>
175
+ <div class="ws-card ws-chat-card">
176
+ <button type="button" class="ws-icon-btn ws-icon-btn--sm ws-chat-card__close" aria-label="Not now: Call Priya back before her offer expires" title="Not now">
177
+ <svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
178
+ </button>
179
+ <div class="ws-chat-card__head">
180
+ <span class="ws-chat-card__kind">
181
+ <span class="ws-disc ws-chat-card__disc ws-chat-card__disc--needs" aria-hidden="true">
182
+ <svg viewBox="0 0 16 16" fill="none"><path d="M4.5 11.5V7.8a3.5 3.5 0 0 1 7 0v3.7l1 1.2h-9z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M7 14a1.2 1.2 0 0 0 2 0" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
183
+ </span>
184
+ <span class="ws-eyebrow">Reminder</span>
103
185
  </span>
104
- <span class="ws-eyebrow">Reminder</span>
105
- </span>
106
- <span class="ws-chat-card__timer" title="2 hours left">
107
- <svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3l2 1.2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
108
- 2h left
109
- </span>
186
+ <span class="ws-chat-card__timer" title="2 hours left">
187
+ <svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3l2 1.2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
188
+ 2h left
189
+ </span>
190
+ </div>
191
+ <p class="ws-section">Call Priya back before her offer expires</p>
192
+ <p class="ws-body">She asked for a decision by end of day. The last note on her file is three days old.</p>
193
+ <div class="ws-band ws-chat-card__band">
194
+ <div class="ws-band__words">
195
+ <p class="ws-band__title">Call her now</p>
196
+ <p class="ws-band__how">Her number is on file</p>
197
+ </div>
198
+ <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Mark done</button></div>
199
+ </div>
110
200
  </div>
111
- <p class="ws-section">Call Priya back before her offer expires</p>
112
- <p class="ws-body">She asked for a decision by end of day. The last note on her file is three days old.</p>
113
- <div class="ws-band ws-chat-card__band">
114
- <div class="ws-band__words">
115
- <p class="ws-band__title">Call her now</p>
116
- <p class="ws-band__how">Her number is on file</p>
117
- </div>
118
- <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Mark done</button></div>
201
+ </div>
202
+ <div class="ws-stack">
203
+ <span class="ws-muted">A text in a narrow chat: who sent it as the title, the text quoted whole, Reply</span>
204
+ <div class="ws-card ws-chat-card">
205
+ <div class="ws-chat-card__head">
206
+ <span class="ws-chat-card__kind">
207
+ <span class="ws-disc ws-chat-card__disc ws-chat-card__disc--needs" aria-hidden="true">
208
+ <svg viewBox="0 0 16 16" fill="none"><path d="M2.8 4.3c0-.8.7-1.5 1.5-1.5h7.4c.8 0 1.5.7 1.5 1.5v5.2c0 .8-.7 1.5-1.5 1.5H7.2L4.5 13v-2h-.2c-.8 0-1.5-.7-1.5-1.5z" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/></svg>
209
+ </span>
210
+ <span class="ws-eyebrow">Text</span>
211
+ </span>
212
+ <span class="ws-meta ws-chat-card__when">8:05 AM</span>
213
+ </div>
214
+ <p class="ws-section">Jordan Lee texted you</p>
215
+ <blockquote class="ws-plate ws-chat-card__quote"><p class="ws-body">Running ten minutes late for our 9. Still on?</p></blockquote>
216
+ <div class="ws-band ws-chat-card__band">
217
+ <a class="ws-chat-card__door" href="#" onclick="return false;">Open the thread</a>
218
+ <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Reply</button></div>
219
+ </div>
119
220
  </div>
120
221
  </div>
121
222
  </div>
@@ -15,6 +15,12 @@
15
15
  .ws-chat-card:has(> .ws-chat-card__close) > .ws-chat-card__head { padding-right: var(--space-xl); }
16
16
  .ws-chat-card__facts { display: flex; flex-wrap: wrap; gap: var(--space-xxs) var(--space-md); font-size: var(--ws-text-dense); color: var(--color-text-body); }
17
17
  .ws-chat-card__facts b { font-weight: 600; color: var(--color-text-heading); }
18
+ /* An email, a call or a text: when it happened sits at the head's end, one line, in the meta words. */
19
+ .ws-chat-card__when { flex-shrink: 0; font-variant-numeric: tabular-nums; white-space: nowrap; }
20
+ /* Its own words (an email's opening lines, a text) quoted on a sunk plate, never adopted: at most three lines, the door
21
+ opens the rest. The clamp sits on the words, not the plate, so a fourth line never shows in the plate's padding. */
22
+ .ws-chat-card__quote { margin: 0; }
23
+ .ws-chat-card__quote > p { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; }
18
24
  /* A chart answer's drawing: the dotted field runs to the card's edges and sits only behind the drawing, 24 under it. */
19
25
  .ws-chat-card__graph { margin: var(--space-xs) calc(var(--ws-card-inset) * -1) 0; padding: var(--space-md) var(--ws-card-inset) var(--space-lg); }
20
26
  /* A breakdown under the answer: rows edge to edge, 44 tall, 0.5 px rules, the label left and the figure right. */
@@ -1,4 +1,4 @@
1
- A small fact in a 24 px tag, in one of six tones, a rating tone or the Example mark; its sibling `ChangeChip` says a
1
+ A small fact in a 24 px tag, in one of seven tones, a rating tone or the Example mark; its sibling `ChangeChip` says a
2
2
  number went up, down or stayed.
3
3
 
4
4
  ## Use it when
@@ -23,6 +23,9 @@ number went up, down or stayed.
23
23
  - Edge: the 0.5 px chip edge (`--ws-edge-chip`), drawn inside, on the plain tone only; tinted tones have none.
24
24
  - Words: 13 / 18 medium (Seth's control words), one line.
25
25
  - Optional icon: 12 px (`--ws-icon-sm`), 4 before the words.
26
+ - Small (`--sm`, #30): 20 tall, 12 / 16 medium words, 6 px sides, the same icon and corners, for several tags in one
27
+ place (a board card, a table cell, a list row). A fact only: a chip that acts (a filter, a remove) keeps 24, so its
28
+ target holds.
26
29
  - Never wider than its column: a long fact ends in an ellipsis inside `ws-chip__label` (and the chip carries a `title`).
27
30
 
28
31
  ### Example
@@ -45,14 +48,18 @@ number went up, down or stayed.
45
48
  | --- | --- | --- | --- |
46
49
  | `neutral` | `--color-bg-page` (cream), chip edge | `--color-text-body` | a plain fact ("Version 1") |
47
50
  | `sunk` | `--ws-surface-sunk` | `--color-text-body` | a fact on a lighter card |
48
- | `accent` | `--ws-surface-sunk` | `--color-text-interactive` (mid blue) | a quiet link-coloured note |
49
- | `live` | `--ws-tint-live` (teal 12%) | `--ws-word-positive` | done, ready, gone well; the rating "Strong" |
51
+ | `accent` | `--ws-surface-sunk` | `--color-text-interactive` (mid blue) | a quiet link-coloured note; an info status |
52
+ | `live` | `--ws-tint-live` (teal 12%) | `--ws-word-positive` | done, ready, gone well; the rating "Strong"; a success status |
50
53
  | `navy` | `--ws-surface-sunk` | `--color-text-heading`, semibold | a count or a highlighted fact ("New") |
51
- | `needs` | `--ws-tint-needs` (salmon 10%) | `--ws-word-needs` | something needs you ("2 behind") |
54
+ | `needs` | `--ws-tint-needs` (salmon 10%) | `--ws-word-needs` | something needs you ("2 behind"); a warning status |
55
+ | `alert` | `--ws-tint-alert` (the alert red 8%) | `--ws-word-alert` | something is wrong now ("Failed", "Rejected"); an error status |
52
56
  | `middle` | `--ws-card-tint-blue` | `--color-text-interactive` | the rating's middle band ("Getting there") |
53
57
  | `needs-work` | `--ws-tint-needs-work` (Seth's pink at 20%) | `--ws-word-needs-work` (#B42D68) | the rating "Needs work" |
54
58
  | `example` | none, dashed muted edge | `--color-text-muted`, 11 px semibold | made-up numbers |
55
59
 
60
+ Sizes: the default 24 (13 / 18 words), and `--sm` 20 (12 / 16 words) where several sit together. Any tone takes either.
61
+ One size per row: a card's tags are all small or all default.
62
+
56
63
  ### ChangeChip marks
57
64
 
58
65
  | Mark | Colour | Meaning |
@@ -92,7 +99,7 @@ number went up, down or stayed.
92
99
 
93
100
  | Name | Type | Meaning |
94
101
  | --- | --- | --- |
95
- | `tone` | `'neutral' \| 'sunk' \| 'accent' \| 'live' \| 'navy' \| 'needs' \| 'middle' \| 'needs-work' \| 'example'` | the look, default `neutral` |
102
+ | `tone` | `'neutral' \| 'sunk' \| 'accent' \| 'live' \| 'navy' \| 'needs' \| 'alert' \| 'middle' \| 'needs-work' \| 'example'` | the look, default `neutral` |
96
103
  | `icon` | `IconName` | an optional 12 px icon before the words |
97
104
  | `children` | `ReactNode` | the words |
98
105
 
@@ -106,7 +113,7 @@ number went up, down or stayed.
106
113
 
107
114
  ## Rules
108
115
 
109
- - Six fact tones, the three rating tones and Example; a further look is a sign the screen needs another component.
116
+ - Seven fact tones, the three rating tones and Example; a further look is a sign the screen needs another component.
110
117
  - Ratings (D10): strong is teal (`live`), the middle band mid blue (`middle`), needs work Seth's pink (`needs-work`, its
111
118
  words the AA step #B42D68). Salmon stays "needs you" (`needs`).
112
119
  - Made-up numbers are always chipped `Example` (issue #8, Seth's v7 first open); real numbers never are.
@@ -124,6 +131,8 @@ tones and the field's fix for a long chip (Ignite controls.tsx: a label that tru
124
131
  ```html
125
132
  <span class="ws-chip ws-chip--needs-work">Needs work</span>
126
133
  <span class="ws-chip ws-chip--example">Example</span>
134
+ <!-- small: several tags together, a fact only -->
135
+ <span class="ws-chip ws-chip--sm ws-chip--sunk">Blog</span>
127
136
  <span class="ws-chip ws-chip--sunk" title="Referred by Dana Alvarez at the open house">
128
137
  <span class="ws-chip__label">Referred by Dana Alvarez at the open house</span>
129
138
  </span>
@@ -136,6 +145,6 @@ tones and the field's fix for a long chip (Ignite controls.tsx: a label that tru
136
145
  ## Styles
137
146
 
138
147
  `design-system/components/Chip/style.css`: `ws-chip` with its tones (`ws-chip--sunk`, `ws-chip--accent`,
139
- `ws-chip--live`, `ws-chip--navy`, `ws-chip--needs`, `ws-chip--middle`, `ws-chip--needs-work`, `ws-chip--example`) and
148
+ `ws-chip--live`, `ws-chip--navy`, `ws-chip--needs`, `ws-chip--alert`, `ws-chip--middle`, `ws-chip--needs-work`, `ws-chip--example`), its small size (`ws-chip--sm`) and
140
149
  `ws-chip__label`. `ws-change` (ChangeChip)
141
150
  is the house's (`_house.css`, Chips).
@@ -11,7 +11,7 @@
11
11
  <div class="ws-stage ws-stage--column">
12
12
 
13
13
  <div class="ws-stack">
14
- <span class="ws-muted">Chip: the six tones (24 px, 4 px corners, 13 px medium)</span>
14
+ <span class="ws-muted">Chip: the fact tones (24 px, 4 px corners, 13 px medium)</span>
15
15
  <div class="ws-cluster">
16
16
  <span class="ws-chip">Version 1</span>
17
17
  <span class="ws-chip ws-chip--sunk">Cold call</span>
@@ -22,6 +22,16 @@
22
22
  </div>
23
23
  </div>
24
24
 
25
+ <div class="ws-stack">
26
+ <span class="ws-muted">Status sets: error (alert), warning (needs), success (live), info (accent)</span>
27
+ <div class="ws-cluster">
28
+ <span class="ws-chip ws-chip--alert">Failed</span>
29
+ <span class="ws-chip ws-chip--needs">Ends Friday</span>
30
+ <span class="ws-chip ws-chip--live">Published</span>
31
+ <span class="ws-chip ws-chip--accent">Queued</span>
32
+ </div>
33
+ </div>
34
+
25
35
  <div class="ws-stack">
26
36
  <span class="ws-muted">Rating tones: strong (teal), getting there (mid blue), needs work (Seth's pink tag)</span>
27
37
  <div class="ws-cluster">
@@ -39,6 +49,20 @@
39
49
  </div>
40
50
  </div>
41
51
 
52
+ <div class="ws-stack">
53
+ <span class="ws-muted">Small (20 px, 12 px words): several tags on a board card or in a table cell</span>
54
+ <div class="ws-cluster ws-cluster--tight">
55
+ <span class="ws-chip ws-chip--sm ws-chip--sunk">Blog</span>
56
+ <span class="ws-chip ws-chip--sm ws-chip--live">Approved</span>
57
+ <span class="ws-chip ws-chip--sm ws-chip--needs">Due Nov 12</span>
58
+ <span class="ws-chip ws-chip--sm ws-chip--middle">In review</span>
59
+ <span class="ws-chip ws-chip--sm">
60
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="8" cy="5.5" r="2.5"/><path d="M3 13c0-2.5 2.2-4 5-4s5 1.5 5 4"/></svg>
61
+ <span class="ws-chip__label">Madan</span>
62
+ </span>
63
+ </div>
64
+ </div>
65
+
42
66
  <div class="ws-stack" style="max-width: 240px;">
43
67
  <span class="ws-muted">A long fact in a narrow column: cut with an ellipsis, whole in its title</span>
44
68
  <span class="ws-chip ws-chip--sunk" title="Referred by Dana Alvarez at the open house">
@@ -9,9 +9,14 @@
9
9
  .ws-chip--live { background: var(--ws-tint-live); color: var(--ws-word-positive); box-shadow: none; }
10
10
  .ws-chip--navy { background: var(--ws-surface-sunk); color: var(--color-text-heading); font-weight: 600; box-shadow: none; }
11
11
  .ws-chip--needs { background: var(--ws-tint-needs); color: var(--ws-word-needs); box-shadow: none; }
12
+ .ws-chip--alert { background: var(--ws-tint-alert); color: var(--ws-word-alert); box-shadow: none; } /* an error status (#15) */
12
13
  /* Rating tones (D10): strong is --live; the middle band ("Getting there") is mid blue; needs work is Seth's pink as a
13
14
  20% tint, its words the AA step (#B42D68, 301:2018). */
14
15
  .ws-chip--middle { background: var(--ws-card-tint-blue); color: var(--ws-rating-middle); box-shadow: none; }
15
16
  .ws-chip--needs-work { background: var(--ws-tint-needs-work); color: var(--ws-word-needs-work); box-shadow: none; }
17
+ /* Small (#30): the dense step for several tags in one place (a board card, a table cell, a list row): 20 tall, 12 / 16
18
+ medium words, 6 px sides, the 12 px icon 4 before them. A fact only, never a control: a chip that acts keeps 24. Any
19
+ tone. */
20
+ .ws-chip--sm { height: calc(var(--space-md) + var(--space-xxs)); padding: 0 var(--space-xxs-plus); font-size: var(--ws-text-dense); line-height: var(--space-md); }
16
21
  /* Example (issue #8, Seth's v7 first open): made-up numbers are chipped. A 1 px dashed edge, 11 px semibold, a round tag. */
17
22
  .ws-chip--example { border-radius: var(--ws-radius-bubble); background: transparent; color: var(--color-text-muted); font-size: var(--ws-text-micro); line-height: var(--ws-leading-micro); font-weight: 600; box-shadow: none; outline: var(--ws-line) dashed var(--color-text-muted); outline-offset: calc(var(--ws-line) * -1); }
@@ -27,6 +27,9 @@ A searchable field for choosing from a long list, matching as you type and offer
27
27
  a glance. This two-weight split is specific to `Combobox`'s rows; `Menu`'s own rows stay uniformly navy-medium.
28
28
  - Highlighted row (the keyboard's, `aria-activedescendant`): `--ws-surface-sunk`; under the pointer, the navy wash
29
29
  (`--ws-hover`); rows have 6 px corners.
30
+ - Chosen row (`aria-selected="true"`): `Menu`'s tick, 16 px navy at the row's end, centred on its first line (a mask the
31
+ kit draws, so the markup does not change). Never the sunk cream: that is the keyboard's, and a list that opens on the
32
+ current value and is then walked with the arrows must say which row is chosen and which the keyboard is on (#19).
30
33
  - "No matches" row: muted words (`--color-text-muted`), not a real option, not focusable.
31
34
  - "Create" row: a text act (`ws-act`-style navy medium, underlined on hover) with a small leading plus icon, since
32
35
  creating a new value is an act, not a choice among existing ones (08-choosing-components.md: "Words that act inside a
@@ -41,13 +44,15 @@ A searchable field for choosing from a long list, matching as you type and offer
41
44
  | --- | --- | --- |
42
45
  | Single choice | the chosen value as plain text in the field | one address, one source |
43
46
  | Multi-select (`TagInput`) | chosen values as chips in the field, wrapping past 32 px as needed | several tags, several assigned people |
47
+ | Multi-select, ticked rows | `aria-multiselectable="true"` on the list: each chosen row keeps its tick; the field says how many ("2 chosen") | a filter's list, where the choices are seen in the list rather than as tags |
44
48
 
45
49
  There is one size; both variants expand to 40 px (or taller, for wrapped chips) on a touch screen.
46
50
 
47
51
  ## States
48
52
 
49
53
  - **Closed, with a value:** the field shows the chosen text (or chips) and the chevron, no panel.
50
- - **Open, with matches:** the panel shows rows with the two-weight highlight; the active row is sunk.
54
+ - **Open, with matches:** the panel shows rows with the two-weight highlight; the active row is sunk; the chosen row,
55
+ if there is one, is ticked (the two can be the same row: sunk and ticked).
51
56
  - **No matches:** the panel shows the muted "No matches" row, and the "Create" row if creating is allowed.
52
57
  - **Multi-select:** chips sit in the field; the panel still opens below for further choices.
53
58
  - **Focus:** the kit's focus ring, 2 px navy, 2 px out, as `Input`'s (a field's edge darkens under the pointer).
@@ -116,12 +121,13 @@ inside edge and hover.
116
121
  <div class="ws-combobox">
117
122
  <label class="ws-label" for="cb-address">Street address</label>
118
123
  <span class="ws-combobox__field">
119
- <input id="cb-address" type="text" role="combobox" aria-expanded="true" aria-controls="cb-list" aria-activedescendant="cb-opt-1" value="pine">
124
+ <input id="cb-address" type="text" role="combobox" aria-expanded="true" aria-controls="cb-list" aria-activedescendant="cb-opt-0" value="pine">
120
125
  <svg class="ws-combobox__chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6l4 4 4-4"/></svg>
121
126
  </span>
122
127
  <div class="ws-menu ws-combobox__panel" role="listbox" id="cb-list">
123
- <div class="ws-combobox__option" role="option" id="cb-opt-0"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest">wood Drive</span></div>
124
- <div class="ws-combobox__option ws-combobox__option--active" role="option" id="cb-opt-1" aria-selected="true"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest"> Street</span></div>
128
+ <!-- the keyboard's row: --active (sunk); the chosen row: aria-selected (ticked) -->
129
+ <div class="ws-combobox__option ws-combobox__option--active" role="option" id="cb-opt-0"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest">wood Drive</span></div>
130
+ <div class="ws-combobox__option" role="option" id="cb-opt-1" aria-selected="true"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest"> Street</span></div>
125
131
  </div>
126
132
  </div>
127
133
  ```
@@ -21,16 +21,16 @@
21
21
  </div>
22
22
 
23
23
  <div class="ws-combobox">
24
- <span class="ws-muted">Open, with matches (typed part navy medium, rest body grey)</span>
24
+ <span class="ws-muted">Open on the chosen value (ticked), the keyboard two rows on (sunk)</span>
25
25
  <label class="ws-label" for="cb-open">Street address</label>
26
26
  <span class="ws-combobox__field ws-combobox__field--focus">
27
- <input id="cb-open" type="text" value="pine" role="combobox" aria-expanded="true" aria-controls="cb-list" aria-activedescendant="cb-opt-1">
27
+ <input id="cb-open" type="text" value="pine" role="combobox" aria-expanded="true" aria-controls="cb-list" aria-activedescendant="cb-opt-2">
28
28
  <svg class="ws-combobox__chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6l4 4 4-4"/></svg>
29
29
  </span>
30
30
  <div class="ws-menu ws-combobox__panel" role="listbox" id="cb-list">
31
31
  <div class="ws-combobox__option" role="option" id="cb-opt-0"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest">wood Drive</span></div>
32
- <div class="ws-combobox__option ws-combobox__option--active" role="option" id="cb-opt-1" aria-selected="true"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest"> Street</span></div>
33
- <div class="ws-combobox__option" role="option" id="cb-opt-2"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest"> Hollow Court</span></div>
32
+ <div class="ws-combobox__option" role="option" id="cb-opt-1" aria-selected="true"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest"> Street</span></div>
33
+ <div class="ws-combobox__option ws-combobox__option--active" role="option" id="cb-opt-2"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest"> Hollow Court</span></div>
34
34
  <div class="ws-combobox__option" role="option" id="cb-opt-3"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest"> Hollow Court, Building 4, Unit 1207, Lakeview Estates North</span></div>
35
35
  </div>
36
36
  </div>
@@ -62,6 +62,21 @@
62
62
  </span>
63
63
  </div>
64
64
 
65
+ <div class="ws-combobox">
66
+ <span class="ws-muted">Several chosen, kept as ticked rows in the list (a filter's list)</span>
67
+ <label class="ws-label" for="cb-many">Channels</label>
68
+ <span class="ws-combobox__field ws-combobox__field--focus">
69
+ <input id="cb-many" type="text" value="" placeholder="2 chosen" role="combobox" aria-expanded="true" aria-controls="cb-list-many" aria-activedescendant="cb-many-2">
70
+ <svg class="ws-combobox__chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6l4 4 4-4"/></svg>
71
+ </span>
72
+ <div class="ws-menu ws-combobox__panel" role="listbox" id="cb-list-many" aria-multiselectable="true">
73
+ <div class="ws-combobox__option" role="option" id="cb-many-0" aria-selected="true"><span class="ws-combobox__rest">Email</span></div>
74
+ <div class="ws-combobox__option" role="option" id="cb-many-1" aria-selected="true"><span class="ws-combobox__rest">Social</span></div>
75
+ <div class="ws-combobox__option ws-combobox__option--active" role="option" id="cb-many-2" aria-selected="false"><span class="ws-combobox__rest">Blog</span></div>
76
+ <div class="ws-combobox__option" role="option" id="cb-many-3" aria-selected="false"><span class="ws-combobox__rest">Paid ads</span></div>
77
+ </div>
78
+ </div>
79
+
65
80
  <div class="ws-combobox">
66
81
  <span class="ws-muted">Error: nothing chosen, with what to do</span>
67
82
  <label class="ws-label" for="cb-error">Listing</label>