@czi-sds/mcp 0.16.0 → 0.18.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.
- package/README.md +2 -1
- package/data/component-docs/Accordion.md +291 -0
- package/data/component-docs/Autocomplete.md +525 -0
- package/data/component-docs/Banner.md +231 -0
- package/data/component-docs/Button.md +224 -0
- package/data/component-docs/ButtonDropdown.md +256 -0
- package/data/component-docs/ButtonGroup.md +320 -0
- package/data/component-docs/ButtonToggle.md +397 -0
- package/data/component-docs/Callout.md +268 -0
- package/data/component-docs/CellBasic.md +122 -0
- package/data/component-docs/CellComponent.md +63 -0
- package/data/component-docs/CellHeader.md +128 -0
- package/data/component-docs/ComplexFilter.md +294 -0
- package/data/component-docs/ContentCard.md +406 -0
- package/data/component-docs/Dialog.md +651 -0
- package/data/component-docs/Dropdown.md +155 -0
- package/data/component-docs/DropdownMenu.md +949 -0
- package/data/component-docs/HeatmapChart.md +782 -0
- package/data/component-docs/Hero.md +363 -0
- package/data/component-docs/Icon.md +283 -0
- package/data/component-docs/InputCheckbox.md +205 -0
- package/data/component-docs/InputDropdown.md +482 -0
- package/data/component-docs/InputRadio.md +173 -0
- package/data/component-docs/InputSearch.md +81 -0
- package/data/component-docs/InputSlider.md +189 -0
- package/data/component-docs/InputText.md +110 -0
- package/data/component-docs/InputToggle.md +141 -0
- package/data/component-docs/IntentMessage.md +293 -0
- package/data/component-docs/Legend.md +442 -0
- package/data/component-docs/Link.md +23 -0
- package/data/component-docs/List.md +300 -0
- package/data/component-docs/LoadingIndicator.md +198 -0
- package/data/component-docs/Menu.md +298 -0
- package/data/component-docs/MenuItem.md +100 -0
- package/data/component-docs/NavigationFooter.md +165 -0
- package/data/component-docs/NavigationHeader.md +500 -0
- package/data/component-docs/NavigationJumpTo.md +414 -0
- package/data/component-docs/Notification.md +288 -0
- package/data/component-docs/Pagination.md +67 -0
- package/data/component-docs/Panel.md +636 -0
- package/data/component-docs/Popover.md +448 -0
- package/data/component-docs/PreComposedTable.md +2947 -0
- package/data/component-docs/ProteinStructureViewer.md +1044 -0
- package/data/component-docs/SegmentedControl.md +396 -0
- package/data/component-docs/StackedBarChart.md +475 -0
- package/data/component-docs/Table.md +2000 -0
- package/data/component-docs/TableHeader.md +53 -0
- package/data/component-docs/TableRow.md +74 -0
- package/data/component-docs/Tabs.md +455 -0
- package/data/component-docs/Tag.md +647 -0
- package/data/component-docs/TagFilter.md +131 -0
- package/data/component-docs/Tooltip.md +561 -0
- package/data/component-docs/TooltipCondensed.md +203 -0
- package/data/component-docs/TooltipTable.md +145 -0
- package/data/component-docs/index.json +267 -0
- package/data/component-list.json +2 -5
- package/data/component-props/Accordion.json +31 -11
- package/data/component-props/Alert.json +3 -3
- package/data/component-props/Autocomplete.json +150 -15
- package/data/component-props/Banner.json +31 -17
- package/data/component-props/Button.json +45 -20
- package/data/component-props/ButtonDropdown.json +36 -17
- package/data/component-props/ButtonDropdownLegacy.json +11 -11
- package/data/component-props/ButtonGroup.json +32 -11
- package/data/component-props/ButtonIcon.json +10 -10
- package/data/component-props/ButtonLegacy.json +19 -19
- package/data/component-props/ButtonToggle.json +32 -19
- package/data/component-props/ButtonToggleLegacy.json +11 -11
- package/data/component-props/Callout.json +58 -17
- package/data/component-props/CellBasic.json +94 -41
- package/data/component-props/CellComponent.json +23 -7
- package/data/component-props/CellHeader.json +62 -19
- package/data/component-props/ComplexFilter.json +52 -21
- package/data/component-props/ContentCard.json +70 -47
- package/data/component-props/Dialog.json +47 -14
- package/data/component-props/Dropdown.json +68 -31
- package/data/component-props/DropdownMenu.json +128 -23
- package/data/component-props/HeatmapChart.json +88 -12
- package/data/component-props/Hero.json +80 -39
- package/data/component-props/Icon.json +20 -9
- package/data/component-props/InputCheckbox.json +36 -14
- package/data/component-props/InputDropdown.json +75 -27
- package/data/component-props/InputRadio.json +31 -13
- package/data/component-props/InputSearch.json +41 -18
- package/data/component-props/InputSlider.json +46 -19
- package/data/component-props/InputText.json +26 -19
- package/data/component-props/InputToggle.json +26 -9
- package/data/component-props/IntentMessage.json +38 -9
- package/data/component-props/Link.json +13 -7
- package/data/component-props/LoadingIndicator.json +11 -3
- package/data/component-props/MenuItem.json +38 -19
- package/data/component-props/MenuSelect.json +8 -8
- package/data/component-props/NavigationFooter.json +49 -19
- package/data/component-props/NavigationHeader.json +150 -37
- package/data/component-props/NavigationJumpTo.json +33 -7
- package/data/component-props/Notification.json +39 -21
- package/data/component-props/Pagination.json +39 -11
- package/data/component-props/Panel.json +62 -9
- package/data/component-props/Popover.json +80 -7
- package/data/component-props/PreComposedTable.json +99 -27
- package/data/component-props/ProteinStructureViewer.json +117 -0
- package/data/component-props/SegmentedControl.json +42 -3
- package/data/component-props/StackedBarChart.json +116 -42
- package/data/component-props/TableRow.json +38 -19
- package/data/component-props/Tabs.json +66 -9
- package/data/component-props/Tag.json +34 -17
- package/data/component-props/TagFilter.json +10 -3
- package/data/component-props/Tooltip.json +49 -18
- package/data/component-props/TooltipCondensed.json +18 -9
- package/data/component-props/TooltipTable.json +17 -7
- package/data/resources/{zeroheight-rules.md → documentation-rules.md} +43 -30
- package/data/resources/figma-rules.md +2 -2
- package/data/tailwind.json +20 -14
- package/dist/stdio.js +112 -208
- package/package.json +9 -5
- package/data/component-props/ButtonDropdownV2.json +0 -34
- package/data/component-props/ButtonNew.json +0 -47
- package/data/component-props/ButtonToggleV2.json +0 -44
- package/data/component-props/ButtonV2.json +0 -43
- package/data/zeroheight-cache.json +0 -10259
- package/data/zeroheight-exports/Accordion.md +0 -774
- package/data/zeroheight-exports/Banner.md +0 -691
- package/data/zeroheight-exports/Borders.md +0 -117
- package/data/zeroheight-exports/Buttons.md +0 -1854
- package/data/zeroheight-exports/Callout.md +0 -931
- package/data/zeroheight-exports/Colors.md +0 -1755
- package/data/zeroheight-exports/Content-Card.md +0 -309
- package/data/zeroheight-exports/Contributing-to-SDS.md +0 -98
- package/data/zeroheight-exports/Control-Inputs.md +0 -2818
- package/data/zeroheight-exports/Corners.md +0 -104
- package/data/zeroheight-exports/Cover-page.md +0 -3
- package/data/zeroheight-exports/Dialog.md +0 -1367
- package/data/zeroheight-exports/Downloads.md +0 -236
- package/data/zeroheight-exports/Drop-Shadows.md +0 -79
- package/data/zeroheight-exports/Dropdown-Input.md +0 -1776
- package/data/zeroheight-exports/Dropdown-Menus.md +0 -913
- package/data/zeroheight-exports/Element-Status-Tracker.md +0 -267
- package/data/zeroheight-exports/Field-Inputs.md +0 -1405
- package/data/zeroheight-exports/Filters.md +0 -1111
- package/data/zeroheight-exports/Getting-Started.md +0 -1157
- package/data/zeroheight-exports/Hero.md +0 -414
- package/data/zeroheight-exports/Icons.md +0 -2067
- package/data/zeroheight-exports/Intent.md +0 -86
- package/data/zeroheight-exports/Introduction-to-Bases.md +0 -35
- package/data/zeroheight-exports/Introduction-to-Cells.md +0 -35
- package/data/zeroheight-exports/Introduction-to-DNA.md +0 -35
- package/data/zeroheight-exports/Introduction-to-Genes.md +0 -35
- package/data/zeroheight-exports/Introduction.md +0 -115
- package/data/zeroheight-exports/Link.md +0 -432
- package/data/zeroheight-exports/Lists.md +0 -986
- package/data/zeroheight-exports/Loading-Indicator.md +0 -41
- package/data/zeroheight-exports/Navigation.md +0 -1190
- package/data/zeroheight-exports/Notification.md +0 -1038
- package/data/zeroheight-exports/Panel.md +0 -1030
- package/data/zeroheight-exports/README.md +0 -122
- package/data/zeroheight-exports/Responsive-Design.md +0 -330
- package/data/zeroheight-exports/Search-Input.md +0 -91
- package/data/zeroheight-exports/Search.md +0 -822
- package/data/zeroheight-exports/Segmented-Control.md +0 -609
- package/data/zeroheight-exports/Spacing.md +0 -297
- package/data/zeroheight-exports/Table.md +0 -5345
- package/data/zeroheight-exports/Tabs.md +0 -1324
- package/data/zeroheight-exports/Tags.md +0 -1545
- package/data/zeroheight-exports/Text-Link.md +0 -268
- package/data/zeroheight-exports/Theming.md +0 -362
- package/data/zeroheight-exports/Tooltips.md +0 -2015
- 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. |
|