@databricks/design-system 2.0.5 → 2.0.7

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 (52) hide show
  1. package/AGENTS.md +239 -166
  2. package/CHANGELOG.md +47 -0
  3. package/design-guidance/docs/README.md +40 -0
  4. package/design-guidance/docs/review-contract.md +22 -0
  5. package/design-guidance/docs/tokens.md +35 -0
  6. package/design-guidance/docs/voice.md +40 -0
  7. package/design-guidance/skills/dbui-build-screen.md +24 -0
  8. package/design-guidance/skills/dbui-check-ecosystem.md +21 -0
  9. package/design-guidance/skills/dbui-check-guidelines.md +29 -0
  10. package/design-guidance/skills/dbui-check-principles.md +26 -0
  11. package/design-guidance/skills/dbui-check-voice.md +17 -0
  12. package/design-guidance/skills/dbui-pick-component.md +23 -0
  13. package/design-guidance/skills/dbui-pick-icon.md +23 -0
  14. package/design-guidance/skills/dbui-review.md +30 -0
  15. package/design-guidance/skills/dbui-validate.md +23 -0
  16. package/dist/{RHFControlledTypeaheadComboboxV2-DsH-nIEk.js → RHFControlledTypeaheadComboboxV2-nSSYj16I.js} +5 -5
  17. package/dist/{RHFControlledTypeaheadComboboxV2-DsH-nIEk.js.map → RHFControlledTypeaheadComboboxV2-nSSYj16I.js.map} +1 -1
  18. package/dist/{WizardStepContentWrapper-Bq1wm0V7.js → WizardStepContentWrapper-bbh_CoIf.js} +644 -679
  19. package/dist/WizardStepContentWrapper-bbh_CoIf.js.map +1 -0
  20. package/dist/dubois-colors.less +1 -1
  21. package/dist/icon-metadata.json +2069 -0
  22. package/dist/{index-BRAVZg-S.js → index-CUCuUviS.js} +350 -139
  23. package/dist/index-CUCuUviS.js.map +1 -0
  24. package/dist/index-dark.css +593 -191
  25. package/dist/index-dark.mitigated.css +623 -208
  26. package/dist/index.css +1536 -1049
  27. package/dist/index.js +4 -4
  28. package/dist/index.mitigated.css +1566 -1066
  29. package/dist/patterns.js +3 -3
  30. package/dist-types/design-system/Alert/Alert.d.ts +21 -4
  31. package/dist-types/design-system/Button/Button.d.ts +2 -1
  32. package/dist-types/design-system/Drawer/Drawer.d.ts +3 -1
  33. package/dist-types/design-system/Icon/AntdIcon.d.ts +3 -0
  34. package/dist-types/design-system/Icon/Icon.d.ts +20 -6
  35. package/dist-types/design-system/Icon/NativeIcon.d.ts +3 -0
  36. package/dist-types/design-system/Icon/__generated/icons/LakewatchIcon.d.ts +4 -0
  37. package/dist-types/design-system/Icon/__generated/icons/SlidesIcon.d.ts +4 -0
  38. package/dist-types/design-system/Icon/__generated/icons/index.d.ts +2 -0
  39. package/dist-types/design-system/Icon/index.d.ts +1 -0
  40. package/dist-types/design-system/Icon/utils.d.ts +1 -0
  41. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxControls.d.ts +0 -2
  42. package/dist-types/design-system/_shared_/Tabs/styles.d.ts +2 -3
  43. package/dist-types/design-system/index.d.ts +0 -1
  44. package/dist-types/design-system/utils/safex.d.ts +4 -2
  45. package/dist-types/theme/generalVariables.d.ts +0 -1
  46. package/dist-types/~patterns/Wizard/WizardModal.d.ts +1 -1
  47. package/package.json +8 -5
  48. package/setup.mjs +586 -0
  49. package/dist/WizardStepContentWrapper-Bq1wm0V7.js.map +0 -1
  50. package/dist/index-BRAVZg-S.js.map +0 -1
  51. package/dist-types/design-system/LegacyTooltip/LegacyTooltip.d.ts +0 -47
  52. package/dist-types/design-system/LegacyTooltip/index.d.ts +0 -1
package/AGENTS.md CHANGED
@@ -1,16 +1,39 @@
1
1
  # Using Du Bois (`@databricks/design-system`)
2
2
 
3
- Du Bois is Databricks' React component library. This file is guidance for coding agents
4
- building UI with it. Everything it describes is available from the published package; all
5
- components are named exports from `@databricks/design-system`.
3
+ Du Bois is Databricks' React component library. This file is guidance for coding agents building UI
4
+ with it. Everything it describes is available from the published package; all components are named
5
+ exports from `@databricks/design-system`.
6
6
 
7
7
  ## If you remember only four things
8
8
 
9
9
  1. **Use an existing component** — don't hand-build a widget the library already has.
10
- 2. **Prefer the composite** — `InfoTooltip`, `DangerModal`, `DropdownMenu`, not primitives glued together.
10
+ 2. **Prefer the composite** — `InfoTooltip`, `DangerModal`, `DropdownMenu`, not primitives glued
11
+ together.
11
12
  3. **Always pass `componentId`** — stable, dotted, no PII.
12
13
  4. **Never hardcode colors or spacing** — read `theme.*` tokens.
13
14
 
15
+ ## Step-by-step workflows
16
+
17
+ This package ships task-oriented workflows under
18
+ `node_modules/@databricks/design-system/design-guidance/`. Point your coding agent at the relevant
19
+ file when you want a repeatable procedure rather than the quick reference below. Start from
20
+ `design-guidance/docs/README.md`, then open the workflow for your task:
21
+
22
+ | Task | Workflow |
23
+ |------------------------------|-----------------------------------|
24
+ | Select a component | `skills/dbui-pick-component.md` |
25
+ | Select an icon | `skills/dbui-pick-icon.md` |
26
+ | Implement a screen | `skills/dbui-build-screen.md` |
27
+ | Check an implementation | `skills/dbui-validate.md` |
28
+ | Review a design (all checks) | `skills/dbui-review.md` |
29
+ | Review copy / voice | `skills/dbui-check-voice.md` |
30
+ | Review UX behavior | `skills/dbui-check-guidelines.md` |
31
+ | Review design intent | `skills/dbui-check-principles.md` |
32
+ | Review platform fit | `skills/dbui-check-ecosystem.md` |
33
+
34
+ Reference docs sit alongside them: `docs/tokens.md` (finding theme tokens as a consumer),
35
+ `docs/voice.md` (product copy), and `docs/review-contract.md`.
36
+
14
37
  ## Setup
15
38
 
16
39
  Install the package and its peer dependencies:
@@ -19,8 +42,8 @@ Install the package and its peer dependencies:
19
42
  npm install @databricks/design-system @emotion/react react react-dom moment
20
43
  ```
21
44
 
22
- `moment` is required by the date components. `@jest/globals` is an additional peer dependency
23
- if you use the `test-utils` entry point.
45
+ `moment` is required by the date components. `@jest/globals` is an additional peer dependency if you
46
+ use the `test-utils` entry point.
24
47
 
25
48
  Import the stylesheet once at your app's entry point, wrap the tree in
26
49
  `DesignSystemProvider`, and render `ApplyGlobalStyles` inside it:
@@ -29,27 +52,55 @@ Import the stylesheet once at your app's entry point, wrap the tree in
29
52
  import '@databricks/design-system/index.css';
30
53
  import '@databricks/design-system/fonts/dm-sans.css';
31
54
 
32
- import { ApplyGlobalStyles, DesignSystemProvider } from '@databricks/design-system';
55
+ import {ApplyGlobalStyles, DesignSystemProvider} from '@databricks/design-system';
33
56
 
34
57
  export const App = () => (
35
- <DesignSystemProvider>
36
- <ApplyGlobalStyles />
37
- <YourApp />
38
- </DesignSystemProvider>
58
+ <DesignSystemProvider>
59
+ <ApplyGlobalStyles/>
60
+ <YourApp/>
61
+ </DesignSystemProvider>
39
62
  );
40
63
  ```
41
64
 
42
- Without `DesignSystemProvider` the theme context is missing and `useDesignSystemTheme()`
43
- throws. For dark mode, also import `@databricks/design-system/index-dark.css` and pass
44
- `isDarkMode` to the provider.
65
+ Without `DesignSystemProvider` the theme context is missing and `useDesignSystemTheme()` throws.
66
+
67
+ `ApplyGlobalStyles` sets the body background and text color but **not** `font-family` (`Typography`
68
+ sets only color and size), so text falls back to the browser serif until you point `body` at the
69
+ `--db-font-family` token `index.css` defines (DM Sans; correct in both themes):
70
+
71
+ ```css
72
+ body {
73
+ font-family: var(--db-font-family);
74
+ }
75
+ ```
76
+
77
+ For dark mode, also import `@databricks/design-system/index-dark.css` and set `isDarkMode` on a
78
+ `DesignSystemThemeProvider` wrapping `DesignSystemProvider` — the provider has no `isDarkMode` prop
79
+ of its own (it reads theme context), so setting it there is a type error that stays light:
80
+
81
+ ```tsx
82
+ import {
83
+ ApplyGlobalStyles,
84
+ DesignSystemProvider,
85
+ DesignSystemThemeProvider
86
+ } from '@databricks/design-system';
87
+
88
+ export const App = () => (
89
+ <DesignSystemThemeProvider isDarkMode>
90
+ <DesignSystemProvider>
91
+ <ApplyGlobalStyles/>
92
+ <YourApp/>
93
+ </DesignSystemProvider>
94
+ </DesignSystemThemeProvider>
95
+ );
96
+ ```
45
97
 
46
98
  Styling uses the Emotion `css` prop, so configure Emotion's JSX runtime — set
47
99
  `jsxImportSource: '@emotion/react'` in your TypeScript or Babel config, or add
48
100
  `/** @jsxImportSource @emotion/react */` per file.
49
101
 
50
102
  The CSS entry points have no type declarations, so TypeScript rejects those side-effect imports
51
- unless your project declares them. Add this once rather than suppressing the error at each
52
- import:
103
+ unless your project declares them. Add this once rather than suppressing the error at each import:
53
104
 
54
105
  ```ts
55
106
  // css.d.ts
@@ -61,19 +112,19 @@ declare module '*.css';
61
112
  Read every design value off the theme.
62
113
 
63
114
  ```tsx
64
- import { useDesignSystemTheme } from '@databricks/design-system';
115
+ import {useDesignSystemTheme} from '@databricks/design-system';
65
116
 
66
117
  const MyPanel = () => {
67
- const { theme } = useDesignSystemTheme();
118
+ const {theme} = useDesignSystemTheme();
68
119
  return (
69
- <div
70
- css={{
71
- padding: theme.spacing.md, // 16 — never write 16
72
- color: theme.colors.textPrimary,
73
- backgroundColor: theme.colors.backgroundPrimary,
74
- borderRadius: theme.borders.borderRadiusSm,
75
- }}
76
- />
120
+ <div
121
+ css={{
122
+ padding: theme.spacing.md, // 16 — never write 16
123
+ color: theme.colors.textPrimary,
124
+ backgroundColor: theme.colors.backgroundPrimary,
125
+ borderRadius: theme.borders.borderRadiusSm,
126
+ }}
127
+ />
77
128
  );
78
129
  };
79
130
  ```
@@ -85,73 +136,93 @@ const MyPanel = () => {
85
136
  - **Radius** — `theme.borders.borderRadius*`. **Shadows** — `theme.shadows.{xs,sm,md,lg,xl}`.
86
137
  - **Motion** — `theme.animation.transitionDuration` (170ms).
87
138
 
88
- Every semantic token has a correct dark-mode value, so using tokens is what makes dark mode
89
- work for free.
90
-
91
- ## Picking a component
92
-
93
- | Need | Use |
94
- | --- | --- |
95
- | Action / navigation | `Button` (with `type`, `danger`), `Typography.Link` for navigation |
96
- | Button + menu | `SplitButton` (primary action + menu) or `DropdownMenu` |
97
- | Text & headings | `Typography.Title` / `.Text` / `.Paragraph` / `.Link` / `.Hint` |
98
- | Text input | `Input`, `Input.TextArea`, `Input.Password` |
99
- | Boolean | `Checkbox` (multi-select / terms), `Switch` (instant setting toggle) |
100
- | One of a small set | `Radio.Group`, or `SimpleSelect` for a dropdown |
101
- | One of many / searchable | `DialogCombobox` (searchable list), `TypeaheadCombobox` (autocomplete) |
102
- | Container / summary | `Card` |
103
- | Sectioned content | `Tabs` |
104
- | Dialog | `Modal`; `DangerModal` for destructive confirmation |
105
- | Contextual help | `Tooltip` (wraps any control), `InfoTooltip` (info icon + tooltip) |
106
- | Menu of actions | `DropdownMenu` |
107
- | Inline message / callout | `Alert` (field/section); `Banner` for page-level with a CTA |
108
- | Toast | `SnackBar` + `useSnackBar` |
109
- | Loading / empty | `Spinner`, `Skeleton` variants, `LoadingState`; `Empty` for no-data |
110
- | Page layout | `PageWrapper`, `Header`, `Sidebar`, `Grid.Row` / `Grid.Col` |
111
- | Tabular data | `Table` + `TableRow` / `TableHeader` / `TableCell` |
112
- | Form | `Form` + `FormUI.*`; `RHFControlledComponents.*` with React Hook Form |
113
- | Icon | Any `<XxxIcon />` (standalone component) |
114
- | Spacing between elements | `<Spacer size="…" />`, or `theme.spacing.*` in `css` |
115
-
116
- The library has roughly 90 components. For anything not listed, check the bundled type
117
- declarations (`dist-types/index.d.ts`) before building something custom — the export list is
118
- the authoritative catalog, and prop types are the authoritative API.
139
+ Every semantic token has a correct dark-mode value, so using tokens is what makes dark mode work for
140
+ free.
141
+
142
+ ## Available components
143
+
144
+ | Need | Use |
145
+ |-----------------------------------------|-----------------------------------------------------------------------------|
146
+ | Action / navigation | `Button` (with `type`, `danger`), `Typography.Link` for navigation |
147
+ | Button + menu | `SplitButton` (primary action + menu) or `DropdownMenu` |
148
+ | Grouped controls bar | `Toolbar` (buttons, toggles, and menus as one bar) |
149
+ | Text & headings | `Typography.Title` / `.Text` / `.Paragraph` / `.Link` / `.Hint` |
150
+ | Text input | `Input`, `Input.TextArea`, `Input.Password` |
151
+ | Boolean | `Checkbox` (multi-select / terms), `Switch` (instant setting toggle) |
152
+ | Toggle a view on/off | `ToggleButton` (binary filter with an immediately visible result) |
153
+ | One of a small set | `Radio.Group`, or `SimpleSelect` for a dropdown |
154
+ | One of a small set (rich cards) | `RadioTile` (option cards, inside a `Radio.Group`) |
155
+ | One of 4+ options | `Select` (dropdown built on `DialogCombobox`) |
156
+ | One of many / searchable | `DialogCombobox` (searchable list), `TypeaheadComboboxV2` (autocomplete) |
157
+ | Selectable option list (building block) | `Listbox` (optionally filterable) |
158
+ | Filter a list / switch related views | `SegmentedControl` (filter), `PillControl` (related page areas) |
159
+ | Value from a range | `Slider` (single, range, or stepped) |
160
+ | Date / time | `DatePicker` (single, range, optional time) |
161
+ | Container / summary | `Card` |
162
+ | Asset preview + actions | `PreviewCard` (image plus related actions) |
163
+ | User or entity avatar | `Avatar` |
164
+ | Label / category / status chip | `Tag` (colored, optionally closable) |
165
+ | Compute resource status | `ResourceStatusIndicator` |
166
+ | Progress of a task | `Progress` (determinate bar) |
167
+ | Multi-step task / wizard | `Stepper` |
168
+ | Sectioned content | `Tabs` |
169
+ | Dialog | `Modal`; `DangerModal` for destructive confirmation |
170
+ | Contextual help | `Tooltip` (wraps any control), `InfoTooltip` (info icon + tooltip) |
171
+ | Menu of actions | `DropdownMenu` |
172
+ | Inline message / callout | `Alert` (field/section); `Banner` for page-level with a CTA |
173
+ | Toast | `SnackBar` + `useSnackBar` |
174
+ | Passive in-app notification | `Notification` (upper-right, auto-dismiss; use `Alert` if action is needed) |
175
+ | Loading / empty | `Spinner`, `Skeleton` variants, `LoadingState`; `Empty` for no-data |
176
+ | Page layout | `PageWrapper`, `Header`, `Sidebar`, `Grid.Row` / `Grid.Col` |
177
+ | Breadcrumb trail | `Breadcrumb` |
178
+ | Routed nav tabs | `NavigationMenu` (wrap your router's `Link` in `NavigationMenu.Item`) |
179
+ | Pagination | `Pagination` (page-based or cursor-based) |
180
+ | Tabular data | `Table` + `TableRow` / `TableHeader` / `TableCell` |
181
+ | Nested hierarchy | `Tree` (navigable), `TreeGrid` (hierarchical rows with columns) |
182
+ | Collapse a long list of items | `Overflow` (shows a few, folds the rest into `+N`) |
183
+ | Form | `Form` + `FormUI.*`; `RHFControlledComponents.*` with React Hook Form |
184
+ | Icon | Any `<XxxIcon />` (standalone component) |
185
+ | Spacing between elements | `<Spacer size="…" />`, or `theme.spacing.*` in `css` |
186
+
187
+ The library has roughly 90 components. For anything not listed, check the bundled type declarations
188
+ (`dist-types/index.d.ts`) before building something custom — the export list is the authoritative
189
+ catalog, and prop types are the authoritative API.
119
190
 
120
191
  ## Use the composite
121
192
 
122
- When you are about to combine primitives, stop. A purpose-built composite usually exists and
123
- handles state, accessibility, and theming for you.
193
+ When you are about to combine primitives, stop. A purpose-built composite usually exists and handles
194
+ state, accessibility, and theming for you.
124
195
 
125
- | About to build… | Use instead |
126
- | --- | --- |
127
- | `Tooltip` wrapping an info icon | `InfoTooltip` |
128
- | `Modal` with a destructive confirm button | `DangerModal` |
129
- | `Button` + chevron + dropdown | `SplitButton` or `DropdownMenu` |
130
- | `Popover` + `<ul>`/`<li>` action list | `DropdownMenu` |
131
- | `Input` + autocomplete list | `TypeaheadCombobox` |
132
- | `Input` + selectable dropdown | `DialogCombobox` or `SimpleSelect` |
133
- | Manually managed open/close for a section | `Accordion` |
134
- | A row of buttons acting as a single choice | `SegmentedControlGroup` |
196
+ | About to build… | Use instead |
197
+ |--------------------------------------------|------------------------------------|
198
+ | `Tooltip` wrapping an info icon | `InfoTooltip` |
199
+ | `Modal` with a destructive confirm button | `DangerModal` |
200
+ | `Button` + chevron + dropdown | `SplitButton` or `DropdownMenu` |
201
+ | `Popover` + `<ul>`/`<li>` action list | `DropdownMenu` |
202
+ | `Input` + autocomplete list | `TypeaheadComboboxV2` |
203
+ | `Input` + selectable dropdown | `DialogCombobox` or `SimpleSelect` |
204
+ | Manually managed open/close for a section | `Accordion` |
205
+ | A row of buttons acting as a single choice | `SegmentedControlGroup` |
135
206
 
136
207
  ### Picking an overlay
137
208
 
138
- | Trigger / intent | Use |
139
- | --- | --- |
140
- | Short label on hover/focus | `Tooltip` |
141
- | Info icon + its tooltip | `InfoTooltip` |
142
- | Info icon + rich clickable content | `InfoPopover` |
143
- | Click for custom transient content | `Popover` |
144
- | Hover for a rich preview card | `HoverCard` |
145
- | A list of actions | `DropdownMenu` (or `ContextMenu` on right-click) |
146
- | Blocking dialog | `Modal` / `DangerModal` |
147
- | Side panel | `Drawer` (`Drawer.Root` / `.Trigger` / `.Content`) |
209
+ | Trigger / intent | Use |
210
+ |------------------------------------|----------------------------------------------------|
211
+ | Short label on hover/focus | `Tooltip` |
212
+ | Info icon + its tooltip | `InfoTooltip` |
213
+ | Info icon + rich clickable content | `InfoPopover` |
214
+ | Click for custom transient content | `Popover` |
215
+ | Hover for a rich preview card | `HoverCard` |
216
+ | A list of actions | `DropdownMenu` (or `ContextMenu` on right-click) |
217
+ | Blocking dialog | `Modal` / `DangerModal` |
218
+ | Side panel | `Drawer` (`Drawer.Root` / `.Trigger` / `.Content`) |
148
219
 
149
220
  ## Common components
150
221
 
151
222
  ### Button
152
223
 
153
- `componentId` is required. `type` is `primary | tertiary | link` (omit for the default);
154
- `danger` for destructive; `size="small"` for compact.
224
+ `type` is `primary | tertiary | link` (omit for the default); `danger` for destructive;
225
+ `size="small"` for compact.
155
226
 
156
227
  ```tsx
157
228
  <Button componentId="settings.save" type="primary" onClick={handleSave}>
@@ -159,13 +230,13 @@ handles state, accessibility, and theming for you.
159
230
  </Button>
160
231
 
161
232
  // Icon-only buttons must carry an accessible label.
162
- <Button componentId="row.delete" icon={<TrashIcon />} aria-label="Delete row" danger />
233
+ <Button componentId="row.delete" icon={<TrashIcon/>} aria-label="Delete row" danger/>
163
234
  ```
164
235
 
165
236
  ### Typography
166
237
 
167
- Never render bare `<h1>`–`<h4>`, `<p>`, or `<a>` for content, so that sizing, color tokens, and
168
- link behavior come from the system.
238
+ Never render bare `<h1>`–`<h4>`, `<p>`, or `<a>` for content, so that sizing, color tokens, and link
239
+ behavior come from the system.
169
240
 
170
241
  ```tsx
171
242
  <Typography.Title level={2}>Section title</Typography.Title>
@@ -182,14 +253,15 @@ Give every input a real label, not a `placeholder` alone. Use `validationState`
182
253
 
183
254
  ```tsx
184
255
  <FormUI.Label htmlFor="email">Email</FormUI.Label>
185
- <Input id="email" componentId="signup.email" type="email" />
186
- <FormUI.Message message="Enter a valid email" type="error" />
256
+ <Input id="email" componentId="signup.email" type="email"/>
257
+ <FormUI.Message message="Enter a valid email" type="error"/>
187
258
 
188
259
  <Checkbox componentId="terms.accept" isChecked={agreed} onChange={setAgreed}>
189
260
  I agree to the terms
190
261
  </Checkbox>
191
262
 
192
- <Switch componentId="settings.notifications" checked={enabled} onChange={setEnabled} label="Email notifications" />
263
+ <Switch componentId="settings.notifications" checked={enabled} onChange={setEnabled}
264
+ label="Email notifications"/>
193
265
 
194
266
  <SimpleSelect componentId="chart.type" value={type} onChange={setType} placeholder="Chart type">
195
267
  <SimpleSelectOption value="bar">Bar</SimpleSelectOption>
@@ -200,15 +272,15 @@ Give every input a real label, not a `placeholder` alone. Use `validationState`
200
272
  With React Hook Form, use `RHFControlledComponents.*` — each takes `name` + `control` + `rules`
201
273
  plus the underlying component's props. Available: `Input`, `PasswordInput`, `TextArea`,
202
274
  `Select`, `Checkbox`, `CheckboxGroup`, `Radio`, `RadioGroup`, `Switch`, `DialogCombobox`,
203
- `TypeaheadCombobox`, `MultiSelectTypeaheadCombobox`.
275
+ `TypeaheadComboboxV2`, `MultiSelectTypeaheadComboboxV2`.
204
276
 
205
277
  ```tsx
206
278
  <Form componentId="signup.form" onSubmit={handleSubmit(onSubmit)}>
207
279
  <RHFControlledComponents.Input
208
- name="email"
209
- control={control}
210
- componentId="signup.email"
211
- rules={{ required: 'Email is required' }}
280
+ name="email"
281
+ control={control}
282
+ componentId="signup.email"
283
+ rules={{required: 'Email is required'}}
212
284
  />
213
285
  <Button componentId="signup.submit" htmlType="submit" type="primary">
214
286
  Sign up
@@ -223,12 +295,12 @@ restyling a `Modal`. Both need a `title` for their accessible name.
223
295
 
224
296
  ```tsx
225
297
  <DangerModal
226
- componentId="delete.modal"
227
- visible={open}
228
- title="Delete project"
229
- okText="Delete"
230
- onOk={handleDelete}
231
- onCancel={close}
298
+ componentId="delete.modal"
299
+ visible={open}
300
+ title="Delete project"
301
+ okText="Delete"
302
+ onOk={handleDelete}
303
+ onCancel={close}
232
304
  >
233
305
  This permanently deletes all project data.
234
306
  </DangerModal>
@@ -243,11 +315,11 @@ Compound API: `Root` / `Trigger` (use `asChild` to wrap your own `Button`) / `Co
243
315
  ```tsx
244
316
  <DropdownMenu.Root>
245
317
  <DropdownMenu.Trigger asChild>
246
- <Button componentId="row.menu" icon={<OverflowIcon />} aria-label="More actions" />
318
+ <Button componentId="row.menu" icon={<OverflowIcon/>} aria-label="More actions"/>
247
319
  </DropdownMenu.Trigger>
248
320
  <DropdownMenu.Content>
249
321
  <DropdownMenu.Item componentId="row.edit" onClick={edit}>Edit</DropdownMenu.Item>
250
- <DropdownMenu.Separator />
322
+ <DropdownMenu.Separator/>
251
323
  <DropdownMenu.Item componentId="row.delete" onClick={remove}>Delete</DropdownMenu.Item>
252
324
  </DropdownMenu.Content>
253
325
  </DropdownMenu.Root>
@@ -255,33 +327,31 @@ Compound API: `Root` / `Trigger` (use `asChild` to wrap your own `Button`) / `Co
255
327
 
256
328
  ### Tooltip and InfoTooltip
257
329
 
258
- `Tooltip` wraps a control and describes it. For a standalone info affordance next to a label,
259
- use `InfoTooltip` — it bundles the icon, the tooltip, accessibility, and theming. Never compose
330
+ `Tooltip` wraps a control and describes it. For a standalone info affordance next to a label, use
331
+ `InfoTooltip` — it bundles the icon, the tooltip, accessibility, and theming. Never compose
260
332
  `Tooltip` around an `InfoIcon` yourself.
261
333
 
262
- Both take a required `componentId`.
263
-
264
334
  ```tsx
265
335
  // Incorrect — hand-rolled info affordance
266
- <Tooltip componentId="search.info" content="Searches project names only."><InfoIcon /></Tooltip>
336
+ <Tooltip componentId="search.info" content="Searches project names only."><InfoIcon/></Tooltip>
267
337
 
268
338
  // Correct
269
339
  <FormUI.Label htmlFor="search">
270
- Search <InfoTooltip componentId="search.info" content="Searches project names only." />
340
+ Search <InfoTooltip componentId="search.info" content="Searches project names only."/>
271
341
  </FormUI.Label>
272
342
 
273
343
  // Tooltip is for describing a control you already have
274
344
  <Tooltip componentId="refresh.tooltip" content="Refresh data">
275
- <Button componentId="refresh" icon={<RefreshIcon />} aria-label="Refresh" />
345
+ <Button componentId="refresh" icon={<RefreshIcon/>} aria-label="Refresh"/>
276
346
  </Tooltip>
277
347
  ```
278
348
 
279
349
  ### Table
280
350
 
281
351
  Compose `Table` from the flat exports `TableRow`, `TableHeader`, and `TableCell`. These are
282
- individual named exports, not a namespace — there is no `TableUI.*`, and no separate head or
283
- body wrapper. Mark the header row with `isHeader`, and give each `TableHeader` a
284
- `componentId`. `LegacyTable` is deprecated.
352
+ individual named exports, not a namespace — there is no `TableUI.*`, and no separate head or body
353
+ wrapper. Mark the header row with `isHeader`, and give each `TableHeader` a
354
+ `componentId`.
285
355
 
286
356
  ```tsx
287
357
  <Table>
@@ -290,10 +360,10 @@ body wrapper. Mark the header row with `isHeader`, and give each `TableHeader` a
290
360
  <TableHeader componentId="projects.header.status">Status</TableHeader>
291
361
  </TableRow>
292
362
  {rows.map((row) => (
293
- <TableRow key={row.id}>
294
- <TableCell>{row.name}</TableCell>
295
- <TableCell>{row.status}</TableCell>
296
- </TableRow>
363
+ <TableRow key={row.id}>
364
+ <TableCell>{row.name}</TableCell>
365
+ <TableCell>{row.status}</TableCell>
366
+ </TableRow>
297
367
  ))}
298
368
  </Table>
299
369
  ```
@@ -303,8 +373,8 @@ Related exports for richer tables: `TableRowAction`, `TableRowActionHeader`,
303
373
 
304
374
  ### Icons
305
375
 
306
- Icons are standalone components — `<PlusIcon />`, `<TrashIcon />`. They take no `componentId`.
307
- Never use the legacy `<Icon component={PlusIcon} />` form, and import icons only from
376
+ Icons are standalone components — `<PlusIcon />`, `<TrashIcon />`. They take no `componentId`. Never
377
+ use the legacy `<Icon component={PlusIcon} />` form, and import icons only from
308
378
  `@databricks/design-system`.
309
379
 
310
380
  ### Loading and empty states
@@ -314,36 +384,40 @@ where the content shape is known, is the single most common way agent-written Du
314
384
  unfinished.
315
385
 
316
386
  - `Skeleton` variants (`TitleSkeleton`, `ParagraphSkeleton`, `TableSkeleton`,
317
- `GenericSkeleton`) — use one shaped like the content it replaces, so there is no layout jump
318
- when data arrives. This is the default choice for a loading branch.
387
+ `GenericSkeleton`) — use one shaped like the content it replaces, so there is no layout jump when
388
+ data arrives. This is the default choice for a loading branch.
319
389
  - `Spinner` — only when the content shape is unknown. Pass `label` for its accessible name.
320
390
  - `Empty` — needs `title` and `description`; add a `button` for the next step.
321
391
 
322
392
  ```tsx
323
393
  // Incorrect — hand-rolled loading text
324
- {isLoading ? <div css={{ textAlign: 'center' }}><Typography.Text>Loading…</Typography.Text></div> : …}
394
+ {
395
+ isLoading ? <div css={{textAlign: 'center'}}><Typography.Text>Loading…</Typography.Text></div> : …
396
+ }
325
397
 
326
398
  // Correct — a skeleton shaped like the table it replaces
327
- {isLoading ? (
328
- <TableSkeleton lines={5} />
329
- ) : rows.length ? (
330
- <Table>…</Table>
331
- ) : (
332
- <Empty title="No dashboards" description="Create one to get started." />
333
- )}
399
+ {
400
+ isLoading ? (
401
+ <TableSkeleton lines={5}/>
402
+ ) : rows.length ? (
403
+ <Table>…</Table>
404
+ ) : (
405
+ <Empty title="No dashboards" description="Create one to get started."/>
406
+ )
407
+ }
334
408
  ```
335
409
 
336
410
  ## Accessibility
337
411
 
338
- Du Bois components target WCAG 2.2 and handle roles and semantics, focus management (dialogs
339
- trap and restore focus; overlays handle Escape and outside-click), keyboard interaction,
340
- focus-visible outlines, and token contrast in both themes. The corollary: replacing a component
341
- with raw HTML or overriding its structure means taking all of that on yourself.
412
+ Du Bois components target WCAG 2.2 and handle roles and semantics, focus management (dialogs trap
413
+ and restore focus; overlays handle Escape and outside-click), keyboard interaction, focus-visible
414
+ outlines, and token contrast in both themes. The corollary: replacing a component with raw HTML or
415
+ overriding its structure means taking all of that on yourself.
342
416
 
343
417
  You must supply:
344
418
 
345
- - **Accessible labels on icon-only controls.** An icon-only `Button` has no accessible name.
346
- A wrapping `Tooltip` is not a substitute — it contributes a *description*
419
+ - **Accessible labels on icon-only controls.** An icon-only `Button` has no accessible name. A
420
+ wrapping `Tooltip` is not a substitute — it contributes a *description*
347
421
  (`aria-describedby`), not a *name*. Always set `aria-label`.
348
422
  - **Real labels on form controls.** A `placeholder` disappears on input and is not reliably
349
423
  announced.
@@ -369,8 +443,8 @@ You must supply:
369
443
 
370
444
  ### Raw HTML where a component exists
371
445
 
372
- Use Du Bois components for interactive controls and styled text. Use semantic HTML for
373
- structure and layout (`div`, `span`, `section`, `ul`/`li`).
446
+ Use Du Bois components for interactive controls and styled text. Use semantic HTML for structure and
447
+ layout (`div`, `span`, `section`, `ul`/`li`).
374
448
 
375
449
  ```tsx
376
450
  // Incorrect
@@ -386,8 +460,8 @@ structure and layout (`div`, `span`, `section`, `ul`/`li`).
386
460
 
387
461
  ### Missing or bad `componentId`
388
462
 
389
- Required on most interactive components, for analytics. Supply a stable, human-readable dotted
390
- path. Never a uuid, and never PII (emails, resource names, user input).
463
+ Required on most interactive components, for analytics. Supply a stable, human-readable dotted path.
464
+ Never a uuid, and never PII (emails, resource names, user input).
391
465
 
392
466
  ```tsx
393
467
  // Incorrect
@@ -403,15 +477,15 @@ path. Never a uuid, and never PII (emails, resource names, user input).
403
477
 
404
478
  ```tsx
405
479
  // Incorrect
406
- <div css={{ color: '#64727D', marginTop: 8, padding: '4px 12px' }} />
480
+ <div css={{color: '#64727D', marginTop: 8, padding: '4px 12px'}}/>
407
481
 
408
482
  // Correct
409
483
  <div
410
- css={{
411
- color: theme.colors.textSecondary,
412
- marginTop: theme.spacing.sm,
413
- padding: `${theme.spacing.xs}px ${theme.spacing.mid}px`,
414
- }}
484
+ css={{
485
+ color: theme.colors.textSecondary,
486
+ marginTop: theme.spacing.sm,
487
+ padding: `${theme.spacing.xs}px ${theme.spacing.mid}px`,
488
+ }}
415
489
  />
416
490
  ```
417
491
 
@@ -423,51 +497,50 @@ Don't reach for `css=`, `style=`, `dangerouslySetAntdProps`, `dangerouslyAppendE
423
497
 
424
498
  ```tsx
425
499
  // Incorrect — fighting the component
426
- <Button componentId="x" css={{ backgroundColor: '#1B5E20', border: 'none' }}>Save</Button>
500
+ <Button componentId="x" css={{backgroundColor: '#1B5E20', border: 'none'}}>Save</Button>
427
501
 
428
502
  // Correct — use the intended prop
429
503
  <Button componentId="x" type="primary">Save</Button>
430
504
  ```
431
505
 
432
- `className` for *layout* (margin, max-width, grid placement) is fine. `className` or `css` to
433
- change a component's *colors or typography* is not.
506
+ `className` for *layout* (margin, max-width, grid placement) is fine. `className` or `css` to change
507
+ a component's *colors or typography* is not.
434
508
 
435
509
  ### Legacy components
436
510
 
437
511
  Du Bois ships modern replacements for every `Legacy*` component. Don't introduce new
438
- `LegacySelect`, `LegacyTable`, `LegacyTooltip`, `LegacyPopover`, or `LegacyForm` imports.
512
+ `LegacySelect`, `LegacyTable`, `LegacyPopover`, or `LegacyForm` imports.
439
513
  `Layout` (`Layout.Header` / `.Sider` / `.Content`) is likewise deprecated — use `PageWrapper` +
440
514
  `Header`.
441
515
 
442
516
  ### Direct AntD imports
443
517
 
444
- Du Bois is built on AntD internally. Never import AntD or `@ant-design/icons` directly — it
445
- bypasses theming and breaks on version bumps.
518
+ Du Bois is built on AntD internally. Never import AntD or `@ant-design/icons` directly — it bypasses
519
+ theming and breaks on version bumps.
446
520
 
447
521
  ```tsx
448
522
  // Incorrect
449
- import { Button } from 'antd';
450
- import { PlusOutlined } from '@ant-design/icons';
523
+ import {Button} from 'antd';
524
+ import {PlusOutlined} from '@ant-design/icons';
451
525
 
452
526
  // Correct
453
- import { Button, PlusIcon } from '@databricks/design-system';
527
+ import {Button, PlusIcon} from '@databricks/design-system';
454
528
  ```
455
529
 
456
530
  ## Making it look good
457
531
 
458
- Polish comes from restraint and consistency, not decoration. Gradients, glass effects, heavy
459
- shadows, and custom accent colors make an enterprise data product look worse. If you are
460
- tempted to hand-write a color, shadow, radius, or spacing value to make something "pop," that
461
- is the signal you are leaving the system.
462
-
463
- - **Use the scales.** Reuse a few spacing steps for rhythm rather than mixing `13px` and
464
- `15px`. Establish hierarchy with `Typography.Title` levels and `Text` sizes, never a hand-set
465
- `fontSize`. Body text reads best at 45–90 characters per line.
466
- - **Let components own elevation.** Card, Popover, Modal, and Dropdown apply their own shadow.
467
- Setting `boxShadow` by hand is almost always wrong.
468
- - **Let semantic tokens carry state.** Prefer a component's own prop (`type="primary"`,
469
- `danger`) over reaching for a raw token — the component wires the full hover/press/disabled
470
- set. Never let color be the only signal for meaning; pair it with an icon, label, or weight.
471
- - **Build the states everyone skips.** Loading (shape-matched skeletons), empty (`Empty` with a
472
- next step), and hover/focus/active/disabled are what separate polished UI from unpolished.
532
+ Polish is restraint, not decoration. Gradients, glass effects, heavy shadows, and custom accent
533
+ colors make an enterprise data product look worse; hand-writing a color, shadow, radius, or spacing
534
+ value to make something "pop" is the signal you are leaving the system.
535
+
536
+ - **Use the scales.** Reuse a few spacing steps rather than mixing `13px` and `15px`; set hierarchy
537
+ with `Typography.Title` levels and `Text` sizes, never a hand-set `fontSize`. Body text reads best
538
+ at 45–90 characters per line.
539
+ - **Let components own elevation.** Card, Popover, Modal, and Dropdown apply their own shadow —
540
+ hand-set `boxShadow` is almost always wrong.
541
+ - **Let semantic tokens carry state.** Prefer a component's own prop (`type="primary"`, `danger`)
542
+ over a raw token; it wires the full hover/press/disabled set. Never let color be the only signal —
543
+ pair it with an icon, label, or weight.
544
+ - **Build the states everyone skips** loading (shape-matched skeletons), empty (`Empty` with a
545
+ next step), hover/focus/active/disabled.
473
546
  - **Match density to context** with `size` props rather than cramming default-size components.