@czi-sds/mcp 0.16.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 +68 -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 +112 -208
  112. package/package.json +9 -5
  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,298 @@
1
+ # Menu
2
+
3
+ A surface of choices that opens from the element the user clicked, for actions and options that do not warrant a permanent place in the layout.
4
+
5
+ > **Menu is not DropdownMenu.** Menu is the simplest dropdown the system has, a restyling of Material UI's own: its rows are commands you write yourself, and picking one runs an action and leaves nothing behind. DropdownMenu is for choosing a value the app keeps, from options passed as data. If what the user picks has to be read back out afterwards, it is not a Menu; the Dropdowns overview sets the two side by side.
6
+
7
+ ## Source Code
8
+
9
+ 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/Menu/index.tsx).
10
+
11
+ ## Import
12
+
13
+ **React TypeScript**
14
+
15
+ ```tsx
16
+ import { Menu } from "@czi-sds/components";
17
+ ```
18
+
19
+ ## Code examples
20
+
21
+ ### **Default Menu**
22
+
23
+ The least a menu needs: an anchor kept in state, an `open` derived from it, and an `onClose` that clears it. The items are commands, so each one clears the anchor as well and the menu closes behind it.
24
+
25
+ **Example: DefaultMenu**
26
+
27
+ ```tsx
28
+ // A Menu anchored to the button that opens it: `anchorEl` places the surface,
29
+ // `open` drives its visibility, and `onClose` handles the backdrop click and
30
+ // the Esc key. Each item closes the Menu itself.
31
+
32
+ import { useState } from "react";
33
+ import { Button, Menu, MenuItem } from "@czi-sds/components";
34
+
35
+ function App() {
36
+ const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
37
+ const isOpen = Boolean(anchorEl);
38
+
39
+ const handleClose = () => setAnchorEl(null);
40
+
41
+ return (
42
+ <div className="app">
43
+ <Button
44
+ id="default-menu-button"
45
+ sdsStyle="minimal"
46
+ sdsType="primary"
47
+ aria-controls={isOpen ? "default-menu" : undefined}
48
+ aria-expanded={isOpen || undefined}
49
+ aria-haspopup="true"
50
+ onClick={(event) => setAnchorEl(event.currentTarget)}
51
+ >
52
+ Open Menu
53
+ </Button>
54
+
55
+ <Menu
56
+ id="default-menu"
57
+ anchorEl={anchorEl}
58
+ open={isOpen}
59
+ onClose={handleClose}
60
+ slotProps={{ list: { "aria-labelledby": "default-menu-button" } }}
61
+ >
62
+ <MenuItem sdsType="action" onClick={handleClose}>
63
+ Contact us
64
+ </MenuItem>
65
+ <MenuItem sdsType="action" onClick={handleClose}>
66
+ Terms of Use
67
+ </MenuItem>
68
+ <MenuItem sdsType="action" onClick={handleClose}>
69
+ Privacy Policy
70
+ </MenuItem>
71
+ <MenuItem sdsType="action" onClick={handleClose}>
72
+ Logout
73
+ </MenuItem>
74
+ </Menu>
75
+ </div>
76
+ );
77
+ }
78
+
79
+ export default App;
80
+ ```
81
+
82
+ ### **Menu placement**
83
+
84
+ A menu wider than its trigger, or one opened from something near the edge of the window, often reads better aligned to an edge than centered. Pairing the right edge of the anchor with the right edge of the menu moves it there without any positioning code of your own.
85
+
86
+ **Example: MenuPlacement**
87
+
88
+ ```tsx
89
+ // `anchorOrigin` picks the point on the trigger the Menu grows from, and
90
+ // `transformOrigin` the corner of the Menu that meets it. Pairing right edges
91
+ // keeps the surface aligned with the end of the button instead of centered
92
+ // under it.
93
+
94
+ import { useState } from "react";
95
+ import { Button, Menu, MenuItem } from "@czi-sds/components";
96
+
97
+ function App() {
98
+ const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
99
+ const isOpen = Boolean(anchorEl);
100
+
101
+ const handleClose = () => setAnchorEl(null);
102
+
103
+ return (
104
+ <div className="app">
105
+ <Button
106
+ id="placement-menu-button"
107
+ sdsStyle="outline"
108
+ sdsType="primary"
109
+ aria-controls={isOpen ? "placement-menu" : undefined}
110
+ aria-expanded={isOpen || undefined}
111
+ aria-haspopup="true"
112
+ onClick={(event) => setAnchorEl(event.currentTarget)}
113
+ >
114
+ Right aligned Menu
115
+ </Button>
116
+
117
+ <Menu
118
+ id="placement-menu"
119
+ anchorEl={anchorEl}
120
+ anchorOrigin={{ horizontal: "right", vertical: "bottom" }}
121
+ open={isOpen}
122
+ transformOrigin={{ horizontal: "right", vertical: "top" }}
123
+ onClose={handleClose}
124
+ slotProps={{ list: { "aria-labelledby": "placement-menu-button" } }}
125
+ >
126
+ <MenuItem sdsType="action" onClick={handleClose}>
127
+ Rename
128
+ </MenuItem>
129
+ <MenuItem sdsType="action" onClick={handleClose}>
130
+ Duplicate
131
+ </MenuItem>
132
+ <MenuItem disabled sdsType="action" onClick={handleClose}>
133
+ Archive
134
+ </MenuItem>
135
+ </Menu>
136
+ </div>
137
+ );
138
+ }
139
+
140
+ export default App;
141
+ ```
142
+
143
+ ### **Menu with selectable items**
144
+
145
+ Selection state lives outside the menu. Passing `isMultiSelect` and `selected` to each MenuItem draws the checkmarks, and leaving the close out of the item handlers keeps the menu open so several options can be set in one visit.
146
+
147
+ **Example: MenuWithSelectableItems**
148
+
149
+ ```tsx
150
+ // Menu itself has no notion of a selected value: MenuItem draws the state and
151
+ // the surrounding component owns it. Because closing only happens when
152
+ // something calls `onClose`, items that toggle a selection leave the Menu open
153
+ // for the next one.
154
+
155
+ import { useState } from "react";
156
+ import { Button, Menu, MenuItem } from "@czi-sds/components";
157
+
158
+ const ORGANISMS = [
159
+ { count: "12,480", name: "Homo sapiens" },
160
+ { count: "8,213", name: "Mus musculus" },
161
+ { count: "3,006", name: "Danio rerio" },
162
+ ];
163
+
164
+ function App() {
165
+ const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
166
+ const [selected, setSelected] = useState<string[]>(["Homo sapiens"]);
167
+ const isOpen = Boolean(anchorEl);
168
+
169
+ const toggle = (name: string) => {
170
+ setSelected((previous) =>
171
+ previous.includes(name)
172
+ ? previous.filter((item) => item !== name)
173
+ : [...previous, name]
174
+ );
175
+ };
176
+
177
+ return (
178
+ <div className="app">
179
+ <Button
180
+ id="selection-menu-button"
181
+ sdsStyle="minimal"
182
+ sdsType="primary"
183
+ aria-controls={isOpen ? "selection-menu" : undefined}
184
+ aria-expanded={isOpen || undefined}
185
+ aria-haspopup="true"
186
+ onClick={(event) => setAnchorEl(event.currentTarget)}
187
+ >
188
+ {`Organism (${selected.length})`}
189
+ </Button>
190
+
191
+ <Menu
192
+ id="selection-menu"
193
+ anchorEl={anchorEl}
194
+ open={isOpen}
195
+ onClose={() => setAnchorEl(null)}
196
+ slotProps={{ list: { "aria-labelledby": "selection-menu-button" } }}
197
+ >
198
+ {ORGANISMS.map((organism) => (
199
+ <MenuItem
200
+ key={organism.name}
201
+ isMultiSelect
202
+ column={organism.count}
203
+ selected={selected.includes(organism.name)}
204
+ onClick={() => toggle(organism.name)}
205
+ >
206
+ {organism.name}
207
+ </MenuItem>
208
+ ))}
209
+ </Menu>
210
+ </div>
211
+ );
212
+ }
213
+
214
+ export default App;
215
+ ```
216
+
217
+ ## SDS vs MUI
218
+
219
+ SDS Menu is a thin wrapper around MUI's Menu. `MenuProps` is MUI's own type re-exported unchanged, so there are no sds-prefixed props and everything in the MUI documentation applies. What SDS contributes is two positioning defaults and the styling of the paper the items sit on:
220
+
221
+ - `anchorOrigin`: set to `{ vertical: "bottom", horizontal: "center" }`, where MUI's default is `"top"` / `"left"`. An SDS menu therefore opens below its anchor rather than on top of it.
222
+
223
+ - `transformOrigin`: set to `{ vertical: "top", horizontal: "center" }`, so the two center points meet and the menu hangs centered under its trigger.
224
+
225
+ - **Both defaults are spread before your props,** which means each one is replaced whole rather than merged. The two are a pair, so repositioning a menu is a matter of passing both, as the placement example below does.
226
+
227
+ - **The paper is restyled:** the surface color comes from the theme's `surfacePrimary`, the corners are the `l` radius, and there is an `xs` inset around the items. SDS also sets `background-image: none`, which removes the tint MUI's Paper paints over surfaces in dark mode.
228
+
229
+ - **The list loses its own padding,** so the space around the items is the paper's inset alone and the first and last item sit as close to the edge as the ones on either side.
230
+
231
+ - **Its children are SDS MenuItems.** Menu draws the surface and nothing within it, so the appearance of a row (its icon, its right hand column, its selected state) belongs to MenuItem.
232
+
233
+ > **SDS Tip:** Reach for Menu when the choices are commands, or a short list of options anchored to a trigger. When the user is picking a value that the trigger should then display, and especially when the list needs search, sections, or Apply and Cancel buttons, use Dropdown instead.
234
+
235
+ ## MUI Documentation
236
+
237
+ Documentation for the underlying MUI component can be found [here](https://mui.com/material-ui/react-menu/), and its full API [here](https://mui.com/material-ui/api/menu/).
238
+
239
+ ## Anchoring and state
240
+
241
+ Menu is controlled: it renders when `open` is `true`, positions itself against the element passed as `anchorEl`, and asks to be dismissed through `onClose`. Holding the anchor element in state covers all three, since whether there is an anchor is also whether the menu is open.
242
+
243
+ **React TypeScript**
244
+
245
+ ```tsx
246
+ const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
247
+
248
+ <Button onClick={(event) => setAnchorEl(event.currentTarget)}>Open Menu</Button>
249
+
250
+ <Menu
251
+ anchorEl={anchorEl}
252
+ open={Boolean(anchorEl)}
253
+ onClose={() => setAnchorEl(null)}
254
+ >
255
+ <MenuItem sdsType="action" onClick={() => setAnchorEl(null)}>
256
+ Rename
257
+ </MenuItem>
258
+ </Menu>
259
+ ```
260
+
261
+ ## Behavior and accessibility
262
+
263
+ - A Menu is a Popover holding a list, and a Popover is built on MUI's Modal. It renders in a portal at the end of the document, traps focus while it is open, hides the rest of the page from assistive technology, and locks the page's scroll.
264
+
265
+ - `onClose` is called with the event and a reason: `"backdropClick"`, `"escapeKeyDown"`, or `"tabKeyDown"`. It is never called for a click on an item. Closing on selection is the item's own `onClick`, which is what lets a menu of toggles stay open while several are set.
266
+
267
+ - **anchorEl has to be state, not a ref.** The menu measures the anchor while rendering, so it needs a render to happen once the element is known. Storing the trigger in a ref leaves the menu with nothing to measure on the first open.
268
+
269
+ - Opening a menu moves focus into it. The arrow keys walk the items, Home and End jump to the ends, and typing a letter moves to the next item whose text starts with it. Disabled items are skipped.
270
+
271
+ - `variant` decides where that focus lands. The default, `"selectedMenu"`, starts on the selected item, which is right for a menu that reflects a current value; pass `"menu"` to always start at the top.
272
+
273
+ - Give the trigger `aria-haspopup`, `aria-controls` pointing at the menu's id, and `aria-expanded` while it is open, then name the list with `slotProps.list` and an `aria-labelledby` that points back at the trigger.
274
+
275
+ - The list is a `role="menu"` of `role="menuitem"` children, which describes a set of commands. A menu used to choose values instead is a listbox: pass `role="listbox"` through `slotProps.list` and give each MenuItem `role="option"` with an `aria-selected`.
276
+
277
+ - Nothing is rendered while `open` is `false`, so the items are mounted fresh on each open. Pass `keepMounted` to keep them in the document instead, which is worth it when the list is expensive to build or has to stay findable by an in-page search.
278
+
279
+ - A menu longer than the window scrolls within its own paper. Where the number of items is unbounded, cap the height through `slotProps.paper` so the surface is the same size whatever it holds.
280
+
281
+ ## Props
282
+
283
+ Menu takes MUI's props and adds none of its own. The ones needed to get a menu working, and those whose SDS defaults differ from MUI's, are listed below. See the MUI documentation for the rest.
284
+
285
+ | Name | Type | Default | Description |
286
+ | -------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
287
+ | `open` | `boolean` | - | Required. Whether the menu is shown. Usually derived from whether an anchor has been recorded. |
288
+ | `anchorEl` | `HTMLElement \| (() => HTMLElement) \| null` | - | The element the menu is positioned against. Keep it in state so that setting it causes the render the menu needs in order to measure it. |
289
+ | `children` | `ReactNode` | - | The contents of the menu, normally SDS MenuItems, placed into the list the menu renders. |
290
+ | `onClose` | `(event, reason) => void` | - | Called on a backdrop click, on Escape, and on Tab, with the reason as its second argument. Closing the menu is up to you. |
291
+ | `anchorOrigin` | `{ vertical: "top" \| "center" \| "bottom" \| number,` `horizontal: "left" \| "center" \| "right" \| number }` | `{ vertical: "bottom", horizontal: "center" }` | The point on the anchor the menu attaches to. SDS changes MUI's default from the anchor's top left corner. |
292
+ | `transformOrigin` | `{ vertical: "top" \| "center" \| "bottom" \| number,` `horizontal: "left" \| "center" \| "right" \| number }` | `{ vertical: "top", horizontal: "center" }` | The point on the menu that meets the anchor's. Passing your own replaces the SDS default rather than merging with it. |
293
+ | `variant` | `"menu" \| "selectedMenu"` | `"selectedMenu"` | Where focus lands when the menu opens: on the selected item, or on the first one. |
294
+ | `autoFocus` | `boolean` | `true` | Whether focus moves into the menu when it opens. Turning it off has severe accessibility implications unless focus is managed some other way. |
295
+ | `slotProps` | `{ root, paper, list, transition, backdrop }` | - | Props for the parts the menu is made of. `slotProps.list` is where the list's label and role belong, and `slotProps.paper` is where a width or a max height belongs. |
296
+ | `keepMounted` | `boolean` | `false` | Keeps the items in the document while the menu is closed, preserving their state at the cost of rendering them up front. |
297
+ | `disablePortal` | `boolean` | `false` | Renders the menu where it is written rather than at the end of the document, which puts it back within reach of an ancestor's overflow. |
298
+ | `transitionDuration` | `number \| { appear, enter, exit } \| "auto"` | `"auto"` | How long the grow transition runs. `"auto"` scales it to the size of the menu. |
@@ -0,0 +1,100 @@
1
+ # MenuItem
2
+
3
+ > **MenuItem is one row of a dropdown.** You write these yourself to fill a Menu; everywhere else in the family the row is drawn for you, from the options you pass, and you only reach for this component to replace it. The Dropdowns overview covers which component draws which part.
4
+
5
+ ## Source Code
6
+
7
+ 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/MenuItem/index.tsx).
8
+
9
+ ## Import
10
+
11
+ **React TypeScript**
12
+
13
+ ```tsx
14
+ import { MenuItem } from "@czi-sds/components";
15
+ ```
16
+
17
+ ## Code Examples
18
+
19
+ ### **Default MenuItem**
20
+
21
+ This example shows the minimum props needed for rendering a MenuItem.
22
+
23
+ **Example: DefaultMenuItem**
24
+
25
+ ```tsx
26
+ import { MenuItem } from "@czi-sds/components";
27
+ import { MenuList } from "@mui/material";
28
+
29
+ function App() {
30
+ return (
31
+ <div className="app">
32
+ <MenuList>
33
+ <MenuItem>MenuItem 1</MenuItem>
34
+ </MenuList>
35
+ </div>
36
+ );
37
+ }
38
+
39
+ export default App;
40
+ ```
41
+
42
+ ### **Multi-Select MenuItem with Icon**
43
+
44
+ This example showcases a multi-select MenuItem component featuring an SDS Icon and a distinct column value.
45
+
46
+ > **SDS Tip:** MenuItem exclusively accepts SDS Icons in xs and s sizes. To explore a comprehensive list of SDS icons and their available sizes, refer to the [IconBank page](https://chanzuckerberg.github.io/sci-components/?path=/story/components-icon--icon-bank) within Storybook.
47
+
48
+ **Example: MultiSelectMenuItemWithIcon**
49
+
50
+ ```tsx
51
+ import { useState } from "react";
52
+ import { MenuItem } from "@czi-sds/components";
53
+ import { MenuList } from "@mui/material";
54
+
55
+ function App() {
56
+ const [selected, setSelected] = useState(false);
57
+
58
+ const handleClick = () => {
59
+ setSelected((prev) => !prev);
60
+ };
61
+
62
+ return (
63
+ <div className="app">
64
+ <MenuList>
65
+ <MenuItem
66
+ isMultiSelect
67
+ column="Column Value"
68
+ sdsIcon="Gear"
69
+ sdsIconProps={{
70
+ color: "purple",
71
+ }}
72
+ selected={selected}
73
+ onClick={handleClick}
74
+ >
75
+ MenuItem 1
76
+ </MenuItem>
77
+ </MenuList>
78
+ </div>
79
+ );
80
+ }
81
+
82
+ export default App;
83
+ ```
84
+
85
+ ## Props
86
+
87
+ Any custom SDS props and MUI props required for implementation are found on the table below. See the MUI documentation for additional optional props.
88
+
89
+ | Name | Type | Default | Description |
90
+ | --------------- | ------------------------------------ | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
91
+ | `column` | `ReactNode` | - | The `column` prop determines the content displayed in the right column of the menu item. This content can be customized to provide additional information or context for the menu item. |
92
+ | `children` | `ReactNode` | - | Main content of the MenuItem. |
93
+ | `disabled` | `boolean` | `false` | When set to `true`, the `disabled` prop indicates that the menu item is disabled and not interactable. |
94
+ | `isMultiSelect` | `boolean` | `false` | When `true`, designates that the menu item supports multi-select functionality. |
95
+ | `icon` | `IconName` \| `ReactElement` | - | The icon shown at the start of the item, either the name of an SDS icon or an element of your own. Only icons that come in a small size can be named here. |
96
+ | `sdsIcon` | `IconName` \| `ReactElement` | - | **Deprecated.** Use `icon` instead. It is the former name of that prop, kept until the next major version, and `icon` wins where both are given. |
97
+ | `sdsIconProps` | `function` | - | Enables you to pass additional props to customize the SDS icon within the menu item. |
98
+ | `sdsStyle` | `"determinate"` \| `"indeterminate"` | `"determinate"` | Determines the style of the menu item, whether it is determinate or indeterminate. |
99
+ | `sdsType` | `"default"` \| `"action"` | `"default"` | An `"action"` item leaves out the selection mark at its start, for a menu whose items run a command rather than choose a value. |
100
+ | `selected` | `boolean` | `false` | When set to `true`, the `selected` prop signifies that the menu item is currently selected. |
@@ -0,0 +1,165 @@
1
+ # NavigationFooter
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/tree/main/packages/components/src/core/NavigationFooter).
6
+
7
+ ## Import
8
+
9
+ **React TypeScript**
10
+
11
+ ```tsx
12
+ import { NavigationFooter } from "@czi-sds/components";
13
+ ```
14
+
15
+ ## Code examples
16
+
17
+ ### Default footer
18
+
19
+ A footer with all four content areas filled: logo with title and tag, the prominent nav items, the bottom row of links, and an image beside them.
20
+
21
+ **Example: NavigationFooterDefault**
22
+
23
+ ```tsx
24
+ // The footer takes three separate lists: navItems sit beside the logo on the
25
+ // top row, navLinks run along the bottom row separated by dividers, and images
26
+ // sit opposite them.
27
+
28
+ import {
29
+ NavigationFooter,
30
+ getSemanticColors,
31
+ type CommonThemeProps,
32
+ } from "@czi-sds/components";
33
+ import styled from "@emotion/styled";
34
+
35
+ const Placeholder = styled.div<CommonThemeProps & { boxWidth: number }>`
36
+ ${(props) => {
37
+ const semanticColors = getSemanticColors(props);
38
+
39
+ return `
40
+ align-items: center;
41
+ border: 1px dashed ${semanticColors?.base?.borderPrimary};
42
+ color: ${semanticColors?.base?.textSecondary};
43
+ display: flex;
44
+ font-size: 10px;
45
+ height: 24px;
46
+ justify-content: center;
47
+ white-space: nowrap;
48
+ width: ${props.boxWidth}px;
49
+ `;
50
+ }}
51
+ `;
52
+
53
+ function App() {
54
+ return (
55
+ <div className="app">
56
+ <NavigationFooter
57
+ images={[
58
+ {
59
+ image: <Placeholder boxWidth={80}>Partner logo</Placeholder>,
60
+ url: "https://chanzuckerberg.com",
61
+ },
62
+ ]}
63
+ logo={<Placeholder boxWidth={64}>Logo slot</Placeholder>}
64
+ logoUrl="https://chanzuckerberg.com"
65
+ navItems={[
66
+ { label: "Datasets", url: "/datasets" },
67
+ { label: "Documentation", url: "/docs" },
68
+ { label: "Support", url: "/support" },
69
+ ]}
70
+ navLinks={[
71
+ { label: "Privacy", url: "/privacy" },
72
+ { label: "Terms", url: "/terms" },
73
+ { label: "Contact us", url: "/contact" },
74
+ ]}
75
+ tag="Beta"
76
+ tagColor="beta"
77
+ title="Cell Atlas"
78
+ />
79
+ </div>
80
+ );
81
+ }
82
+
83
+ export default App;
84
+ ```
85
+
86
+ ### Dark footer
87
+
88
+ The same structure on a dark surface, with the text and dividers inverted.
89
+
90
+ **Example: NavigationFooterDark**
91
+
92
+ ```tsx
93
+ // backgroundAppearance="dark" puts the footer on a dark surface and inverts its
94
+ // text and dividers. In dark mode it makes no difference: the footer is already
95
+ // dark, so the prop only ever adds darkness, never removes it.
96
+
97
+ import { NavigationFooter } from "@czi-sds/components";
98
+
99
+ function App() {
100
+ return (
101
+ <div className="app">
102
+ <NavigationFooter
103
+ backgroundAppearance="dark"
104
+ navItems={[
105
+ { label: "Datasets", url: "/datasets" },
106
+ { label: "Documentation", url: "/docs" },
107
+ ]}
108
+ navLinks={[
109
+ { label: "Privacy", url: "/privacy" },
110
+ { label: "Terms", url: "/terms" },
111
+ ]}
112
+ title="Cell Atlas"
113
+ />
114
+ </div>
115
+ );
116
+ }
117
+
118
+ export default App;
119
+ ```
120
+
121
+ ## Behavior notes
122
+
123
+ - The footer is two rows. The top row is the logo, title, and tag on one side with `navItems` beside them; below a divider, the bottom row is `navLinks` on one side and `images` on the other.
124
+
125
+ - The two link lists are styled differently on purpose. `navItems` are the prominent destinations; the `navLinks` run in a single line with dividers drawn between them, which is where policy and contact links belong.
126
+
127
+ - Like the header, the footer decides on its own when to go narrow, below 512px or whenever its content no longer fits. In the narrow layout the links wrap into rows and the component drops the divider at the end of each row.
128
+
129
+ - There is no `hasInvertedStyle` prop here either; `backgroundAppearance` is the one to reach for, and it only changes anything in light mode.
130
+
131
+ - The props are the whole surface: `NavigationFooterProps` does not extend the DOM attributes, so there is no `className`, `style`, or `ref` to pass.
132
+
133
+ ## Props
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. |
148
+
149
+ ## FooterImage
150
+
151
+ | Name | Type | Default | Description |
152
+ | ----------- | ------------------------- | ------- | ---------------------------------------------------------------------------------- |
153
+ | `image` | `ReactNode` | - | The image element to be displayed. Can be an icon, image, SVG, or any `ReactNode`. |
154
+ | `url` | `string` | - | Optional URL to navigate to when the image is clicked. |
155
+ | `component` | `ElementType` | `"a"` | Custom link component to use for navigation (e.g., a router link). |
156
+ | `linkProps` | `Record<string, unknown>` | - | Additional props passed to the link component. |
157
+
158
+ ## NavigationFooterNavItem
159
+
160
+ | Name | Type | Default | Description |
161
+ | ----------- | ------------------------- | ------- | --------------------------------------------------------- |
162
+ | `label` | `string` | - | The text label displayed for the navigation item. |
163
+ | `url` | `string` | - | Optional URL the item links to. |
164
+ | `component` | `ElementType` | `"a"` | Custom component to render the link (e.g., Next.js Link). |
165
+ | `linkProps` | `Record<string, unknown>` | - | Props forwarded to the link component. |