@czi-sds/mcp 0.20.2 → 0.21.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.
@@ -231,20 +231,8 @@ const OPTIONS: DefaultAutocompleteOption[] = [
231
231
  <div>
232
232
  Available labels
233
233
  <div style={{ display: "flex", gap: 4, marginTop: 4 }}>
234
- <Tag
235
- color="positive"
236
- hover={false}
237
- label="curated"
238
- sdsStyle="square"
239
- sdsType="secondary"
240
- />
241
- <Tag
242
- color="notice"
243
- hover={false}
244
- label="draft"
245
- sdsStyle="square"
246
- sdsType="secondary"
247
- />
234
+ <Tag color="positive" label="curated" sdsStyle="outline" />
235
+ <Tag color="notice" label="draft" sdsStyle="outline" />
248
236
  </div>
249
237
  </div>
250
238
  ),
@@ -0,0 +1,160 @@
1
+ # Chip
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/Chip/index.tsx).
6
+
7
+ ## Import
8
+
9
+ **React TypeScript**
10
+
11
+ ```tsx
12
+ import { Chip } from "@czi-sds/components";
13
+ ```
14
+
15
+ > **Coming from TagFilter?** Chip is the reworked TagFilter, renamed in SDS 25. The previous TagFilter still ships unchanged, and deprecated, so nothing breaks until you move to Chip. "Migrating from TagFilter" below covers what changes when you do.
16
+
17
+ ## Code examples
18
+
19
+ ### Default Chip
20
+
21
+ A row of applied filters, solid and outlined, each removing itself from the page's state through `onDelete`. The row is a named group, which tells screen reader users what the chips are removing.
22
+
23
+ **Example: DefaultChip**
24
+
25
+ ```tsx
26
+ // Chip is the tag that comes off: onDelete is required, and removing the chip
27
+ // from your own state is what makes it disappear. The whole chip is the remove
28
+ // control, so a click anywhere on it, Enter or Space, and Backspace or Delete
29
+ // all call onDelete.
30
+ //
31
+ // Each chip is one tab stop, named "Remove" followed by its label. sdsStyle picks
32
+ // between the solid accent fill and the outlined one.
33
+
34
+ import {
35
+ Chip,
36
+ fontBodyXs,
37
+ getSemanticColors,
38
+ getSpaces,
39
+ type CommonThemeProps,
40
+ } from "@czi-sds/components";
41
+ import styled from "@emotion/styled";
42
+ import { useState } from "react";
43
+
44
+ const FILTERS = ["Homo sapiens", "Lung", "10x 3' v3", "Healthy"];
45
+
46
+ const Row = styled.div<CommonThemeProps>`
47
+ ${(props) => {
48
+ const spaces = getSpaces(props);
49
+
50
+ return `
51
+ display: flex;
52
+ flex-wrap: wrap;
53
+ gap: ${spaces?.s}px;
54
+ margin-bottom: ${spaces?.m}px;
55
+ min-height: 24px;
56
+ `;
57
+ }}
58
+ `;
59
+
60
+ const Readout = styled.p<CommonThemeProps>`
61
+ ${fontBodyXs}
62
+
63
+ ${(props) => {
64
+ const semanticColors = getSemanticColors(props);
65
+
66
+ return `
67
+ color: ${semanticColors?.base?.textSecondary};
68
+ margin: 0;
69
+ `;
70
+ }}
71
+ `;
72
+
73
+ function App() {
74
+ const [filters, setFilters] = useState(FILTERS);
75
+
76
+ const remove = (filter: string) =>
77
+ setFilters((current) => current.filter((item) => item !== filter));
78
+
79
+ return (
80
+ <div className="app">
81
+ <Row aria-label="Applied filters" role="group">
82
+ {filters.map((filter, index) => (
83
+ <Chip
84
+ key={filter}
85
+ label={filter}
86
+ onDelete={() => remove(filter)}
87
+ sdsStyle={index % 2 === 0 ? "solid" : "outline"}
88
+ />
89
+ ))}
90
+ </Row>
91
+
92
+ <Readout>
93
+ {filters.length > 0
94
+ ? `${filters.length} of ${FILTERS.length} filters applied`
95
+ : "No filters applied"}
96
+ </Readout>
97
+ </div>
98
+ );
99
+ }
100
+
101
+ export default App;
102
+ ```
103
+
104
+ ## SDS vs MUI
105
+
106
+ Chip is built on the SDS Tag, and so on MUI's Chip, but it exists for one job: showing which Filters are applied and letting them be taken off again:
107
+
108
+ - **onDelete is required.** MUI treats it as the switch that decides whether a chip can be deleted; here removal is the chip's whole purpose, so the handler has to be there. Removing the chip from your own state is what makes it disappear.
109
+
110
+ - **The whole chip removes it:** a click anywhere on the chip calls `onDelete`, not only a click on the X. An `onClick` of your own runs first.
111
+
112
+ - `sdsStyle`: `"solid"` (default) fills the chip with the accent color; `"outline"` tints it and draws the label, the X and a 1px border in the accent color. Everything else about the look is fixed: the accent intent, the medium size, the 4px corners and the 12px X. Tag's `color`, `size`, `href` and `showLinkIcon` are not part of the type.
113
+
114
+ - **The X cannot be swapped:** SDS applies its own `deleteIcon` after your props, so a `deleteIcon` of your own is ignored without a warning.
115
+
116
+ ## MUI Documentation
117
+
118
+ Documentation for the underlying MUI component can be found [here](https://mui.com/material-ui/react-chip/).
119
+
120
+ ## Behavior and accessibility
121
+
122
+ - Each chip is a single button and a single tab stop. It answers a click, Enter and Space, and also Backspace and Delete, and every one of them calls `onDelete`. The X is decorative and hidden from screen readers.
123
+
124
+ - The chip is named "Remove" followed by its label, such as "Remove Lung", so the name says what activating it does. Pass `aria-label` to word it differently, for instance in another language. A row of filters is still worth wrapping in a group with a name of its own; the example above uses `role="group"` with an `aria-label`.
125
+
126
+ - Removing a chip takes the focused element out of the page, so move focus somewhere sensible afterwards, such as the next chip or the filter control that added it.
127
+
128
+ - Like a Tag, a chip does not wrap: a long filter value is cut off with an ellipsis. Keep the values short, or shorten them yourself so the part that survives is the part that matters.
129
+
130
+ ## Migrating from TagFilter
131
+
132
+ `TagFilter` is deprecated but still exported, with the look and behavior it had in SDS 24, so an app can upgrade first and move to Chip later. The props are the same, so the move starts with the name:
133
+
134
+ **React TypeScript**
135
+
136
+ ```tsx
137
+ // Before
138
+ <TagFilter label="Lung" onDelete={handleDelete} />
139
+ // After
140
+ <Chip label="Lung" onDelete={handleDelete} />
141
+ ```
142
+
143
+ Then check each call site for what behaves differently:
144
+
145
+ - **The whole chip removes the filter,** not only the X. An `onClick` that also removed the filter now removes it twice; drop it and keep `onDelete`.
146
+
147
+ - **One tab stop instead of two.** The X is no longer a button of its own. Tests that looked for a button named "Delete Tag" should look for the chip, named "Remove" followed by its label.
148
+
149
+ - **The new design:** a regular-weight 13px label and 6px padding, and a choice of `sdsStyle`.
150
+
151
+ ## Props
152
+
153
+ Any custom SDS props and MUI props required for implementation are found on the table below. See the MUI documentation for additional optional props.
154
+
155
+ | Name | Type | Default | Description |
156
+ | ------------ | ------------------------ | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
157
+ | `label` | `string` | - (required) | The filter's text. Cut off with an ellipsis when there is not room for it. |
158
+ | `onDelete` | `function` | - (required) | Runs when the chip is clicked or activated with Enter or Space, and when Backspace or Delete is pressed on it. Drop the filter from your state here; the component does not remove itself. **Signature:** `function(event: SyntheticEvent) => void` |
159
+ | `sdsStyle` | `"solid"` \| `"outline"` | `"solid"` | `solid` fills the chip with the accent color. `outline` tints it and draws the label, the X and a 1px border in the accent color. |
160
+ | `aria-label` | `string` | `"Remove {label}"` | The chip's accessible name, "Remove" followed by the label unless set. Override it to word the removal differently. |
@@ -132,19 +132,19 @@ export default App;
132
132
 
133
133
  ## Props
134
134
 
135
- | Name | Type | Default | Description |
136
- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------ |
137
- | `backgroundAppearance` | `"matchBackground"` \| `"dark"` | `"matchBackground"` | `"dark"` puts the footer on a dark surface and inverts its text and dividers, in light mode only. |
138
- | `images` | `FooterImage[]` | - | An array of images displayed in the footer. Each item includes an image, optional link URL, and component. |
139
- | `logo` | `ReactNode` | - | The logo displayed in the footer. Can be any valid React node such as an image, icon, or SVG. |
140
- | `logoUrl` | `string` | - | If provided, clicking the logo will navigate to this URL. |
141
- | `logoComponent` | `ElementType` | `"a"` | Specifies the component to use for the logo link. Defaults to an anchor tag. |
142
- | `logoLinkProps` | `Record<string, unknown>` | - | Additional props passed to the logo link component. |
143
- | `navItems` | `NavigationFooterNavItem[]` | - | The prominent links on the top row, next to the logo. They are headings, not body text, and get no dividers. |
144
- | `navLinks` | `NavigationFooterNavItem[]` | - | The smaller links on the bottom row, drawn in one line with dividers between them. |
145
- | `tag` | `string` | - | A small label displayed next to the title. |
146
- | `tagColor` | `"info" \| "positive"` \| `"notice" \| "negative"` \| `"neutral" \| "beta"` \| `[string, string]` \| `[string, string, string]` | - | The Tag's color. A tuple sets the label, background, and icon colors by hand. |
147
- | `title` | `string` | - | The main title displayed in the footer. |
135
+ | Name | Type | Default | Description |
136
+ | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------- |
137
+ | `backgroundAppearance` | `"matchBackground"` \| `"dark"` | `"matchBackground"` | `"dark"` puts the footer on a dark surface and inverts its text and dividers, in light mode only. |
138
+ | `images` | `FooterImage[]` | - | An array of images displayed in the footer. Each item includes an image, optional link URL, and component. |
139
+ | `logo` | `ReactNode` | - | The logo displayed in the footer. Can be any valid React node such as an image, icon, or SVG. |
140
+ | `logoUrl` | `string` | - | If provided, clicking the logo will navigate to this URL. |
141
+ | `logoComponent` | `ElementType` | `"a"` | Specifies the component to use for the logo link. Defaults to an anchor tag. |
142
+ | `logoLinkProps` | `Record<string, unknown>` | - | Additional props passed to the logo link component. |
143
+ | `navItems` | `NavigationFooterNavItem[]` | - | The prominent links on the top row, next to the logo. They are headings, not body text, and get no dividers. |
144
+ | `navLinks` | `NavigationFooterNavItem[]` | - | The smaller links on the bottom row, drawn in one line with dividers between them. |
145
+ | `tag` | `string` | - | A small label displayed next to the title. |
146
+ | `tagColor` | `"accent" \| "beta"` \| `"info" \| "negative"` \| `"neutral" \| "notice"` \| `"positive"` \| `[string, string]` \| `[string, string, string]` | - | The intent of the small, solid Tag beside the title. A tuple sets the label, background, and icon colors by hand. |
147
+ | `title` | `string` | - | The main title displayed in the footer. |
148
148
 
149
149
  ## FooterImage
150
150
 
@@ -431,32 +431,32 @@ In the narrow layout both styles collapse to accordions inside the drawer, and t
431
431
 
432
432
  Any custom SDS props and MUI props required for implementation are found on the table below. See the MUI documentation for additional optional props.
433
433
 
434
- | Name | Type | Default | Description |
435
- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
436
- | `activePrimaryNavKey` | `string` | - | The key of the active primary item. Optional, since the header tracks this itself; when given, it overrides the internal value. |
437
- | `setActivePrimaryNavKey` | `(key: string) => void` | - | Called when a primary item becomes active. The header updates its internal key as well, so this is a notification rather than the only way the value changes. |
438
- | `backgroundAppearance` | `"matchBackground"` \| `"dark"` | `"matchBackground"` | `"dark"` puts the header on a dark surface and inverts its contents. It only changes anything in light mode. |
439
- | `buttons` | `Partial<ButtonProps>[]` \| `ReactNode[]` | - | Actions at the right end of the bar. Prop objects render as SDS Buttons; elements are cloned with the header's appearance applied. An icon-only button gets an `aria-label` from its child, and in the narrow layout every button goes full width and closes the drawer when clicked. |
440
- | `sdsStyle` | `"dropdown"` \| `"drawer"` | `"dropdown"` | How dropdown nav items open, and which parts of their data are used. See the comparison above. |
441
- | `drawerOpen` | `boolean` | - | Controls the narrow layout's drawer. Leave both this and `setDrawerOpen` out to let the hamburger manage it. |
442
- | `setDrawerOpen` | `(open: boolean) => void` | - | Replaces the drawer's internal state update, so it has to be paired with `drawerOpen` or the drawer stops opening. |
443
- | `isSticky` | `boolean` | `true` | Whether the header sticks to the top on scroll. Ignored when `sdsStyle` is `"drawer"`, which is always sticky, and best left alone alongside `topComponentSlot`. |
444
- | `menuProps` | [`Partial<MenuProps>`](https://mui.com/material-ui/api/menu/) | `{ disableScrollLock: true, disablePortal: true }` | Props for the dropdown menus. Passing this replaces the default object rather than merging with it. |
445
- | `topComponentSlot` | `ReactNode` | - | Content rendered above the header, such as a Banner. The header measures it and offsets its own sticky top to match. |
446
- | `onDrawerStyleNavItemHover` | `function` | - | `(item: NavigationHeaderPrimaryNavItem<T> \| NavigationHeaderSecondaryNavItem) => void`. Called with the hovered primary or secondary item while `sdsStyle` is `"drawer"`. Useful for prefetching what the panel will show. |
447
- | `logo` | `ReactNode` | - | The logo displayed in the header. Can be an image, icon, svg or any `ReactNode`. |
448
- | `logoUrl` | `string` | - | URL for the logo link. If provided, clicking the logo navigates to this URL. |
449
- | `logoLinkComponent` | `ElementType` | `"a"` | Specifies the component to use for the logo link. |
450
- | `logoLinkProps` | [`LinkProps`](https://mui.com/material-ui/api/link/) | - | Props to pass to the logo link component. |
451
- | `primaryNavItems` | `NavigationHeaderPrimaryNavItem<T>[]` | - | List of items for the primary navigation section. |
452
- | `primaryNavPosition` | `"left" \|"right"` | `"left"` | Position of the `primaryNavItems` list. If set to `"left"`, the items appear to the left of the search bar. If set to `"right"`, they are positioned next to the `secondaryNavItems` on the right. |
453
- | `showSearch` | `boolean` | `true` | Whether to display the search input in the header. |
454
- | `searchProps` | `Partial<InputSearchProps>` | - | Props passed to the search input component. |
455
- | `secondaryNavItems` | `NavigationHeaderSecondaryNavItem[]` | - | List of items for the secondary navigation section. |
456
- | `scrollElevation` | `boolean` | `true` | Controls whether a shadow is shown under the Nav when scrolling. |
457
- | `tag` | `string` | - | A small label displayed next to the title. |
458
- | `tagColor` | `"info"` \| `"positive"` \| `"notice"` \| `"negative"` \| `"neutral"` \| `"beta"` \| `[string, string]` \| `[string, string, string]` | `"neutral"` | The color of the tag label. |
459
- | `title` | `string` | - | The main title displayed in the header. |
434
+ | Name | Type | Default | Description |
435
+ | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
436
+ | `activePrimaryNavKey` | `string` | - | The key of the active primary item. Optional, since the header tracks this itself; when given, it overrides the internal value. |
437
+ | `setActivePrimaryNavKey` | `(key: string) => void` | - | Called when a primary item becomes active. The header updates its internal key as well, so this is a notification rather than the only way the value changes. |
438
+ | `backgroundAppearance` | `"matchBackground"` \| `"dark"` | `"matchBackground"` | `"dark"` puts the header on a dark surface and inverts its contents. It only changes anything in light mode. |
439
+ | `buttons` | `Partial<ButtonProps>[]` \| `ReactNode[]` | - | Actions at the right end of the bar. Prop objects render as SDS Buttons; elements are cloned with the header's appearance applied. An icon-only button gets an `aria-label` from its child, and in the narrow layout every button goes full width and closes the drawer when clicked. |
440
+ | `sdsStyle` | `"dropdown"` \| `"drawer"` | `"dropdown"` | How dropdown nav items open, and which parts of their data are used. See the comparison above. |
441
+ | `drawerOpen` | `boolean` | - | Controls the narrow layout's drawer. Leave both this and `setDrawerOpen` out to let the hamburger manage it. |
442
+ | `setDrawerOpen` | `(open: boolean) => void` | - | Replaces the drawer's internal state update, so it has to be paired with `drawerOpen` or the drawer stops opening. |
443
+ | `isSticky` | `boolean` | `true` | Whether the header sticks to the top on scroll. Ignored when `sdsStyle` is `"drawer"`, which is always sticky, and best left alone alongside `topComponentSlot`. |
444
+ | `menuProps` | [`Partial<MenuProps>`](https://mui.com/material-ui/api/menu/) | `{ disableScrollLock: true, disablePortal: true }` | Props for the dropdown menus. Passing this replaces the default object rather than merging with it. |
445
+ | `topComponentSlot` | `ReactNode` | - | Content rendered above the header, such as a Banner. The header measures it and offsets its own sticky top to match. |
446
+ | `onDrawerStyleNavItemHover` | `function` | - | `(item: NavigationHeaderPrimaryNavItem<T> \| NavigationHeaderSecondaryNavItem) => void`. Called with the hovered primary or secondary item while `sdsStyle` is `"drawer"`. Useful for prefetching what the panel will show. |
447
+ | `logo` | `ReactNode` | - | The logo displayed in the header. Can be an image, icon, svg or any `ReactNode`. |
448
+ | `logoUrl` | `string` | - | URL for the logo link. If provided, clicking the logo navigates to this URL. |
449
+ | `logoLinkComponent` | `ElementType` | `"a"` | Specifies the component to use for the logo link. |
450
+ | `logoLinkProps` | [`LinkProps`](https://mui.com/material-ui/api/link/) | - | Props to pass to the logo link component. |
451
+ | `primaryNavItems` | `NavigationHeaderPrimaryNavItem<T>[]` | - | List of items for the primary navigation section. |
452
+ | `primaryNavPosition` | `"left" \|"right"` | `"left"` | Position of the `primaryNavItems` list. If set to `"left"`, the items appear to the left of the search bar. If set to `"right"`, they are positioned next to the `secondaryNavItems` on the right. |
453
+ | `showSearch` | `boolean` | `true` | Whether to display the search input in the header. |
454
+ | `searchProps` | `Partial<InputSearchProps>` | - | Props passed to the search input component. |
455
+ | `secondaryNavItems` | `NavigationHeaderSecondaryNavItem[]` | - | List of items for the secondary navigation section. |
456
+ | `scrollElevation` | `boolean` | `true` | Controls whether a shadow is shown under the Nav when scrolling. |
457
+ | `tag` | `string` | - | A small label displayed next to the title. |
458
+ | `tagColor` | `"accent"` \| `"beta"` \| `"info"` \| `"negative"` \| `"neutral"` \| `"notice"` \| `"positive"` \| `[string, string]` \| `[string, string, string]` | `"neutral"` | The intent of the small, solid Tag beside the title, or custom colors as `[label, background]` or `[label, background, icon]`. |
459
+ | `title` | `string` | - | The main title displayed in the header. |
460
460
 
461
461
  NavigationHeader also extends MUI's [AppBar](https://mui.com/material-ui/api/app-bar/) minus its `position` prop, so the remaining AppBar and DOM props reach the underlying element.
462
462
 
@@ -240,10 +240,8 @@ const COLUMNS: ColumnDef<Employee>[] = [
240
240
  <CellComponent as={as} style={style}>
241
241
  <Tag
242
242
  color={getValue() === "Active" ? "positive" : "negative"}
243
- hover={false}
244
243
  label={getValue() as string}
245
- sdsStyle="rounded"
246
- sdsType="secondary"
244
+ sdsStyle="outline"
247
245
  />
248
246
  </CellComponent>
249
247
  ),
@@ -569,10 +567,8 @@ const COLUMNS: ColumnDef<Employee>[] = [
569
567
  <CellComponent as={as} style={style}>
570
568
  <Tag
571
569
  color={getValue() === "Active" ? "positive" : "negative"}
572
- hover={false}
573
570
  label={getValue() as string}
574
- sdsStyle="rounded"
575
- sdsType="secondary"
571
+ sdsStyle="outline"
576
572
  />
577
573
  </CellComponent>
578
574
  ),
@@ -897,10 +893,8 @@ const COLUMNS: ColumnDef<Employee>[] = [
897
893
  <CellComponent as={as} style={style}>
898
894
  <Tag
899
895
  color={getValue() === "Active" ? "positive" : "negative"}
900
- hover={false}
901
896
  label={getValue() as string}
902
- sdsStyle="rounded"
903
- sdsType="secondary"
897
+ sdsStyle="outline"
904
898
  />
905
899
  </CellComponent>
906
900
  ),
@@ -1228,10 +1222,8 @@ const COLUMNS: ColumnDef<Employee>[] = [
1228
1222
  <CellComponent as={as} style={style}>
1229
1223
  <Tag
1230
1224
  color={getValue() === "Active" ? "positive" : "negative"}
1231
- hover={false}
1232
1225
  label={getValue() as string}
1233
- sdsStyle="rounded"
1234
- sdsType="secondary"
1226
+ sdsStyle="outline"
1235
1227
  />
1236
1228
  </CellComponent>
1237
1229
  ),
@@ -1567,10 +1559,8 @@ const COLUMNS: ColumnDef<Employee>[] = [
1567
1559
  <CellComponent as={as} style={style}>
1568
1560
  <Tag
1569
1561
  color={getValue() === "Active" ? "positive" : "negative"}
1570
- hover={false}
1571
1562
  label={getValue() as string}
1572
- sdsStyle="rounded"
1573
- sdsType="secondary"
1563
+ sdsStyle="outline"
1574
1564
  />
1575
1565
  </CellComponent>
1576
1566
  ),
@@ -1825,10 +1815,8 @@ const COLUMNS: ColumnDef<Employee>[] = [
1825
1815
  <CellComponent as={as} style={style}>
1826
1816
  <Tag
1827
1817
  color={getValue() === "Active" ? "positive" : "negative"}
1828
- hover={false}
1829
1818
  label={getValue() as string}
1830
- sdsStyle="rounded"
1831
- sdsType="secondary"
1819
+ sdsStyle="outline"
1832
1820
  />
1833
1821
  </CellComponent>
1834
1822
  ),
@@ -2096,10 +2084,8 @@ const COLUMNS: ColumnDef<Employee>[] = [
2096
2084
  <CellComponent as={as} style={style}>
2097
2085
  <Tag
2098
2086
  color={getValue() === "Active" ? "positive" : "negative"}
2099
- hover={false}
2100
2087
  label={getValue() as string}
2101
- sdsStyle="rounded"
2102
- sdsType="secondary"
2088
+ sdsStyle="outline"
2103
2089
  />
2104
2090
  </CellComponent>
2105
2091
  ),
@@ -2404,10 +2390,8 @@ const COLUMNS: ColumnDef<Employee>[] = [
2404
2390
  <CellComponent as={as} style={style}>
2405
2391
  <Tag
2406
2392
  color={getValue() === "Active" ? "positive" : "negative"}
2407
- hover={false}
2408
2393
  label={getValue() as string}
2409
- sdsStyle="rounded"
2410
- sdsType="secondary"
2394
+ sdsStyle="outline"
2411
2395
  />
2412
2396
  </CellComponent>
2413
2397
  ),
@@ -2796,10 +2780,8 @@ const COLUMNS: ColumnDef<Employee>[] = [
2796
2780
  <CellComponent as={as} style={style}>
2797
2781
  <Tag
2798
2782
  color={getValue() === "Active" ? "positive" : "negative"}
2799
- hover={false}
2800
2783
  label={getValue() as string}
2801
- sdsStyle="rounded"
2802
- sdsType="secondary"
2784
+ sdsStyle="outline"
2803
2785
  />
2804
2786
  </CellComponent>
2805
2787
  ),
@@ -20,6 +20,14 @@ import { ProteinStructureViewer } from "@czi-sds/data-viz";
20
20
 
21
21
  The viewer fills its parent. Mol\* sizes its canvas from the laid-out container, so give the parent a real height - a viewer inside a box with no height will wait for one rather than render.
22
22
 
23
+ The sequence panel along the bottom takes `max(104px, 30%)` of that height, growing to `max(134px, 32%)` once the viewer is 880px wide or more, and the 3D view fills the rest. `sequenceViewerHeight` sets the panel's height outright, as any CSS length or a number of pixels, and holds it at every width. The legend moves with the panel, so it stays sitting on top of it.
24
+
25
+ **React TypeScript**
26
+
27
+ ```tsx
28
+ <ProteinStructureViewer structure={PDB} sequenceViewerHeight={240} />
29
+ ```
30
+
23
31
  ## Code examples
24
32
 
25
33
  ### **Default ProteinStructureViewer**
@@ -2169,6 +2177,7 @@ The viewer spreads any remaining props onto its root div, so standard HTML attri
2169
2177
  | `sequenceViewerBackgroundColor` | `string` | - | Sequence panel background, as any CSS color. Defaults to the SDS theme's primary surface, so the panel follows the surrounding page in both modes. |
2170
2178
  | `showAxes` | `boolean` | `true` | Show the orientation axes widget and the reset-camera button. |
2171
2179
  | `showSequenceViewer` | `boolean` | `true` | Show the sequence panel pinned along the bottom of the viewer. |
2180
+ | `sequenceViewerHeight` | `number \| string` | - | Height of the sequence panel, as any CSS length; a number is read as pixels, and a percentage is of the viewer's own height. The 3D view and the legend move up to make room for it. Ignored while `showSequenceViewer` is off. Left undefined, the panel takes `max(104px, 30%)` of the viewer, growing to `max(134px, 32%)` once the viewer is 880px wide or more. A height set here holds at every width. |
2172
2181
  | `showLegend` | `boolean` | `true` | Show the stats and color scale legend overlaid on the viewer. |
2173
2182
  | `onResidueClick` | `function` | - | `(residue: ResidueRef) => void`. Called with the residue under the pointer: `index` (0-based, across the whole structure), `compId`, `chainId`, `seqId` and `insCode`. What the click _selected_ comes through `onSelectionChange`, which a drag makes a range. |
2174
2183
  | `onResidueHover` | `function` | - | `(residue: ResidueRef \| null) => void`. Called as the pointer moves over residues, and with `null` when it leaves the structure. |
@@ -68,12 +68,7 @@ function App() {
68
68
  <CellComponent verticalAlign="center" horizontalAlign="center">
69
69
  <StyledIconCell>
70
70
  <Icon sdsSize="xl" sdsIcon="Flask" />
71
- <Tag
72
- color="info"
73
- label="Chemistry"
74
- sdsStyle="rounded"
75
- sdsType="secondary"
76
- />
71
+ <Tag color="info" label="Chemistry" sdsStyle="outline" />
77
72
  </StyledIconCell>
78
73
  </CellComponent>
79
74
  <CellBasic
@@ -95,8 +90,7 @@ function App() {
95
90
  key={item}
96
91
  color={item as SdsTagColorType}
97
92
  label={item as string}
98
- sdsStyle="rounded"
99
- sdsType="secondary"
93
+ sdsStyle="outline"
100
94
  />
101
95
  )
102
96
  )}
@@ -114,8 +108,7 @@ function App() {
114
108
  <Tag
115
109
  color="info"
116
110
  label="Downloadable Content"
117
- sdsStyle="rounded"
118
- sdsType="secondary"
111
+ sdsStyle="outline"
119
112
  />
120
113
  </StyledIconCell>
121
114
  </CellComponent>
@@ -157,12 +150,7 @@ function App() {
157
150
  <CellComponent verticalAlign="center" horizontalAlign="center">
158
151
  <StyledIconCell>
159
152
  <Icon sdsSize="xl" sdsIcon="Bacteria" />
160
- <Tag
161
- color="negative"
162
- label="Disease"
163
- sdsStyle="rounded"
164
- sdsType="secondary"
165
- />
153
+ <Tag color="negative" label="Disease" sdsStyle="outline" />
166
154
  </StyledIconCell>
167
155
  </CellComponent>
168
156
  <CellBasic
@@ -561,10 +549,8 @@ const columns: ColumnDef<Person>[] = [
561
549
  <CellComponent verticalAlign="center">
562
550
  <Tag
563
551
  color={STATUS_COLORS[status]}
564
- hover={false}
565
552
  label={status}
566
- sdsStyle="rounded"
567
- sdsType="secondary"
553
+ sdsStyle="outline"
568
554
  />
569
555
  </CellComponent>
570
556
  );
@@ -793,9 +779,7 @@ const columns = [
793
779
  ? "positive"
794
780
  : "negative"
795
781
  }
796
- sdsStyle="rounded"
797
- sdsType="secondary"
798
- hover={false}
782
+ sdsStyle="outline"
799
783
  />
800
784
  </CellComponent>
801
785
  ),
@@ -1061,10 +1045,8 @@ const columns: ColumnDef<Person>[] = [
1061
1045
  <CellComponent verticalAlign="center">
1062
1046
  <Tag
1063
1047
  color={STATUS_COLORS[status]}
1064
- hover={false}
1065
1048
  label={status}
1066
- sdsStyle="rounded"
1067
- sdsType="secondary"
1049
+ sdsStyle="outline"
1068
1050
  />
1069
1051
  </CellComponent>
1070
1052
  );
@@ -1609,10 +1591,8 @@ const columns: ColumnDef<Person>[] = [
1609
1591
  <CellComponent verticalAlign="center">
1610
1592
  <Tag
1611
1593
  color={STATUS_COLORS[status]}
1612
- hover={false}
1613
1594
  label={status}
1614
- sdsStyle="rounded"
1615
- sdsType="secondary"
1595
+ sdsStyle="outline"
1616
1596
  />
1617
1597
  </CellComponent>
1618
1598
  );
@@ -1892,10 +1872,8 @@ const columns: ColumnDef<Person>[] = [
1892
1872
  <CellComponent verticalAlign="center">
1893
1873
  <Tag
1894
1874
  color={STATUS_COLORS[status]}
1895
- hover={false}
1896
1875
  label={status}
1897
- sdsStyle="rounded"
1898
- sdsType="secondary"
1876
+ sdsStyle="outline"
1899
1877
  />
1900
1878
  </CellComponent>
1901
1879
  );
@@ -157,12 +157,7 @@ function App() {
157
157
  count={
158
158
  <CountWithTag>
159
159
  14
160
- <Tag
161
- color="beta"
162
- label="BETA"
163
- sdsStyle="rounded"
164
- sdsType="secondary"
165
- />
160
+ <Tag color="beta" label="BETA" sdsStyle="outline" size="small" />
166
161
  </CountWithTag>
167
162
  }
168
163
  label="Analyses"