@czi-sds/mcp 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +2 -1
  2. package/data/component-docs/Accordion.md +291 -0
  3. package/data/component-docs/Autocomplete.md +525 -0
  4. package/data/component-docs/Banner.md +231 -0
  5. package/data/component-docs/Button.md +224 -0
  6. package/data/component-docs/ButtonDropdown.md +256 -0
  7. package/data/component-docs/ButtonGroup.md +320 -0
  8. package/data/component-docs/ButtonToggle.md +397 -0
  9. package/data/component-docs/Callout.md +268 -0
  10. package/data/component-docs/CellBasic.md +122 -0
  11. package/data/component-docs/CellComponent.md +63 -0
  12. package/data/component-docs/CellHeader.md +128 -0
  13. package/data/component-docs/ComplexFilter.md +294 -0
  14. package/data/component-docs/ContentCard.md +406 -0
  15. package/data/component-docs/Dialog.md +651 -0
  16. package/data/component-docs/Dropdown.md +155 -0
  17. package/data/component-docs/DropdownMenu.md +949 -0
  18. package/data/component-docs/HeatmapChart.md +782 -0
  19. package/data/component-docs/Hero.md +363 -0
  20. package/data/component-docs/Icon.md +283 -0
  21. package/data/component-docs/InputCheckbox.md +205 -0
  22. package/data/component-docs/InputDropdown.md +482 -0
  23. package/data/component-docs/InputRadio.md +173 -0
  24. package/data/component-docs/InputSearch.md +81 -0
  25. package/data/component-docs/InputSlider.md +189 -0
  26. package/data/component-docs/InputText.md +110 -0
  27. package/data/component-docs/InputToggle.md +141 -0
  28. package/data/component-docs/IntentMessage.md +293 -0
  29. package/data/component-docs/Legend.md +442 -0
  30. package/data/component-docs/Link.md +23 -0
  31. package/data/component-docs/List.md +300 -0
  32. package/data/component-docs/LoadingIndicator.md +198 -0
  33. package/data/component-docs/Menu.md +298 -0
  34. package/data/component-docs/MenuItem.md +100 -0
  35. package/data/component-docs/NavigationFooter.md +165 -0
  36. package/data/component-docs/NavigationHeader.md +500 -0
  37. package/data/component-docs/NavigationJumpTo.md +414 -0
  38. package/data/component-docs/Notification.md +288 -0
  39. package/data/component-docs/Pagination.md +67 -0
  40. package/data/component-docs/Panel.md +636 -0
  41. package/data/component-docs/Popover.md +448 -0
  42. package/data/component-docs/PreComposedTable.md +2947 -0
  43. package/data/component-docs/SegmentedControl.md +396 -0
  44. package/data/component-docs/StackedBarChart.md +475 -0
  45. package/data/component-docs/Table.md +2000 -0
  46. package/data/component-docs/TableHeader.md +53 -0
  47. package/data/component-docs/TableRow.md +74 -0
  48. package/data/component-docs/Tabs.md +455 -0
  49. package/data/component-docs/Tag.md +647 -0
  50. package/data/component-docs/TagFilter.md +131 -0
  51. package/data/component-docs/Tooltip.md +561 -0
  52. package/data/component-docs/TooltipCondensed.md +203 -0
  53. package/data/component-docs/TooltipTable.md +145 -0
  54. package/data/component-docs/index.json +262 -0
  55. package/data/component-list.json +2 -5
  56. package/data/component-props/Accordion.json +31 -11
  57. package/data/component-props/Alert.json +3 -3
  58. package/data/component-props/Autocomplete.json +150 -15
  59. package/data/component-props/Banner.json +31 -17
  60. package/data/component-props/Button.json +45 -20
  61. package/data/component-props/ButtonDropdown.json +36 -17
  62. package/data/component-props/ButtonDropdownLegacy.json +11 -11
  63. package/data/component-props/ButtonGroup.json +32 -11
  64. package/data/component-props/ButtonIcon.json +10 -10
  65. package/data/component-props/ButtonLegacy.json +19 -19
  66. package/data/component-props/ButtonToggle.json +32 -19
  67. package/data/component-props/ButtonToggleLegacy.json +11 -11
  68. package/data/component-props/Callout.json +58 -17
  69. package/data/component-props/CellBasic.json +94 -41
  70. package/data/component-props/CellComponent.json +23 -7
  71. package/data/component-props/CellHeader.json +62 -19
  72. package/data/component-props/ComplexFilter.json +52 -21
  73. package/data/component-props/ContentCard.json +70 -47
  74. package/data/component-props/Dialog.json +47 -14
  75. package/data/component-props/Dropdown.json +67 -31
  76. package/data/component-props/DropdownMenu.json +128 -23
  77. package/data/component-props/HeatmapChart.json +88 -12
  78. package/data/component-props/Hero.json +80 -39
  79. package/data/component-props/Icon.json +20 -9
  80. package/data/component-props/InputCheckbox.json +36 -14
  81. package/data/component-props/InputDropdown.json +75 -27
  82. package/data/component-props/InputRadio.json +31 -13
  83. package/data/component-props/InputSearch.json +41 -18
  84. package/data/component-props/InputSlider.json +46 -19
  85. package/data/component-props/InputText.json +26 -19
  86. package/data/component-props/InputToggle.json +26 -9
  87. package/data/component-props/IntentMessage.json +38 -9
  88. package/data/component-props/Link.json +13 -7
  89. package/data/component-props/LoadingIndicator.json +11 -3
  90. package/data/component-props/MenuItem.json +38 -19
  91. package/data/component-props/MenuSelect.json +8 -8
  92. package/data/component-props/NavigationFooter.json +49 -19
  93. package/data/component-props/NavigationHeader.json +150 -37
  94. package/data/component-props/NavigationJumpTo.json +33 -7
  95. package/data/component-props/Notification.json +39 -21
  96. package/data/component-props/Pagination.json +39 -11
  97. package/data/component-props/Panel.json +62 -9
  98. package/data/component-props/Popover.json +80 -7
  99. package/data/component-props/PreComposedTable.json +99 -27
  100. package/data/component-props/SegmentedControl.json +42 -3
  101. package/data/component-props/StackedBarChart.json +116 -42
  102. package/data/component-props/TableRow.json +38 -19
  103. package/data/component-props/Tabs.json +66 -9
  104. package/data/component-props/Tag.json +34 -17
  105. package/data/component-props/TagFilter.json +10 -3
  106. package/data/component-props/Tooltip.json +49 -18
  107. package/data/component-props/TooltipCondensed.json +18 -9
  108. package/data/component-props/TooltipTable.json +17 -7
  109. package/data/resources/{zeroheight-rules.md → documentation-rules.md} +43 -30
  110. package/data/resources/figma-rules.md +2 -2
  111. package/dist/stdio.js +483 -780
  112. package/package.json +12 -8
  113. package/data/component-props/ButtonDropdownV2.json +0 -34
  114. package/data/component-props/ButtonNew.json +0 -47
  115. package/data/component-props/ButtonToggleV2.json +0 -44
  116. package/data/component-props/ButtonV2.json +0 -43
  117. package/data/zeroheight-cache.json +0 -10259
  118. package/data/zeroheight-exports/Accordion.md +0 -774
  119. package/data/zeroheight-exports/Banner.md +0 -691
  120. package/data/zeroheight-exports/Borders.md +0 -117
  121. package/data/zeroheight-exports/Buttons.md +0 -1854
  122. package/data/zeroheight-exports/Callout.md +0 -931
  123. package/data/zeroheight-exports/Colors.md +0 -1755
  124. package/data/zeroheight-exports/Content-Card.md +0 -309
  125. package/data/zeroheight-exports/Contributing-to-SDS.md +0 -98
  126. package/data/zeroheight-exports/Control-Inputs.md +0 -2818
  127. package/data/zeroheight-exports/Corners.md +0 -104
  128. package/data/zeroheight-exports/Cover-page.md +0 -3
  129. package/data/zeroheight-exports/Dialog.md +0 -1367
  130. package/data/zeroheight-exports/Downloads.md +0 -236
  131. package/data/zeroheight-exports/Drop-Shadows.md +0 -79
  132. package/data/zeroheight-exports/Dropdown-Input.md +0 -1776
  133. package/data/zeroheight-exports/Dropdown-Menus.md +0 -913
  134. package/data/zeroheight-exports/Element-Status-Tracker.md +0 -267
  135. package/data/zeroheight-exports/Field-Inputs.md +0 -1405
  136. package/data/zeroheight-exports/Filters.md +0 -1111
  137. package/data/zeroheight-exports/Getting-Started.md +0 -1157
  138. package/data/zeroheight-exports/Hero.md +0 -414
  139. package/data/zeroheight-exports/Icons.md +0 -2067
  140. package/data/zeroheight-exports/Intent.md +0 -86
  141. package/data/zeroheight-exports/Introduction-to-Bases.md +0 -35
  142. package/data/zeroheight-exports/Introduction-to-Cells.md +0 -35
  143. package/data/zeroheight-exports/Introduction-to-DNA.md +0 -35
  144. package/data/zeroheight-exports/Introduction-to-Genes.md +0 -35
  145. package/data/zeroheight-exports/Introduction.md +0 -115
  146. package/data/zeroheight-exports/Link.md +0 -432
  147. package/data/zeroheight-exports/Lists.md +0 -986
  148. package/data/zeroheight-exports/Loading-Indicator.md +0 -41
  149. package/data/zeroheight-exports/Navigation.md +0 -1190
  150. package/data/zeroheight-exports/Notification.md +0 -1038
  151. package/data/zeroheight-exports/Panel.md +0 -1030
  152. package/data/zeroheight-exports/README.md +0 -122
  153. package/data/zeroheight-exports/Responsive-Design.md +0 -330
  154. package/data/zeroheight-exports/Search-Input.md +0 -91
  155. package/data/zeroheight-exports/Search.md +0 -822
  156. package/data/zeroheight-exports/Segmented-Control.md +0 -609
  157. package/data/zeroheight-exports/Spacing.md +0 -297
  158. package/data/zeroheight-exports/Table.md +0 -5345
  159. package/data/zeroheight-exports/Tabs.md +0 -1324
  160. package/data/zeroheight-exports/Tags.md +0 -1545
  161. package/data/zeroheight-exports/Text-Link.md +0 -268
  162. package/data/zeroheight-exports/Theming.md +0 -362
  163. package/data/zeroheight-exports/Tooltips.md +0 -2015
  164. package/data/zeroheight-exports/Typography.md +0 -800
@@ -0,0 +1,647 @@
1
+ # Tag
2
+
3
+ ## Source Code
4
+
5
+ The component's source code in the SDS codebase can be found [here](https://github.com/chanzuckerberg/sci-components/blob/main/packages/components/src/core/Tag/index.tsx).
6
+
7
+ ## Import
8
+
9
+ **React TypeScript**
10
+
11
+ ```tsx
12
+ import { Tag } from "@czi-sds/components";
13
+ ```
14
+
15
+ ## Code examples
16
+
17
+ ### **Default Tag**
18
+
19
+ A tag with nothing but a label, next to the same tag asking for the rounded shape the design guidance prefers.
20
+
21
+ **Example: DefaultTag**
22
+
23
+ ```tsx
24
+ // A label is all a Tag needs. Everything else has a default: the neutral grey
25
+ // intent, the small size, and the square shape.
26
+ //
27
+ // Note that the component defaults to square while the design guidance above
28
+ // treats rounded as the shape to reach for, so a tag that should match the rest
29
+ // of the system asks for it: sdsStyle="rounded".
30
+
31
+ import {
32
+ Tag,
33
+ fontBodyXs,
34
+ getSemanticColors,
35
+ getSpaces,
36
+ type CommonThemeProps,
37
+ } from "@czi-sds/components";
38
+ import styled from "@emotion/styled";
39
+
40
+ const Stack = styled.div<CommonThemeProps>`
41
+ ${(props) => {
42
+ const spaces = getSpaces(props);
43
+
44
+ return `
45
+ display: flex;
46
+ flex-direction: column;
47
+ gap: ${spaces?.l}px;
48
+ `;
49
+ }}
50
+ `;
51
+
52
+ const Group = styled.div<CommonThemeProps>`
53
+ ${(props) => {
54
+ const spaces = getSpaces(props);
55
+
56
+ return `
57
+ align-items: center;
58
+ display: flex;
59
+ gap: ${spaces?.m}px;
60
+ `;
61
+ }}
62
+ `;
63
+
64
+ const Caption = styled.p<CommonThemeProps>`
65
+ ${fontBodyXs}
66
+
67
+ ${(props) => {
68
+ const semanticColors = getSemanticColors(props);
69
+
70
+ return `
71
+ color: ${semanticColors?.base?.textSecondary};
72
+ margin: 0;
73
+ min-width: 110px;
74
+ `;
75
+ }}
76
+ `;
77
+
78
+ function App() {
79
+ return (
80
+ <div className="app">
81
+ <Stack>
82
+ <Group>
83
+ <Caption>Square</Caption>
84
+ <Tag label="Science Design System" />
85
+ </Group>
86
+
87
+ <Group>
88
+ <Caption>Rounded</Caption>
89
+ <Tag label="Science Design System" sdsStyle="rounded" />
90
+ </Group>
91
+ </Stack>
92
+ </div>
93
+ );
94
+ }
95
+
96
+ export default App;
97
+ ```
98
+
99
+ ### Intents
100
+
101
+ The six intents, drawn as primary and then as secondary. A tag left without a color is neutral.
102
+
103
+ **Example: TagIntents**
104
+
105
+ ```tsx
106
+ // color carries the tag's intent. Six names are available, and neutral is what a
107
+ // tag falls back to when the prop is left out.
108
+ //
109
+ // sdsType picks how that intent is drawn: primary fills the tag with the intent
110
+ // color and sets the label white, secondary tints the fill and keeps the label in
111
+ // the intent color behind a matching border.
112
+
113
+ import {
114
+ Tag,
115
+ fontBodyXs,
116
+ getSemanticColors,
117
+ getSpaces,
118
+ type CommonThemeProps,
119
+ type SdsTagColorType,
120
+ } from "@czi-sds/components";
121
+ import styled from "@emotion/styled";
122
+
123
+ const INTENTS: Extract<SdsTagColorType, string>[] = [
124
+ "info",
125
+ "positive",
126
+ "notice",
127
+ "negative",
128
+ "neutral",
129
+ "beta",
130
+ ];
131
+
132
+ const Stack = styled.div<CommonThemeProps>`
133
+ ${(props) => {
134
+ const spaces = getSpaces(props);
135
+
136
+ return `
137
+ display: flex;
138
+ flex-direction: column;
139
+ gap: ${spaces?.l}px;
140
+ `;
141
+ }}
142
+ `;
143
+
144
+ const Row = styled.div<CommonThemeProps>`
145
+ ${(props) => {
146
+ const spaces = getSpaces(props);
147
+
148
+ return `
149
+ display: flex;
150
+ flex-wrap: wrap;
151
+ gap: ${spaces?.s}px;
152
+ `;
153
+ }}
154
+ `;
155
+
156
+ const Caption = styled.p<CommonThemeProps>`
157
+ ${fontBodyXs}
158
+
159
+ ${(props) => {
160
+ const semanticColors = getSemanticColors(props);
161
+ const spaces = getSpaces(props);
162
+
163
+ return `
164
+ color: ${semanticColors?.base?.textSecondary};
165
+ margin: 0 0 ${spaces?.xxs}px;
166
+ `;
167
+ }}
168
+ `;
169
+
170
+ function App() {
171
+ return (
172
+ <div className="app">
173
+ <Stack>
174
+ <div>
175
+ <Caption>Primary</Caption>
176
+ <Row>
177
+ {INTENTS.map((intent) => (
178
+ <Tag
179
+ color={intent}
180
+ key={intent}
181
+ label={intent}
182
+ sdsStyle="rounded"
183
+ />
184
+ ))}
185
+ </Row>
186
+ </div>
187
+
188
+ <div>
189
+ <Caption>Secondary</Caption>
190
+ <Row>
191
+ {INTENTS.map((intent) => (
192
+ <Tag
193
+ color={intent}
194
+ key={intent}
195
+ label={intent}
196
+ sdsStyle="rounded"
197
+ sdsType="secondary"
198
+ />
199
+ ))}
200
+ </Row>
201
+ </div>
202
+ </Stack>
203
+ </div>
204
+ );
205
+ }
206
+
207
+ export default App;
208
+ ```
209
+
210
+ ### Tag + Icon
211
+
212
+ A large tag, which has to carry an icon, beside a small one. Each uses an Icon whose own size matches the size the tag will draw it at.
213
+
214
+ **Example: TagIcon**
215
+
216
+ ```tsx
217
+ // An icon goes on the leading edge of a tag, and the large size requires one:
218
+ // TypeScript rejects sdsSize="l" without it.
219
+ //
220
+ // The tag draws whatever icon it is given at a fixed size: 12px in a small tag,
221
+ // 24px in a large one. Match the Icon's own sdsSize to that so the artwork is
222
+ // drawn at the size it was made for: s or xs for a small tag, l for a large one.
223
+ // Not every icon exists at both sizes: Virus below is large-only, so asking for it
224
+ // at a small size renders nothing and logs an error.
225
+
226
+ import { Icon, Tag } from "@czi-sds/components";
227
+ import styled from "@emotion/styled";
228
+ import {
229
+ fontBodyXs,
230
+ getSemanticColors,
231
+ getSpaces,
232
+ type CommonThemeProps,
233
+ } from "@czi-sds/components";
234
+
235
+ const Row = styled.div<CommonThemeProps>`
236
+ ${(props) => {
237
+ const spaces = getSpaces(props);
238
+
239
+ return `
240
+ align-items: center;
241
+ display: flex;
242
+ flex-wrap: wrap;
243
+ gap: ${spaces?.m}px;
244
+ `;
245
+ }}
246
+ `;
247
+
248
+ const Caption = styled.p<CommonThemeProps>`
249
+ ${fontBodyXs}
250
+
251
+ ${(props) => {
252
+ const semanticColors = getSemanticColors(props);
253
+ const spaces = getSpaces(props);
254
+
255
+ return `
256
+ color: ${semanticColors?.base?.textSecondary};
257
+ margin: 0 0 ${spaces?.xxs}px;
258
+ `;
259
+ }}
260
+ `;
261
+
262
+ function App() {
263
+ return (
264
+ <div className="app">
265
+ <Caption>
266
+ A large tag with a large icon, and a small tag with a small one
267
+ </Caption>
268
+ <Row>
269
+ <Tag
270
+ color="negative"
271
+ icon={<Icon sdsIcon="Virus" sdsSize="l" />}
272
+ label="Virus"
273
+ sdsSize="l"
274
+ sdsStyle="rounded"
275
+ />
276
+
277
+ <Tag
278
+ color="negative"
279
+ icon={<Icon sdsIcon="Bacteria" sdsSize="s" />}
280
+ label="Bacteria"
281
+ sdsStyle="rounded"
282
+ />
283
+ </Row>
284
+ </div>
285
+ );
286
+ }
287
+
288
+ export default App;
289
+ ```
290
+
291
+ ### Tag with custom colors
292
+
293
+ Colors given as a tuple, for a tag the intents do not cover. The two-value form leaves the icon white, so a tag with an icon wants all three.
294
+
295
+ **Example: TagWithCustomColors**
296
+
297
+ ```tsx
298
+ // color also takes a tuple of CSS colors for a tag the intents do not cover:
299
+ // [label, background] or [label, background, icon].
300
+ //
301
+ // The two-value form does not touch the icon, which stays white and disappears on
302
+ // a light background (the first tag below). A tag with an icon wants the
303
+ // three-value form, and the contrast of whatever colors you pick is on you, since
304
+ // SDS only guarantees it for its own intents.
305
+
306
+ import { Icon, Tag } from "@czi-sds/components";
307
+ import styled from "@emotion/styled";
308
+ import {
309
+ fontBodyXs,
310
+ getSemanticColors,
311
+ getSpaces,
312
+ type CommonThemeProps,
313
+ } from "@czi-sds/components";
314
+
315
+ const Stack = styled.div<CommonThemeProps>`
316
+ ${(props) => {
317
+ const spaces = getSpaces(props);
318
+
319
+ return `
320
+ display: flex;
321
+ flex-direction: column;
322
+ gap: ${spaces?.l}px;
323
+ `;
324
+ }}
325
+ `;
326
+
327
+ const Group = styled.div<CommonThemeProps>`
328
+ ${(props) => {
329
+ const spaces = getSpaces(props);
330
+
331
+ return `
332
+ align-items: center;
333
+ display: flex;
334
+ gap: ${spaces?.m}px;
335
+ `;
336
+ }}
337
+ `;
338
+
339
+ const Caption = styled.p<CommonThemeProps>`
340
+ ${fontBodyXs}
341
+
342
+ ${(props) => {
343
+ const semanticColors = getSemanticColors(props);
344
+
345
+ return `
346
+ color: ${semanticColors?.base?.textSecondary};
347
+ margin: 0;
348
+ min-width: 180px;
349
+ `;
350
+ }}
351
+ `;
352
+
353
+ function App() {
354
+ return (
355
+ <div className="app">
356
+ <Stack>
357
+ <Group>
358
+ <Caption>[label, background]</Caption>
359
+ <Tag
360
+ color={["#3b2f00", "#ffe6a0"]}
361
+ icon={<Icon sdsIcon="Star" sdsSize="l" />}
362
+ label="Icon left white"
363
+ sdsSize="l"
364
+ sdsStyle="rounded"
365
+ />
366
+ </Group>
367
+
368
+ <Group>
369
+ <Caption>[label, background, icon]</Caption>
370
+ <Tag
371
+ color={["#3b2f00", "#ffe6a0", "#b26f00"]}
372
+ icon={<Icon sdsIcon="Star" sdsSize="l" />}
373
+ label="Icon colored too"
374
+ sdsSize="l"
375
+ sdsStyle="rounded"
376
+ />
377
+ </Group>
378
+
379
+ <Group>
380
+ <Caption>No icon, two values</Caption>
381
+ <Tag
382
+ color={["#3b2f00", "#ffe6a0"]}
383
+ label="Label and background"
384
+ sdsStyle="rounded"
385
+ />
386
+ </Group>
387
+ </Stack>
388
+ </div>
389
+ );
390
+ }
391
+
392
+ export default App;
393
+ ```
394
+
395
+ ### Clickable and static tags
396
+
397
+ A tag with an `onClick` behaves as a button for both the pointer and the keyboard. A tag that only labels something uses `hover={false}` so it stops looking clickable.
398
+
399
+ **Example: InteractiveTag**
400
+
401
+ ```tsx
402
+ // A tag with an onClick becomes a button: it takes a tab stop, answers Enter and
403
+ // Space, and reports its label as its name. Use it for a tag that filters or
404
+ // navigates, not for one that only labels something.
405
+ //
406
+ // Every tag darkens under the pointer and shows a pointer cursor by default,
407
+ // including one that does nothing. hover={false} turns that off, and with it all
408
+ // pointer events, so a static tag stops looking clickable, but it also stops
409
+ // answering the mouse and stops triggering a Tooltip wrapped around it.
410
+
411
+ import {
412
+ Tag,
413
+ fontBodyXs,
414
+ getSemanticColors,
415
+ getSpaces,
416
+ type CommonThemeProps,
417
+ } from "@czi-sds/components";
418
+ import styled from "@emotion/styled";
419
+ import { useState } from "react";
420
+
421
+ const Stack = styled.div<CommonThemeProps>`
422
+ ${(props) => {
423
+ const spaces = getSpaces(props);
424
+
425
+ return `
426
+ display: flex;
427
+ flex-direction: column;
428
+ gap: ${spaces?.l}px;
429
+ `;
430
+ }}
431
+ `;
432
+
433
+ const Group = styled.div<CommonThemeProps>`
434
+ ${(props) => {
435
+ const spaces = getSpaces(props);
436
+
437
+ return `
438
+ align-items: center;
439
+ display: flex;
440
+ gap: ${spaces?.m}px;
441
+ `;
442
+ }}
443
+ `;
444
+
445
+ const Caption = styled.p<CommonThemeProps>`
446
+ ${fontBodyXs}
447
+
448
+ ${(props) => {
449
+ const semanticColors = getSemanticColors(props);
450
+
451
+ return `
452
+ color: ${semanticColors?.base?.textSecondary};
453
+ margin: 0;
454
+ min-width: 150px;
455
+ `;
456
+ }}
457
+ `;
458
+
459
+ const Readout = styled.p<CommonThemeProps>`
460
+ ${fontBodyXs}
461
+
462
+ ${(props) => {
463
+ const semanticColors = getSemanticColors(props);
464
+
465
+ return `
466
+ color: ${semanticColors?.base?.textSecondary};
467
+ margin: 0;
468
+ `;
469
+ }}
470
+ `;
471
+
472
+ function App() {
473
+ const [clicks, setClicks] = useState(0);
474
+
475
+ return (
476
+ <div className="app">
477
+ <Stack>
478
+ <Group>
479
+ <Caption>Clickable</Caption>
480
+ <Tag
481
+ color="info"
482
+ label="Filter by species"
483
+ onClick={() => setClicks((count) => count + 1)}
484
+ sdsStyle="rounded"
485
+ />
486
+ </Group>
487
+
488
+ <Group>
489
+ <Caption>Static</Caption>
490
+ <Tag hover={false} label="Read-only label" sdsStyle="rounded" />
491
+ </Group>
492
+
493
+ <Readout>
494
+ The clickable tag has been activated {clicks}{" "}
495
+ {clicks === 1 ? "time" : "times"}, by pointer or by keyboard.
496
+ </Readout>
497
+ </Stack>
498
+ </div>
499
+ );
500
+ }
501
+
502
+ export default App;
503
+ ```
504
+
505
+ ### A label with no room
506
+
507
+ What a long label does in a narrow container, and the Tooltip that keeps the truncated text reachable.
508
+
509
+ **Example: TagWithLongLabel**
510
+
511
+ ```tsx
512
+ // A tag never wraps: it stretches to its label and then, in a container too narrow
513
+ // for it, cuts the label off with an ellipsis. The text that is cut is not
514
+ // available anywhere else, so a tag that can hold a long value belongs in a
515
+ // Tooltip that carries the whole thing.
516
+ //
517
+ // The tooltip only works because the tag still receives pointer events. Adding
518
+ // hover={false} to quiet the hover styling would silence the tooltip with it.
519
+
520
+ import {
521
+ Tag,
522
+ Tooltip,
523
+ fontBodyXs,
524
+ getSemanticColors,
525
+ getSpaces,
526
+ type CommonThemeProps,
527
+ } from "@czi-sds/components";
528
+ import styled from "@emotion/styled";
529
+
530
+ const LABEL = "Homo sapiens lung epithelial cell";
531
+
532
+ const Stack = styled.div<CommonThemeProps>`
533
+ ${(props) => {
534
+ const spaces = getSpaces(props);
535
+
536
+ return `
537
+ display: flex;
538
+ flex-direction: column;
539
+ gap: ${spaces?.l}px;
540
+ `;
541
+ }}
542
+ `;
543
+
544
+ const NarrowColumn = styled.div<CommonThemeProps>`
545
+ ${(props) => {
546
+ const semanticColors = getSemanticColors(props);
547
+
548
+ return `
549
+ border: 1px dashed ${semanticColors?.base?.divider};
550
+ padding: 4px;
551
+ width: 160px;
552
+ `;
553
+ }}
554
+ `;
555
+
556
+ const Caption = styled.p<CommonThemeProps>`
557
+ ${fontBodyXs}
558
+
559
+ ${(props) => {
560
+ const semanticColors = getSemanticColors(props);
561
+ const spaces = getSpaces(props);
562
+
563
+ return `
564
+ color: ${semanticColors?.base?.textSecondary};
565
+ margin: 0 0 ${spaces?.xxs}px;
566
+ `;
567
+ }}
568
+ `;
569
+
570
+ function App() {
571
+ return (
572
+ <div className="app">
573
+ <Stack>
574
+ <div>
575
+ <Caption>Room for the whole label</Caption>
576
+ <Tag label={LABEL} sdsStyle="rounded" />
577
+ </div>
578
+
579
+ <div>
580
+ <Caption>
581
+ Cut off in a 160px column, with the full text on hover
582
+ </Caption>
583
+ <NarrowColumn>
584
+ <Tooltip placement="top" title={LABEL}>
585
+ <Tag label={LABEL} sdsStyle="rounded" />
586
+ </Tooltip>
587
+ </NarrowColumn>
588
+ </div>
589
+ </Stack>
590
+ </div>
591
+ );
592
+ }
593
+
594
+ export default App;
595
+ ```
596
+
597
+ ## SDS vs MUI
598
+
599
+ SDS Tag wraps MUI's Chip and replaces its palette, sizing and shape with SDS ones. SDS also splits the Chip's two jobs in two: Tag labels something, and TagFilter is the tag that can be removed. The differences from MUI are these:
600
+
601
+ - `sdsStyle`: `"square"` or `"rounded"`. The component defaults to `"square"`, while the design guidance above treats rounded as the shape to reach for, so a tag that should match the rest of the system asks for it explicitly.
602
+
603
+ - `sdsType`: `"primary"` (default) fills the tag with the intent color and sets the label white; `"secondary"` tints the fill, keeps the label in the intent color and draws a 1px border in it.
604
+
605
+ - `sdsSize`: `"s"` (default) or `"l"`, which is the pair of sizes the design carries rather than MUI's `"small"` and `"medium"`. A large tag must have an icon: TypeScript rejects `sdsSize="l"` without one.
606
+
607
+ - `color`: an SDS intent rather than one of MUI's palette names, since SDS hands MUI a fixed color of its own and uses this prop for the fill, the label and the icon. Six intents are available and a tag without the prop is neutral. It also takes a tuple of CSS colors for cases the intents do not cover.
608
+
609
+ - `hover`: on by default, which draws the hover and pressed states and a pointer cursor on every tag, whether or not anything happens when it is clicked. Setting it to `false` removes those states by taking the tag out of pointer events entirely, which also stops a Tooltip wrapped around it from opening.
610
+
611
+ - **Sizing and variant props do nothing:** MUI's `size` and `variant` set their classes but SDS pins the height, padding, fill and border, so a tag looks the same either way. MUI's `clickable` does have an effect, and not a useful one: it makes the tag a tab stop that does nothing. Pass `onClick` instead.
612
+
613
+ - **onDelete works, but off-brand:** a Tag given `onDelete` does become deletable, drawing MUI's filled-circle Cancel icon rather than the SDS X. Reach for TagFilter when a tag needs to come off.
614
+
615
+ ## MUI Documentation
616
+
617
+ Documentation for the underlying MUI component can be found [here](https://mui.com/material-ui/react-chip/).
618
+
619
+ ## Behavior and accessibility
620
+
621
+ - A plain tag is a div holding its label, with no role and no tab stop, and is read as the text it shows. Giving it an `onClick` turns it into a button: it takes a tab stop, answers Enter and Space, and takes its accessible name from the label.
622
+
623
+ - Because `hover` is on by default, a tag that only labels something still darkens under the pointer and shows a pointer cursor, which reads as clickable. `hover={false}` settles that, at the cost of all pointer events, so do not combine it with `onClick`, which would leave the tag reachable by keyboard but dead to the mouse.
624
+
625
+ - Nothing about the intent reaches assistive technology: `color` is color only, so a negative tag needs a label that says what is wrong rather than relying on red.
626
+
627
+ - A tag never wraps. It stretches to fit its label and then, in a container too narrow, cuts the label off with an ellipsis, leaving the rest of the text nowhere else to be read. A tag that can hold a long value belongs in a Tooltip carrying the whole string.
628
+
629
+ - Icons are drawn at a fixed size (12px in a small tag, 24px in a large one) whatever size the Icon itself asks for, so match the Icon's `sdsSize` to the tag: `"s"` or `"xs"` for a small tag, `"l"` for a large one. Some icons exist at only one of those sizes, Star and Virus among them, and asking for one at a size it does not have renders nothing and logs an error.
630
+
631
+ - The two-value form of a custom `color` leaves the icon white rather than coloring it with the label, so it vanishes on a light fill; a tag with an icon wants the three-value form. On a secondary tag, custom colors also draw the border in the fill color, which hides it. Contrast is yours to check. SDS only guarantees it for its own intents.
632
+
633
+ ## Props
634
+
635
+ Any custom SDS props and MUI props required for implementation are found on the table below. See the MUI documentation for additional optional props.
636
+
637
+ | Name | Type | Default | Description |
638
+ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
639
+ | `label` | `string` | - (required) | The tag's text, and its accessible name. It is cut off with an ellipsis rather than wrapped when there is not room for it. |
640
+ | `color` | `"info"` \| `"positive"` \| `"notice"` \| `"negative"` \| `"neutral"` \| `"beta"` \| `[string, string]` \| `[string, string, string]` | `"neutral"` | The tag's intent, given either as one of the six names or as CSS colors: 1. [label color, background color]: the icon stays white 2. [label color, background color, icon color] |
641
+ | `sdsType` | `"primary"` \| `"secondary"` | `"primary"` | primary fills the tag with the intent color and sets the label white. secondary tints the fill and keeps the label and a 1px border in the intent color. |
642
+ | `sdsStyle` | `"square"` \| `"rounded"` | `"square"` | The shape of the tag. The design guidance treats rounded as the default for the system, so it is usually worth passing. |
643
+ | `sdsSize` | `"s" \| "l"` | `"s"` | The size of the tag: an 11px label with a 12px icon, or a 13px label with a 24px icon. A large tag has to have an icon. |
644
+ | `icon` | `JSX.Element` | - | An icon on the leading edge, usually an SDS Icon. It is drawn at the tag's icon size whatever size it asks for, so match its `sdsSize` to the tag. |
645
+ | `hover` | `boolean` | `true` | Whether the tag responds to the pointer with a darker fill and a pointer cursor. False removes the tag from pointer events altogether, which also keeps a surrounding Tooltip from opening. |
646
+ | `onClick` | `(event) => void` | - | MUI's prop. Makes the tag a button: a tab stop that answers Enter and Space. |
647
+ | `onDelete` | `(event) => void` | - | MUI's prop. Adds a delete control, drawn with MUI's Cancel icon rather than the SDS X. Use TagFilter for a removable tag instead. |