@databricks/design-system 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +473 -0
- package/CHANGELOG.md +5 -0
- package/README.md +5 -3
- package/dist/{WizardStepContentWrapper-Dvdj_FRA.js → WizardStepContentWrapper-DnwQIMN1.js} +787 -193
- package/dist/WizardStepContentWrapper-DnwQIMN1.js.map +1 -0
- package/dist/dubois-colors.less +2 -0
- package/dist/index-dark.css +10 -319
- package/dist/index-dark.mitigated.css +10 -319
- package/dist/index.css +61 -279
- package/dist/index.js +1809 -155
- package/dist/index.js.map +1 -1
- package/dist/index.mitigated.css +61 -279
- package/dist/patterns.js +10 -1
- package/dist/patterns.js.map +1 -1
- package/dist-types/design-system/Button/Button.d.ts +2 -2
- package/dist-types/design-system/Drawer/DrawerContext.d.ts +9 -0
- package/dist-types/design-system/FormV2/RHFAdapters.d.ts +8 -8
- package/dist-types/design-system/Grid/Col.d.ts +2 -2
- package/dist-types/design-system/Grid/Row.d.ts +2 -2
- package/dist-types/design-system/Icon/__generated/icons/FlowsIcon.d.ts +4 -0
- package/dist-types/design-system/Icon/__generated/icons/LakewatchAlertIcon.d.ts +4 -0
- package/dist-types/design-system/Icon/__generated/icons/LakewatchDatasourceIcon.d.ts +4 -0
- package/dist-types/design-system/Icon/__generated/icons/LakewatchDetectionRuleIcon.d.ts +4 -0
- package/dist-types/design-system/Icon/__generated/icons/LakewatchParserIcon.d.ts +4 -0
- package/dist-types/design-system/Icon/__generated/icons/index.d.ts +5 -0
- package/dist-types/design-system/LegacyTooltip/index.d.ts +0 -1
- package/dist-types/design-system/Skeleton/TitleSkeleton.d.ts +9 -3
- package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxControls.d.ts +2 -0
- package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxMultiSelectInput.d.ts +9 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/CountBadge.d.ts +6 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxAddButton.d.ts +3 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxCheckboxItem.d.ts +10 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxControls.d.ts +11 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxFooter.d.ts +2 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxInput.d.ts +9 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxMenu.d.ts +17 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxMenuItem.d.ts +16 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxMultiSelectInput.d.ts +18 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxRoot.d.ts +17 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxSectionHeader.d.ts +1 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxSelectedItem.d.ts +11 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxSeparator.d.ts +1 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/TypeaheadComboboxToggleButton.d.ts +4 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/hooks/footerFocus.d.ts +13 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/hooks/index.d.ts +4 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/hooks/useComboboxItems.d.ts +32 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/hooks/useComboboxState.d.ts +75 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/hooks/useComboboxStateProps.d.ts +36 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/hooks/useMultipleSelectionState.d.ts +25 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/hooks/useScrollOptionIntoView.d.ts +11 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/hooks/useTypeaheadComboboxContext.d.ts +2 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/hooks/useVirtualizedComboboxScroll.d.ts +36 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/index.d.ts +13 -0
- package/dist-types/design-system/TypeaheadComboboxReactAria/providers/TypeaheadComboboxContext.d.ts +45 -0
- package/dist-types/design-system/Typography/titleLevel.d.ts +11 -0
- package/dist-types/design-system/index.d.ts +1 -0
- package/dist-types/design-system/utils/useMediaQuery.d.ts +4 -1
- package/dist-types/theme/_generated/ValidSemanticColors.d.ts +2 -1
- package/package.json +14 -3
- package/dist/WizardStepContentWrapper-Dvdj_FRA.js.map +0 -1
- package/dist-types/design-system/LegacyTooltip/LegacyInfoTooltip.d.ts +0 -16
package/AGENTS.md
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
# Using Du Bois (`@databricks/design-system`)
|
|
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`.
|
|
6
|
+
|
|
7
|
+
## If you remember only four things
|
|
8
|
+
|
|
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.
|
|
11
|
+
3. **Always pass `componentId`** — stable, dotted, no PII.
|
|
12
|
+
4. **Never hardcode colors or spacing** — read `theme.*` tokens.
|
|
13
|
+
|
|
14
|
+
## Setup
|
|
15
|
+
|
|
16
|
+
Install the package and its peer dependencies:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @databricks/design-system @emotion/react react react-dom moment
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`moment` is required by the date components. `@jest/globals` is an additional peer dependency
|
|
23
|
+
if you use the `test-utils` entry point.
|
|
24
|
+
|
|
25
|
+
Import the stylesheet once at your app's entry point, wrap the tree in
|
|
26
|
+
`DesignSystemProvider`, and render `ApplyGlobalStyles` inside it:
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import '@databricks/design-system/index.css';
|
|
30
|
+
import '@databricks/design-system/fonts/dm-sans.css';
|
|
31
|
+
|
|
32
|
+
import { ApplyGlobalStyles, DesignSystemProvider } from '@databricks/design-system';
|
|
33
|
+
|
|
34
|
+
export const App = () => (
|
|
35
|
+
<DesignSystemProvider>
|
|
36
|
+
<ApplyGlobalStyles />
|
|
37
|
+
<YourApp />
|
|
38
|
+
</DesignSystemProvider>
|
|
39
|
+
);
|
|
40
|
+
```
|
|
41
|
+
|
|
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.
|
|
45
|
+
|
|
46
|
+
Styling uses the Emotion `css` prop, so configure Emotion's JSX runtime — set
|
|
47
|
+
`jsxImportSource: '@emotion/react'` in your TypeScript or Babel config, or add
|
|
48
|
+
`/** @jsxImportSource @emotion/react */` per file.
|
|
49
|
+
|
|
50
|
+
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:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// css.d.ts
|
|
56
|
+
declare module '*.css';
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Theming
|
|
60
|
+
|
|
61
|
+
Read every design value off the theme.
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { useDesignSystemTheme } from '@databricks/design-system';
|
|
65
|
+
|
|
66
|
+
const MyPanel = () => {
|
|
67
|
+
const { theme } = useDesignSystemTheme();
|
|
68
|
+
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
|
+
/>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- **Spacing** — `theme.spacing`: `xs` (4), `sm` (8), `mid` (12), `md` (16), `lg` (24), `xl` (32).
|
|
82
|
+
For a gap between two elements use `<Spacer size="md" />`.
|
|
83
|
+
- **Colors** — semantic tokens on `theme.colors`: `textPrimary`, `textSecondary`,
|
|
84
|
+
`backgroundPrimary`, `border`, `actionPrimaryBackgroundDefault`, and so on. Never a hex value.
|
|
85
|
+
- **Radius** — `theme.borders.borderRadius*`. **Shadows** — `theme.shadows.{xs,sm,md,lg,xl}`.
|
|
86
|
+
- **Motion** — `theme.animation.transitionDuration` (170ms).
|
|
87
|
+
|
|
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.
|
|
119
|
+
|
|
120
|
+
## Use the composite
|
|
121
|
+
|
|
122
|
+
When you are about to combine primitives, stop. A purpose-built composite usually exists and
|
|
123
|
+
handles state, accessibility, and theming for you.
|
|
124
|
+
|
|
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` |
|
|
135
|
+
|
|
136
|
+
### Picking an overlay
|
|
137
|
+
|
|
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`) |
|
|
148
|
+
|
|
149
|
+
## Common components
|
|
150
|
+
|
|
151
|
+
### Button
|
|
152
|
+
|
|
153
|
+
`componentId` is required. `type` is `primary | tertiary | link` (omit for the default);
|
|
154
|
+
`danger` for destructive; `size="small"` for compact.
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
<Button componentId="settings.save" type="primary" onClick={handleSave}>
|
|
158
|
+
Save changes
|
|
159
|
+
</Button>
|
|
160
|
+
|
|
161
|
+
// Icon-only buttons must carry an accessible label.
|
|
162
|
+
<Button componentId="row.delete" icon={<TrashIcon />} aria-label="Delete row" danger />
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Typography
|
|
166
|
+
|
|
167
|
+
Never render bare `<h1>`–`<h4>`, `<p>`, or `<a>` for content, so that sizing, color tokens, and
|
|
168
|
+
link behavior come from the system.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
<Typography.Title level={2}>Section title</Typography.Title>
|
|
172
|
+
<Typography.Paragraph>Body copy.</Typography.Paragraph>
|
|
173
|
+
<Typography.Text bold>Emphasis</Typography.Text>
|
|
174
|
+
<Typography.Text color="secondary" size="sm">Muted helper text</Typography.Text>
|
|
175
|
+
<Typography.Link href="/docs">Learn more</Typography.Link>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Input and form controls
|
|
179
|
+
|
|
180
|
+
Give every input a real label, not a `placeholder` alone. Use `validationState`
|
|
181
|
+
(`error | warning | success`) to show state.
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
<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" />
|
|
187
|
+
|
|
188
|
+
<Checkbox componentId="terms.accept" isChecked={agreed} onChange={setAgreed}>
|
|
189
|
+
I agree to the terms
|
|
190
|
+
</Checkbox>
|
|
191
|
+
|
|
192
|
+
<Switch componentId="settings.notifications" checked={enabled} onChange={setEnabled} label="Email notifications" />
|
|
193
|
+
|
|
194
|
+
<SimpleSelect componentId="chart.type" value={type} onChange={setType} placeholder="Chart type">
|
|
195
|
+
<SimpleSelectOption value="bar">Bar</SimpleSelectOption>
|
|
196
|
+
<SimpleSelectOption value="line">Line</SimpleSelectOption>
|
|
197
|
+
</SimpleSelect>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
With React Hook Form, use `RHFControlledComponents.*` — each takes `name` + `control` + `rules`
|
|
201
|
+
plus the underlying component's props. Available: `Input`, `PasswordInput`, `TextArea`,
|
|
202
|
+
`Select`, `Checkbox`, `CheckboxGroup`, `Radio`, `RadioGroup`, `Switch`, `DialogCombobox`,
|
|
203
|
+
`TypeaheadCombobox`, `MultiSelectTypeaheadCombobox`.
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
<Form componentId="signup.form" onSubmit={handleSubmit(onSubmit)}>
|
|
207
|
+
<RHFControlledComponents.Input
|
|
208
|
+
name="email"
|
|
209
|
+
control={control}
|
|
210
|
+
componentId="signup.email"
|
|
211
|
+
rules={{ required: 'Email is required' }}
|
|
212
|
+
/>
|
|
213
|
+
<Button componentId="signup.submit" htmlType="submit" type="primary">
|
|
214
|
+
Sign up
|
|
215
|
+
</Button>
|
|
216
|
+
</Form>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Modal and DangerModal
|
|
220
|
+
|
|
221
|
+
`Modal` is controlled by `visible`. Use `DangerModal` for destructive confirmations rather than
|
|
222
|
+
restyling a `Modal`. Both need a `title` for their accessible name.
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
<DangerModal
|
|
226
|
+
componentId="delete.modal"
|
|
227
|
+
visible={open}
|
|
228
|
+
title="Delete project"
|
|
229
|
+
okText="Delete"
|
|
230
|
+
onOk={handleDelete}
|
|
231
|
+
onCancel={close}
|
|
232
|
+
>
|
|
233
|
+
This permanently deletes all project data.
|
|
234
|
+
</DangerModal>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### DropdownMenu
|
|
238
|
+
|
|
239
|
+
Compound API: `Root` / `Trigger` (use `asChild` to wrap your own `Button`) / `Content` / `Item` /
|
|
240
|
+
`Separator` / `CheckboxItem` / `RadioGroup` + `RadioItem` / `Sub`. `componentId` goes on each
|
|
241
|
+
`Item`.
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
<DropdownMenu.Root>
|
|
245
|
+
<DropdownMenu.Trigger asChild>
|
|
246
|
+
<Button componentId="row.menu" icon={<OverflowIcon />} aria-label="More actions" />
|
|
247
|
+
</DropdownMenu.Trigger>
|
|
248
|
+
<DropdownMenu.Content>
|
|
249
|
+
<DropdownMenu.Item componentId="row.edit" onClick={edit}>Edit</DropdownMenu.Item>
|
|
250
|
+
<DropdownMenu.Separator />
|
|
251
|
+
<DropdownMenu.Item componentId="row.delete" onClick={remove}>Delete</DropdownMenu.Item>
|
|
252
|
+
</DropdownMenu.Content>
|
|
253
|
+
</DropdownMenu.Root>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Tooltip and InfoTooltip
|
|
257
|
+
|
|
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
|
|
260
|
+
`Tooltip` around an `InfoIcon` yourself.
|
|
261
|
+
|
|
262
|
+
Both take a required `componentId`.
|
|
263
|
+
|
|
264
|
+
```tsx
|
|
265
|
+
// Incorrect — hand-rolled info affordance
|
|
266
|
+
<Tooltip componentId="search.info" content="Searches project names only."><InfoIcon /></Tooltip>
|
|
267
|
+
|
|
268
|
+
// Correct
|
|
269
|
+
<FormUI.Label htmlFor="search">
|
|
270
|
+
Search <InfoTooltip componentId="search.info" content="Searches project names only." />
|
|
271
|
+
</FormUI.Label>
|
|
272
|
+
|
|
273
|
+
// Tooltip is for describing a control you already have
|
|
274
|
+
<Tooltip componentId="refresh.tooltip" content="Refresh data">
|
|
275
|
+
<Button componentId="refresh" icon={<RefreshIcon />} aria-label="Refresh" />
|
|
276
|
+
</Tooltip>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Table
|
|
280
|
+
|
|
281
|
+
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.
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
<Table>
|
|
288
|
+
<TableRow isHeader>
|
|
289
|
+
<TableHeader componentId="projects.header.name">Name</TableHeader>
|
|
290
|
+
<TableHeader componentId="projects.header.status">Status</TableHeader>
|
|
291
|
+
</TableRow>
|
|
292
|
+
{rows.map((row) => (
|
|
293
|
+
<TableRow key={row.id}>
|
|
294
|
+
<TableCell>{row.name}</TableCell>
|
|
295
|
+
<TableCell>{row.status}</TableCell>
|
|
296
|
+
</TableRow>
|
|
297
|
+
))}
|
|
298
|
+
</Table>
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Related exports for richer tables: `TableRowAction`, `TableRowActionHeader`,
|
|
302
|
+
`TableRowSelectCell`, `TableFilterInput`, `TableFilterLayout`, `TableSkeleton`.
|
|
303
|
+
|
|
304
|
+
### Icons
|
|
305
|
+
|
|
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
|
|
308
|
+
`@databricks/design-system`.
|
|
309
|
+
|
|
310
|
+
### Loading and empty states
|
|
311
|
+
|
|
312
|
+
Never hand-roll these. A `<div>` containing "Loading…" text, or a bare centered `Spinner`
|
|
313
|
+
where the content shape is known, is the single most common way agent-written Du Bois UI looks
|
|
314
|
+
unfinished.
|
|
315
|
+
|
|
316
|
+
- `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.
|
|
319
|
+
- `Spinner` — only when the content shape is unknown. Pass `label` for its accessible name.
|
|
320
|
+
- `Empty` — needs `title` and `description`; add a `button` for the next step.
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
// Incorrect — hand-rolled loading text
|
|
324
|
+
{isLoading ? <div css={{ textAlign: 'center' }}><Typography.Text>Loading…</Typography.Text></div> : …}
|
|
325
|
+
|
|
326
|
+
// 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
|
+
)}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Accessibility
|
|
337
|
+
|
|
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.
|
|
342
|
+
|
|
343
|
+
You must supply:
|
|
344
|
+
|
|
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*
|
|
347
|
+
(`aria-describedby`), not a *name*. Always set `aria-label`.
|
|
348
|
+
- **Real labels on form controls.** A `placeholder` disappears on input and is not reliably
|
|
349
|
+
announced.
|
|
350
|
+
- **Meaningful text.** Button and link text must describe the action, not "Click here".
|
|
351
|
+
- **Semantic structure.** Landmarks (`nav`, `main`, `section`) and headings via
|
|
352
|
+
`Typography.Title` with the correct `level`, not a tree of `<div>`s.
|
|
353
|
+
- **No nested interactive controls.** An interactive element must never contain another. This
|
|
354
|
+
applies inside composites whose items are already interactive: put the action on
|
|
355
|
+
`DropdownMenu.Item` itself, or use `asChild` to render the item *as* a link. Use
|
|
356
|
+
`DropdownMenu.CheckboxItem` / `RadioItem` rather than nesting a `Checkbox` in an `Item`.
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
// Incorrect — button nested inside an already-interactive menu item
|
|
360
|
+
<DropdownMenu.Item componentId="row.rename">
|
|
361
|
+
<Button componentId="row.rename.btn" onClick={rename}>Rename</Button>
|
|
362
|
+
</DropdownMenu.Item>
|
|
363
|
+
|
|
364
|
+
// Correct — the item is the control
|
|
365
|
+
<DropdownMenu.Item componentId="row.rename" onClick={rename}>Rename</DropdownMenu.Item>
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Pitfalls
|
|
369
|
+
|
|
370
|
+
### Raw HTML where a component exists
|
|
371
|
+
|
|
372
|
+
Use Du Bois components for interactive controls and styled text. Use semantic HTML for
|
|
373
|
+
structure and layout (`div`, `span`, `section`, `ul`/`li`).
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
// Incorrect
|
|
377
|
+
<button onClick={save}>Save</button>
|
|
378
|
+
<a href="/docs">Docs</a>
|
|
379
|
+
<h2>Settings</h2>
|
|
380
|
+
|
|
381
|
+
// Correct
|
|
382
|
+
<Button componentId="save" onClick={save}>Save</Button>
|
|
383
|
+
<Typography.Link href="/docs">Docs</Typography.Link>
|
|
384
|
+
<Typography.Title level={2}>Settings</Typography.Title>
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Missing or bad `componentId`
|
|
388
|
+
|
|
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).
|
|
391
|
+
|
|
392
|
+
```tsx
|
|
393
|
+
// Incorrect
|
|
394
|
+
<Button onClick={save}>Save</Button>
|
|
395
|
+
<Button componentId={crypto.randomUUID()} onClick={save}>Save</Button>
|
|
396
|
+
<Button componentId={`share.${user.email}`} onClick={save}>Save</Button>
|
|
397
|
+
|
|
398
|
+
// Correct
|
|
399
|
+
<Button componentId="settings.save" onClick={save}>Save</Button>
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Hardcoded colors and spacing
|
|
403
|
+
|
|
404
|
+
```tsx
|
|
405
|
+
// Incorrect
|
|
406
|
+
<div css={{ color: '#64727D', marginTop: 8, padding: '4px 12px' }} />
|
|
407
|
+
|
|
408
|
+
// Correct
|
|
409
|
+
<div
|
|
410
|
+
css={{
|
|
411
|
+
color: theme.colors.textSecondary,
|
|
412
|
+
marginTop: theme.spacing.sm,
|
|
413
|
+
padding: `${theme.spacing.xs}px ${theme.spacing.mid}px`,
|
|
414
|
+
}}
|
|
415
|
+
/>
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Style-overriding a component
|
|
419
|
+
|
|
420
|
+
Don't reach for `css=`, `style=`, `dangerouslySetAntdProps`, `dangerouslyAppendEmotionCSS`,
|
|
421
|
+
`!important`, or an `as` cast to reshape a component's appearance. Look for a real prop first
|
|
422
|
+
(`type`, `size`, `danger`, `contentPadding`).
|
|
423
|
+
|
|
424
|
+
```tsx
|
|
425
|
+
// Incorrect — fighting the component
|
|
426
|
+
<Button componentId="x" css={{ backgroundColor: '#1B5E20', border: 'none' }}>Save</Button>
|
|
427
|
+
|
|
428
|
+
// Correct — use the intended prop
|
|
429
|
+
<Button componentId="x" type="primary">Save</Button>
|
|
430
|
+
```
|
|
431
|
+
|
|
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.
|
|
434
|
+
|
|
435
|
+
### Legacy components
|
|
436
|
+
|
|
437
|
+
Du Bois ships modern replacements for every `Legacy*` component. Don't introduce new
|
|
438
|
+
`LegacySelect`, `LegacyTable`, `LegacyTooltip`, `LegacyPopover`, or `LegacyForm` imports.
|
|
439
|
+
`Layout` (`Layout.Header` / `.Sider` / `.Content`) is likewise deprecated — use `PageWrapper` +
|
|
440
|
+
`Header`.
|
|
441
|
+
|
|
442
|
+
### Direct AntD imports
|
|
443
|
+
|
|
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.
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
// Incorrect
|
|
449
|
+
import { Button } from 'antd';
|
|
450
|
+
import { PlusOutlined } from '@ant-design/icons';
|
|
451
|
+
|
|
452
|
+
// Correct
|
|
453
|
+
import { Button, PlusIcon } from '@databricks/design-system';
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
## Making it look good
|
|
457
|
+
|
|
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.
|
|
473
|
+
- **Match density to context** with `size` props rather than cramming default-size components.
|
package/CHANGELOG.md
ADDED
package/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# DuBois Design System
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Component library for Databricks.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Using DuBois with a coding agent
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
This package ships `AGENTS.md` — setup, component selection, theming, accessibility, and the
|
|
8
|
+
pitfalls to avoid. You can include `@node_modules/@databricks/design-system/AGENTS.md` in your project's agent
|
|
9
|
+
instructions.
|