@scattered-light/loomiere-mojave 0.6.0 → 0.7.1
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/dist/exports/AGENTS.md +24 -8
- package/dist/exports/catalog.json +21 -0
- package/dist/exports/chakra.js +333 -0
- package/dist/exports/design-system/README.md +23 -7
- package/dist/exports/design-system/components/Badge/README.md +35 -0
- package/dist/exports/design-system/components/Badge/preview.html +19 -0
- package/dist/exports/design-system/components/Collection/README.md +14 -0
- package/dist/exports/design-system/components/CollectionPagination/README.md +15 -0
- package/dist/exports/design-system/components/CollectionToolbar/README.md +29 -0
- package/dist/exports/design-system/components/DataList/README.md +39 -0
- package/dist/exports/design-system/components/DataList/preview.html +475 -0
- package/dist/exports/design-system/components/DataTable/README.md +41 -0
- package/dist/exports/design-system/components/DataTable/preview.html +475 -0
- package/dist/exports/design-system/components/DatePicker/README.md +55 -0
- package/dist/exports/design-system/components/DatePicker/preview.html +475 -0
- package/dist/exports/design-system/components/EditableList/README.md +33 -0
- package/dist/exports/design-system/components/EditableList/preview.html +475 -0
- package/dist/exports/design-system/components/EmptyState/README.md +60 -0
- package/dist/exports/design-system/components/EmptyState/preview.html +475 -0
- package/dist/exports/design-system/components/ListDetail/README.md +43 -0
- package/dist/exports/design-system/components/ListDetail/preview.html +475 -0
- package/dist/exports/design-system/components/MoneyField/README.md +52 -0
- package/dist/exports/design-system/components/MoneyField/preview.html +475 -0
- package/dist/exports/design-system/components/Splitter/README.md +42 -0
- package/dist/exports/design-system/components/Splitter/preview.html +475 -0
- package/dist/exports/design-system/components/Table/README.md +2 -1
- package/dist/exports/design-system/components/Table/preview.html +1 -1
- package/dist/exports/design-system/components/bundle.css +2461 -190
- package/dist/exports/design-system/components/bundle.js +7 -5
- package/dist/exports/design-system/components/index.d.ts +3 -21
- package/dist/exports/design-system/tokens.json +15 -0
- package/dist/exports/figma.json +1 -1
- package/dist/exports/mui.js +727 -0
- package/dist/exports/tailwind.css +36 -0
- package/dist/exports/tokens.dtcg.json +320 -2
- package/dist/tokens.css +112 -4
- package/dist/tokens.d.ts +94 -0
- package/dist/tokens.js +95 -1
- package/dist/tokens.json +580 -2
- package/package.json +2 -2
package/dist/exports/AGENTS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This folder is a Loomiere theme. Load `tokens.css` (every token as a `--sl-` variable, light and dark) and `utilities.css` (text styles, focus ring, brand pairs). Framework adapters sit in `exports/`: `tailwind.css` (Tailwind v4: text styles by tier such as `text-body-base`, concept classes such as `bg-field` and `text-link`, no bare sizes like `text-sm`), `shadcn.css` (shadcn/ui), `mui.js`, `chakra.js`, AG Grid themes, `tokens.dtcg.json`. `tokens.json` lists every token with its path, value, modes and the reason it exists; read a token's `description` before using it.
|
|
4
4
|
|
|
5
|
-
Components: `@scattered-light/loomiere-base-ui` (Base UI parts styled by class name; import `@scattered-light/loomiere-base-ui/styles.css` after the theme). `exports/design-system/components/<Name>/README.md` lists each component's classes and an example.
|
|
5
|
+
Components: `@scattered-light/loomiere-base-ui` (Base UI parts styled by class name; import `@scattered-light/loomiere-base-ui/styles.css` after the theme). Collection (`DataTable`, `DataList`, `CollectionToolbar`, `CollectionPagination`) is imported from `@scattered-light/loomiere-base-ui/custom/collection`, and the app installs `@tanstack/react-table`. `EditableList` comes from `@scattered-light/loomiere-base-ui/custom`. Use AG Grid only for spreadsheet work (cell-by-cell editing, ranges, tens of thousands of rows); say why in the code. `exports/design-system/components/<Name>/README.md` lists each component's classes and an example.
|
|
6
6
|
|
|
7
7
|
Change the brand only in the brand file and rebuild (`loomiere build`); never edit generated files.
|
|
8
8
|
|
|
@@ -152,7 +152,7 @@ Looks: this brand can look 2 ways. With no `data-look` it is Mojave; `data-look=
|
|
|
152
152
|
|
|
153
153
|
### Components
|
|
154
154
|
|
|
155
|
-
The components are [Base UI](https://base-ui.com) parts styled by class name: `Accordion`, `AlertDialog`, `Autocomplete`, `Avatar`, `Button`, `Checkbox`, `CheckboxGroup`, `Collapsible`, `Combobox`, `ContextMenu`, `Dialog`, `Drawer`, `Field`, `Fieldset`, `Form`, `Input`, `Menu`, `Menubar`, `Meter`, `NavigationMenu`, `NumberField`, `OTPField`, `Popover`, `PreviewCard`, `Progress`, `Radio`, `ScrollArea`, `Select`, `Separator`, `Slider`, `Switch`, `Table`, `Tabs`, `Toast`, `Toggle`, `ToggleGroup`, `Toolbar`, `Tooltip`. Each component's README lists the classes its parts take and the data attributes they answer to (`data-size="sm|lg"`, `data-emphasis`, `data-color`).
|
|
155
|
+
The components are [Base UI](https://base-ui.com) parts styled by class name: `Accordion`, `AlertDialog`, `Autocomplete`, `Avatar`, `Badge`, `Button`, `Checkbox`, `CheckboxGroup`, `Collapsible`, `Collection`, `CollectionPagination`, `CollectionToolbar`, `Combobox`, `ContextMenu`, `DataList`, `DataTable`, `DatePicker`, `Dialog`, `Drawer`, `EditableList`, `EmptyState`, `Field`, `Fieldset`, `Form`, `Input`, `ListDetail`, `Menu`, `Menubar`, `Meter`, `MoneyField`, `NavigationMenu`, `NumberField`, `OTPField`, `Popover`, `PreviewCard`, `Progress`, `Radio`, `ScrollArea`, `Select`, `Separator`, `Slider`, `Splitter`, `Switch`, `Table`, `Tabs`, `Toast`, `Toggle`, `ToggleGroup`, `Toolbar`, `Tooltip`. Each component's README lists the classes its parts take and the data attributes they answer to (`data-size="sm|lg"`, `data-emphasis`, `data-color`).
|
|
156
156
|
|
|
157
157
|
Icons are Material Symbols Outlined by ligature name (`<span class="material-symbols-outlined">search</span>`, or `Loomiere.MaterialSymbol name="search"`), sized by the `.icon-<tier>` utilities to match the text beside them.
|
|
158
158
|
|
|
@@ -166,8 +166,8 @@ Load three things, in this order:
|
|
|
166
166
|
|
|
167
167
|
`window.Loomiere` holds two kinds of component:
|
|
168
168
|
|
|
169
|
-
- **Wrappers** put their own classes on, so use them bare: `Loomiere.Button`, `Loomiere.Input`, `Loomiere.Field`, `Loomiere.Fieldset`, `Loomiere.Form`, `Loomiere.NavigationMenu`, `Loomiere.Select`, `Loomiere.NumberField`, `Loomiere.OTPField`, `Loomiere.Autocomplete`, `Loomiere.Combobox`, `Loomiere.Checkbox`, `Loomiere.Radio`, `Loomiere.CheckboxGroup`, `Loomiere.Toggle`, `Loomiere.ToggleGroup`, `Loomiere.Dialog`, `Loomiere.AlertDialog`, `Loomiere.Meter`, `Loomiere.Progress`, `Loomiere.Slider`, `Loomiere.Menu`, `Loomiere.ContextMenu`, `Loomiere.Menubar`, `Loomiere.Popover`, `Loomiere.PreviewCard`, `Loomiere.Tooltip`, `Loomiere.Drawer`, `Loomiere.Accordion`, `Loomiere.Collapsible`, `Loomiere.Tabs`, `Loomiere.Switch`, `Loomiere.Toast`, `Loomiere.Avatar`, `Loomiere.Toolbar`, `Loomiere.ScrollArea`, `Loomiere.Separator`. `Loomiere.Button` also takes `emphasis` (`bold|standard|subtle|quiet`) and `palette` props, and a Button holding only an icon draws itself square (it sets `data-icon-only`). Wrapped parts that are buttons (`Dialog.Trigger`, `Menu.Trigger`, `Toolbar.Button`, `Drawer.Close`...) take the same `emphasis` and `palette` props and draw square the same way. `Popover.Trigger`, `Tooltip.Trigger`, `Select.Trigger` and `Dialog.Close` become Buttons only when they set `emphasis`, `palette` or `className="Button"`. A plain `.Button` on a bare part is drawn square when it has an `aria-label` and a single icon inside, or when you set `data-icon-only` on it.
|
|
170
|
-
- **Table
|
|
169
|
+
- **Wrappers** put their own classes on, so use them bare: `Loomiere.Button`, `Loomiere.Input`, `Loomiere.Field`, `Loomiere.Fieldset`, `Loomiere.Form`, `Loomiere.NavigationMenu`, `Loomiere.Select`, `Loomiere.NumberField`, `Loomiere.OTPField`, `Loomiere.Autocomplete`, `Loomiere.Combobox`, `Loomiere.Checkbox`, `Loomiere.Radio`, `Loomiere.CheckboxGroup`, `Loomiere.Toggle`, `Loomiere.ToggleGroup`, `Loomiere.Dialog`, `Loomiere.AlertDialog`, `Loomiere.Meter`, `Loomiere.Progress`, `Loomiere.Slider`, `Loomiere.Menu`, `Loomiere.ContextMenu`, `Loomiere.Menubar`, `Loomiere.Popover`, `Loomiere.PreviewCard`, `Loomiere.Tooltip`, `Loomiere.Drawer`, `Loomiere.Accordion`, `Loomiere.Collapsible`, `Loomiere.Tabs`, `Loomiere.Switch`, `Loomiere.Toast`, `Loomiere.Avatar`, `Loomiere.Toolbar`, `Loomiere.ScrollArea`, `Loomiere.Separator`, `Loomiere.Badge`, `Loomiere.DatePicker`, `Loomiere.MoneyField`, `Loomiere.Splitter`, `Loomiere.ListDetail`, `Loomiere.EmptyState`, `Loomiere.DataTable`, `Loomiere.DataList`, `Loomiere.CollectionToolbar`, `Loomiere.CollectionPagination`, `Loomiere.EditableList`. `Loomiere.Button` also takes `emphasis` (`bold|standard|subtle|quiet`) and `palette` props, and a Button holding only an icon draws itself square (it sets `data-icon-only`). Wrapped parts that are buttons (`Dialog.Trigger`, `Menu.Trigger`, `Toolbar.Button`, `Drawer.Close`...) take the same `emphasis` and `palette` props and draw square the same way. `Popover.Trigger`, `Tooltip.Trigger`, `Select.Trigger` and `Dialog.Close` become Buttons only when they set `emphasis`, `palette` or `className="Button"`. A plain `.Button` on a bare part is drawn square when it has an `aria-label` and a single icon inside, or when you set `data-icon-only` on it. `Loomiere.Badge` takes the same `emphasis` and `palette` props, plus `status`, `size` and `dot`.
|
|
170
|
+
- **Table, Badge, DatePicker, MoneyField, Splitter, ListDetail, EmptyState, DataTable, DataList, CollectionToolbar, CollectionPagination and EditableList are Loomiere components**, not Base UI parts. Table is plain HTML for a static table or a report: use the classes in its stylesheet. Badge is `Loomiere.Badge`. DatePicker is `Loomiere.DatePicker`; `Loomiere.Calendar` is the month grid on its own and `Loomiere.DatePresets` is the quick-selection list. MoneyField is `Loomiere.MoneyField`: an amount of money, stored as minor units. Splitter is `Loomiere.Splitter`. ListDetail is `Loomiere.ListDetail`. EmptyState is `Loomiere.EmptyState`. DataTable, DataList, CollectionToolbar and CollectionPagination come from `@scattered-light/loomiere-base-ui/custom/collection` and need `@tanstack/react-table` installed. EditableList comes from the package root or `./custom`.
|
|
171
171
|
|
|
172
172
|
`Loomiere.Base` holds the bare Base UI parts for the wrappers too (`Loomiere.Base.Button`), for when you need the part without its classes.
|
|
173
173
|
|
|
@@ -177,18 +177,19 @@ Pick by what the person is doing, not by look:
|
|
|
177
177
|
|
|
178
178
|
| Component | Use it to |
|
|
179
179
|
|---|---|
|
|
180
|
-
| `Button` | Run one action. Set its emphasis by how much the action matters. For a small, frequent action shown as an icon alone (
|
|
180
|
+
| `Button` | Run one action. Set its emphasis by how much the action matters. For a small, frequent action shown as an icon alone (the month arrows inside DatePicker, row actions), use a quiet neutral icon-only Button: `<Loomiere.Button emphasis="quiet" palette="neutral" data-size="xs" aria-label="Next month">` with one icon inside. |
|
|
181
181
|
| `Switch` | Turn one setting on or off, taking effect at once. |
|
|
182
182
|
| `Checkbox` | Turn one option on or off inside a form that is submitted later. |
|
|
183
183
|
| `Toggle` | A tool that stays pressed, such as Bold in a toolbar. |
|
|
184
|
-
| `ToggleGroup` | Switch between 2 to 5 short modes or views that apply at once (
|
|
184
|
+
| `ToggleGroup` | Switch between 2 to 5 short modes or views that apply at once (List / Grid). Picking a date or a period is DatePicker, not a toggle. |
|
|
185
185
|
| `Tabs` | Switch between panels of content in the same place. |
|
|
186
186
|
| `Radio` | Choose one of 2 to 6 options in a form, where each option can carry a label and description. |
|
|
187
187
|
| `CheckboxGroup` | Choose any number of a few visible options. |
|
|
188
188
|
| `Select` | Choose one of a fixed list too long to show (about 6 to 15 items). |
|
|
189
189
|
| `Combobox` | Choose one or more from a long list by typing to filter it. |
|
|
190
190
|
| `Autocomplete` | Type free text, with suggestions to speed it up. |
|
|
191
|
-
| `NumberField` | Enter an exact number, with steppers. |
|
|
191
|
+
| `NumberField` | Enter an exact number, with steppers. For an amount of money, use MoneyField. |
|
|
192
|
+
| `MoneyField` | Enter an amount of money in one or more currencies. Use NumberField for plain quantities and percentages. |
|
|
192
193
|
| `Slider` | Set a value in a range where roughly is good enough. |
|
|
193
194
|
| `OTPField` | Enter a one-time code. |
|
|
194
195
|
| `Menu` | Offer commands from a button. Menus run actions; they don't hold a value. |
|
|
@@ -202,11 +203,26 @@ Pick by what the person is doing, not by look:
|
|
|
202
203
|
| `Dialog` | A task that needs full attention before the page goes on. |
|
|
203
204
|
| `AlertDialog` | Confirm a destructive or hard-to-undo action. |
|
|
204
205
|
| `Drawer` | A side task or detail panel that keeps the page in view. |
|
|
206
|
+
| `Splitter` | Let people resize side-by-side or stacked areas, like a sidebar or a documents column. |
|
|
207
|
+
| `ListDetail` | Show the details of one item next to its list, falling back to a drawer or a page on narrow screens. Use Dialog when the detail must block the list. |
|
|
205
208
|
| `Accordion` | Several sections where only some need to be open. |
|
|
206
209
|
| `Collapsible` | One section to show or hide. |
|
|
207
210
|
| `Toast` | Report the result of an action, briefly. |
|
|
211
|
+
| `Badge` | Label a status or a count next to something else. Not clickable; use Button or Toggle for that. |
|
|
212
|
+
| `DatePicker` | Pick a date or a period, with quick selections. Use Input type=date only when you can't load React. Calendar is the grid on its own; DatePresets is the list of quick selections. |
|
|
213
|
+
| `EmptyState` | Show that a list, table or page has nothing in it yet, nothing matches, failed to load, or is all done. Pick the kind; write your own copy. |
|
|
214
|
+
| `DataList` | A list people work through: a review queue, inbox, search results. Default for narrow panes. |
|
|
215
|
+
| `DataTable` | Rows people compare across several columns. Use the plain Table for static tables and reports. |
|
|
216
|
+
| `EditableList` | Repeating form rows people add, edit and remove: line items, allocations. |
|
|
217
|
+
| `CollectionToolbar` | Search, tabs, filters and the selection bar for a DataTable or a DataList. |
|
|
218
|
+
| `CollectionPagination` | Which page of a long list you are on. It also works without a collection. |
|
|
219
|
+
| `EmptyState` | Don't use it for a message about something that just happened (use Toast) or a warning above content that still shows (use a notice or an inline alert). |
|
|
208
220
|
| `Progress` | Show how far a task has got. |
|
|
209
221
|
| `Meter` | Show a measured amount within known limits, such as storage used. |
|
|
210
222
|
|
|
211
|
-
A list of choices that stays on screen inside a panel, one of them selected (
|
|
223
|
+
A date or a period, including the quick selections beside the calendar, is DatePicker. Any other list of choices that stays on screen inside a panel, one of them selected (saved filters, views), has no Base UI part. Make each row a `<button aria-pressed>` drawn from the item concept: `--sl-item-padding-block`, `-padding-inline`, `-radius` and `-gap`, `--sl-item-background-hover` and `-color-hover` on hover, `--sl-item-background-selected` and `-color-selected` with the `-selected` text style when chosen. These are the same rows menus and selects use. When the choice is a form value, use Radio instead.
|
|
224
|
+
|
|
225
|
+
An empty state's title says what is empty in plain words ("No invoices yet"). The description says why, or what to do next, in one sentence. The action is a verb ("Create invoice", "Clear filters"). The first action is the main one: bold when the person is creating the first thing, standard everywhere else, and a secondary action quiet. Error and no-access stay straight: no jokes.
|
|
226
|
+
|
|
227
|
+
Use AG Grid only for spreadsheet work (cell-by-cell editing, ranges, tens of thousands of rows). A screen that is a list people work through uses DataList or DataTable, and the code should say why if it reaches for the grid.
|
|
212
228
|
|
|
@@ -103,6 +103,8 @@
|
|
|
103
103
|
"design-system/components/Autocomplete/preview.html",
|
|
104
104
|
"design-system/components/Avatar/README.md",
|
|
105
105
|
"design-system/components/Avatar/preview.html",
|
|
106
|
+
"design-system/components/Badge/README.md",
|
|
107
|
+
"design-system/components/Badge/preview.html",
|
|
106
108
|
"design-system/components/Button/README.md",
|
|
107
109
|
"design-system/components/Button/preview.html",
|
|
108
110
|
"design-system/components/Checkbox/README.md",
|
|
@@ -111,14 +113,27 @@
|
|
|
111
113
|
"design-system/components/CheckboxGroup/preview.html",
|
|
112
114
|
"design-system/components/Collapsible/README.md",
|
|
113
115
|
"design-system/components/Collapsible/preview.html",
|
|
116
|
+
"design-system/components/Collection/README.md",
|
|
117
|
+
"design-system/components/CollectionPagination/README.md",
|
|
118
|
+
"design-system/components/CollectionToolbar/README.md",
|
|
114
119
|
"design-system/components/Combobox/README.md",
|
|
115
120
|
"design-system/components/Combobox/preview.html",
|
|
116
121
|
"design-system/components/ContextMenu/README.md",
|
|
117
122
|
"design-system/components/ContextMenu/preview.html",
|
|
123
|
+
"design-system/components/DataList/README.md",
|
|
124
|
+
"design-system/components/DataList/preview.html",
|
|
125
|
+
"design-system/components/DataTable/README.md",
|
|
126
|
+
"design-system/components/DataTable/preview.html",
|
|
127
|
+
"design-system/components/DatePicker/README.md",
|
|
128
|
+
"design-system/components/DatePicker/preview.html",
|
|
118
129
|
"design-system/components/Dialog/README.md",
|
|
119
130
|
"design-system/components/Dialog/preview.html",
|
|
120
131
|
"design-system/components/Drawer/README.md",
|
|
121
132
|
"design-system/components/Drawer/preview.html",
|
|
133
|
+
"design-system/components/EditableList/README.md",
|
|
134
|
+
"design-system/components/EditableList/preview.html",
|
|
135
|
+
"design-system/components/EmptyState/README.md",
|
|
136
|
+
"design-system/components/EmptyState/preview.html",
|
|
122
137
|
"design-system/components/Field/README.md",
|
|
123
138
|
"design-system/components/Field/preview.html",
|
|
124
139
|
"design-system/components/Fieldset/README.md",
|
|
@@ -127,12 +142,16 @@
|
|
|
127
142
|
"design-system/components/Form/preview.html",
|
|
128
143
|
"design-system/components/Input/README.md",
|
|
129
144
|
"design-system/components/Input/preview.html",
|
|
145
|
+
"design-system/components/ListDetail/README.md",
|
|
146
|
+
"design-system/components/ListDetail/preview.html",
|
|
130
147
|
"design-system/components/Menu/README.md",
|
|
131
148
|
"design-system/components/Menu/preview.html",
|
|
132
149
|
"design-system/components/Menubar/README.md",
|
|
133
150
|
"design-system/components/Menubar/preview.html",
|
|
134
151
|
"design-system/components/Meter/README.md",
|
|
135
152
|
"design-system/components/Meter/preview.html",
|
|
153
|
+
"design-system/components/MoneyField/README.md",
|
|
154
|
+
"design-system/components/MoneyField/preview.html",
|
|
136
155
|
"design-system/components/NavigationMenu/README.md",
|
|
137
156
|
"design-system/components/NavigationMenu/preview.html",
|
|
138
157
|
"design-system/components/NumberField/README.md",
|
|
@@ -155,6 +174,8 @@
|
|
|
155
174
|
"design-system/components/Separator/preview.html",
|
|
156
175
|
"design-system/components/Slider/README.md",
|
|
157
176
|
"design-system/components/Slider/preview.html",
|
|
177
|
+
"design-system/components/Splitter/README.md",
|
|
178
|
+
"design-system/components/Splitter/preview.html",
|
|
158
179
|
"design-system/components/Switch/README.md",
|
|
159
180
|
"design-system/components/Switch/preview.html",
|
|
160
181
|
"design-system/components/Table/README.md",
|
package/dist/exports/chakra.js
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
* Every palette, plus "accent" and "chrome", works as a colorPalette. Button variants are
|
|
12
12
|
* the brand's emphasis levels (solid = bold, outline = standard, subtle = subtle,
|
|
13
13
|
* ghost = quiet); each keeps its own color unless you pass colorPalette.
|
|
14
|
+
* Badge uses the same levels (solid = bold, outline = standard, subtle and surface = subtle,
|
|
15
|
+
* plain = quiet) and does not change on hover.
|
|
14
16
|
* To add your own config on top: createSystem(config, yours).
|
|
15
17
|
*/
|
|
16
18
|
import { createSystem, defaultConfig, mergeConfigs } from '@chakra-ui/react';
|
|
@@ -350,6 +352,194 @@ const recipes = {
|
|
|
350
352
|
}
|
|
351
353
|
}
|
|
352
354
|
},
|
|
355
|
+
badge: {
|
|
356
|
+
base: {
|
|
357
|
+
colorPalette: "chrome",
|
|
358
|
+
display: "inline-flex",
|
|
359
|
+
alignItems: "center",
|
|
360
|
+
whiteSpace: "nowrap",
|
|
361
|
+
bg: "colorPalette.soft",
|
|
362
|
+
color: "colorPalette.on-soft",
|
|
363
|
+
borderColor: "colorPalette.soft",
|
|
364
|
+
borderWidth: "var(--sl-stroke-default)",
|
|
365
|
+
borderStyle: "solid",
|
|
366
|
+
borderRadius: "var(--sl-radius-pill)",
|
|
367
|
+
height: "var(--sl-badge-height-condense)",
|
|
368
|
+
minH: "var(--sl-badge-height-condense)",
|
|
369
|
+
minW: "var(--sl-badge-height-condense)",
|
|
370
|
+
px: "var(--sl-badge-padding-inline-condense)",
|
|
371
|
+
gap: "var(--sl-badge-gap-condense)",
|
|
372
|
+
fontFamily: "var(--sl-font-trigger-condense-font-family)",
|
|
373
|
+
fontSize: "var(--sl-font-trigger-condense-font-size)",
|
|
374
|
+
fontWeight: "var(--sl-font-trigger-condense-font-weight)",
|
|
375
|
+
lineHeight: "var(--sl-font-trigger-condense-line-height)",
|
|
376
|
+
letterSpacing: "var(--sl-font-trigger-condense-letter-spacing)"
|
|
377
|
+
},
|
|
378
|
+
variants: {
|
|
379
|
+
variant: {
|
|
380
|
+
solid: {
|
|
381
|
+
colorPalette: "accent",
|
|
382
|
+
display: "inline-flex",
|
|
383
|
+
alignItems: "center",
|
|
384
|
+
whiteSpace: "nowrap",
|
|
385
|
+
bg: "colorPalette.solid",
|
|
386
|
+
color: "colorPalette.on-solid",
|
|
387
|
+
borderColor: "colorPalette.solid",
|
|
388
|
+
borderWidth: "var(--sl-stroke-default)",
|
|
389
|
+
borderStyle: "solid",
|
|
390
|
+
borderRadius: "var(--sl-radius-pill)",
|
|
391
|
+
height: "var(--sl-badge-height-condense)",
|
|
392
|
+
minH: "var(--sl-badge-height-condense)",
|
|
393
|
+
minW: "var(--sl-badge-height-condense)",
|
|
394
|
+
px: "var(--sl-badge-padding-inline-condense)",
|
|
395
|
+
gap: "var(--sl-badge-gap-condense)",
|
|
396
|
+
fontFamily: "var(--sl-font-trigger-condense-font-family)",
|
|
397
|
+
fontSize: "var(--sl-font-trigger-condense-font-size)",
|
|
398
|
+
fontWeight: "var(--sl-font-trigger-condense-font-weight)",
|
|
399
|
+
lineHeight: "var(--sl-font-trigger-condense-line-height)",
|
|
400
|
+
letterSpacing: "var(--sl-font-trigger-condense-letter-spacing)"
|
|
401
|
+
},
|
|
402
|
+
subtle: {
|
|
403
|
+
colorPalette: "chrome",
|
|
404
|
+
display: "inline-flex",
|
|
405
|
+
alignItems: "center",
|
|
406
|
+
whiteSpace: "nowrap",
|
|
407
|
+
bg: "colorPalette.soft",
|
|
408
|
+
color: "colorPalette.on-soft",
|
|
409
|
+
borderColor: "colorPalette.soft",
|
|
410
|
+
borderWidth: "var(--sl-stroke-default)",
|
|
411
|
+
borderStyle: "solid",
|
|
412
|
+
borderRadius: "var(--sl-radius-pill)",
|
|
413
|
+
height: "var(--sl-badge-height-condense)",
|
|
414
|
+
minH: "var(--sl-badge-height-condense)",
|
|
415
|
+
minW: "var(--sl-badge-height-condense)",
|
|
416
|
+
px: "var(--sl-badge-padding-inline-condense)",
|
|
417
|
+
gap: "var(--sl-badge-gap-condense)",
|
|
418
|
+
fontFamily: "var(--sl-font-trigger-condense-font-family)",
|
|
419
|
+
fontSize: "var(--sl-font-trigger-condense-font-size)",
|
|
420
|
+
fontWeight: "var(--sl-font-trigger-condense-font-weight)",
|
|
421
|
+
lineHeight: "var(--sl-font-trigger-condense-line-height)",
|
|
422
|
+
letterSpacing: "var(--sl-font-trigger-condense-letter-spacing)"
|
|
423
|
+
},
|
|
424
|
+
surface: {
|
|
425
|
+
colorPalette: "chrome",
|
|
426
|
+
display: "inline-flex",
|
|
427
|
+
alignItems: "center",
|
|
428
|
+
whiteSpace: "nowrap",
|
|
429
|
+
bg: "colorPalette.soft",
|
|
430
|
+
color: "colorPalette.on-soft",
|
|
431
|
+
borderColor: "colorPalette.soft",
|
|
432
|
+
borderWidth: "var(--sl-stroke-default)",
|
|
433
|
+
borderStyle: "solid",
|
|
434
|
+
borderRadius: "var(--sl-radius-pill)",
|
|
435
|
+
height: "var(--sl-badge-height-condense)",
|
|
436
|
+
minH: "var(--sl-badge-height-condense)",
|
|
437
|
+
minW: "var(--sl-badge-height-condense)",
|
|
438
|
+
px: "var(--sl-badge-padding-inline-condense)",
|
|
439
|
+
gap: "var(--sl-badge-gap-condense)",
|
|
440
|
+
fontFamily: "var(--sl-font-trigger-condense-font-family)",
|
|
441
|
+
fontSize: "var(--sl-font-trigger-condense-font-size)",
|
|
442
|
+
fontWeight: "var(--sl-font-trigger-condense-font-weight)",
|
|
443
|
+
lineHeight: "var(--sl-font-trigger-condense-line-height)",
|
|
444
|
+
letterSpacing: "var(--sl-font-trigger-condense-letter-spacing)"
|
|
445
|
+
},
|
|
446
|
+
outline: {
|
|
447
|
+
colorPalette: "accent",
|
|
448
|
+
display: "inline-flex",
|
|
449
|
+
alignItems: "center",
|
|
450
|
+
whiteSpace: "nowrap",
|
|
451
|
+
bg: "transparent",
|
|
452
|
+
color: "colorPalette.fg",
|
|
453
|
+
borderColor: "colorPalette.border",
|
|
454
|
+
borderWidth: "var(--sl-stroke-default)",
|
|
455
|
+
borderStyle: "solid",
|
|
456
|
+
borderRadius: "var(--sl-radius-pill)",
|
|
457
|
+
height: "var(--sl-badge-height-condense)",
|
|
458
|
+
minH: "var(--sl-badge-height-condense)",
|
|
459
|
+
minW: "var(--sl-badge-height-condense)",
|
|
460
|
+
px: "var(--sl-badge-padding-inline-condense)",
|
|
461
|
+
gap: "var(--sl-badge-gap-condense)",
|
|
462
|
+
fontFamily: "var(--sl-font-trigger-condense-font-family)",
|
|
463
|
+
fontSize: "var(--sl-font-trigger-condense-font-size)",
|
|
464
|
+
fontWeight: "var(--sl-font-trigger-condense-font-weight)",
|
|
465
|
+
lineHeight: "var(--sl-font-trigger-condense-line-height)",
|
|
466
|
+
letterSpacing: "var(--sl-font-trigger-condense-letter-spacing)"
|
|
467
|
+
},
|
|
468
|
+
plain: {
|
|
469
|
+
colorPalette: "chrome",
|
|
470
|
+
display: "inline-flex",
|
|
471
|
+
alignItems: "center",
|
|
472
|
+
whiteSpace: "nowrap",
|
|
473
|
+
bg: "transparent",
|
|
474
|
+
color: "colorPalette.fg",
|
|
475
|
+
borderColor: "colorPalette.border",
|
|
476
|
+
borderWidth: "var(--sl-stroke-default)",
|
|
477
|
+
borderStyle: "solid",
|
|
478
|
+
borderRadius: "var(--sl-radius-pill)",
|
|
479
|
+
height: "var(--sl-badge-height-condense)",
|
|
480
|
+
minH: "var(--sl-badge-height-condense)",
|
|
481
|
+
minW: "var(--sl-badge-height-condense)",
|
|
482
|
+
px: "var(--sl-badge-padding-inline-condense)",
|
|
483
|
+
gap: "var(--sl-badge-gap-condense)",
|
|
484
|
+
fontFamily: "var(--sl-font-trigger-condense-font-family)",
|
|
485
|
+
fontSize: "var(--sl-font-trigger-condense-font-size)",
|
|
486
|
+
fontWeight: "var(--sl-font-trigger-condense-font-weight)",
|
|
487
|
+
lineHeight: "var(--sl-font-trigger-condense-line-height)",
|
|
488
|
+
letterSpacing: "var(--sl-font-trigger-condense-letter-spacing)"
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
size: {
|
|
492
|
+
xs: {
|
|
493
|
+
height: "var(--sl-badge-height-minimize)",
|
|
494
|
+
minH: "var(--sl-badge-height-minimize)",
|
|
495
|
+
minW: "var(--sl-badge-height-minimize)",
|
|
496
|
+
px: "var(--sl-badge-padding-inline-minimize)",
|
|
497
|
+
gap: "var(--sl-badge-gap-minimize)",
|
|
498
|
+
fontFamily: "var(--sl-font-trigger-minimize-font-family)",
|
|
499
|
+
fontSize: "var(--sl-font-trigger-minimize-font-size)",
|
|
500
|
+
fontWeight: "var(--sl-font-trigger-minimize-font-weight)",
|
|
501
|
+
lineHeight: "var(--sl-font-trigger-minimize-line-height)",
|
|
502
|
+
letterSpacing: "var(--sl-font-trigger-minimize-letter-spacing)"
|
|
503
|
+
},
|
|
504
|
+
sm: {
|
|
505
|
+
height: "var(--sl-badge-height-condense)",
|
|
506
|
+
minH: "var(--sl-badge-height-condense)",
|
|
507
|
+
minW: "var(--sl-badge-height-condense)",
|
|
508
|
+
px: "var(--sl-badge-padding-inline-condense)",
|
|
509
|
+
gap: "var(--sl-badge-gap-condense)",
|
|
510
|
+
fontFamily: "var(--sl-font-trigger-condense-font-family)",
|
|
511
|
+
fontSize: "var(--sl-font-trigger-condense-font-size)",
|
|
512
|
+
fontWeight: "var(--sl-font-trigger-condense-font-weight)",
|
|
513
|
+
lineHeight: "var(--sl-font-trigger-condense-line-height)",
|
|
514
|
+
letterSpacing: "var(--sl-font-trigger-condense-letter-spacing)"
|
|
515
|
+
},
|
|
516
|
+
md: {
|
|
517
|
+
height: "var(--sl-badge-height-base)",
|
|
518
|
+
minH: "var(--sl-badge-height-base)",
|
|
519
|
+
minW: "var(--sl-badge-height-base)",
|
|
520
|
+
px: "var(--sl-badge-padding-inline-base)",
|
|
521
|
+
gap: "var(--sl-badge-gap-base)",
|
|
522
|
+
fontFamily: "var(--sl-font-trigger-base-font-family)",
|
|
523
|
+
fontSize: "var(--sl-font-trigger-base-font-size)",
|
|
524
|
+
fontWeight: "var(--sl-font-trigger-base-font-weight)",
|
|
525
|
+
lineHeight: "var(--sl-font-trigger-base-line-height)",
|
|
526
|
+
letterSpacing: "var(--sl-font-trigger-base-letter-spacing)"
|
|
527
|
+
},
|
|
528
|
+
lg: {
|
|
529
|
+
height: "var(--sl-badge-height-base)",
|
|
530
|
+
minH: "var(--sl-badge-height-base)",
|
|
531
|
+
minW: "var(--sl-badge-height-base)",
|
|
532
|
+
px: "var(--sl-badge-padding-inline-base)",
|
|
533
|
+
gap: "var(--sl-badge-gap-base)",
|
|
534
|
+
fontFamily: "var(--sl-font-trigger-base-font-family)",
|
|
535
|
+
fontSize: "var(--sl-font-trigger-base-font-size)",
|
|
536
|
+
fontWeight: "var(--sl-font-trigger-base-font-weight)",
|
|
537
|
+
lineHeight: "var(--sl-font-trigger-base-line-height)",
|
|
538
|
+
letterSpacing: "var(--sl-font-trigger-base-letter-spacing)"
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
},
|
|
353
543
|
input: {
|
|
354
544
|
base: {
|
|
355
545
|
boxSizing: "border-box",
|
|
@@ -538,6 +728,149 @@ const recipes = {
|
|
|
538
728
|
};
|
|
539
729
|
|
|
540
730
|
const slotRecipes = {
|
|
731
|
+
emptyState: {
|
|
732
|
+
base: {
|
|
733
|
+
root: {
|
|
734
|
+
width: "100%",
|
|
735
|
+
color: "var(--sl-text-primary)",
|
|
736
|
+
textAlign: "center"
|
|
737
|
+
},
|
|
738
|
+
content: {
|
|
739
|
+
display: "flex",
|
|
740
|
+
alignItems: "center",
|
|
741
|
+
justifyContent: "center"
|
|
742
|
+
},
|
|
743
|
+
indicator: {
|
|
744
|
+
display: "flex",
|
|
745
|
+
alignItems: "center",
|
|
746
|
+
justifyContent: "center"
|
|
747
|
+
},
|
|
748
|
+
title: {
|
|
749
|
+
margin: 0
|
|
750
|
+
},
|
|
751
|
+
description: {
|
|
752
|
+
margin: 0
|
|
753
|
+
}
|
|
754
|
+
},
|
|
755
|
+
variants: {
|
|
756
|
+
size: {
|
|
757
|
+
sm: {
|
|
758
|
+
root: {
|
|
759
|
+
px: "var(--sl-empty-padding-inline-compact)",
|
|
760
|
+
py: "var(--sl-empty-padding-block-compact)"
|
|
761
|
+
},
|
|
762
|
+
content: {
|
|
763
|
+
gap: "var(--sl-empty-gap-compact)",
|
|
764
|
+
flexDirection: "row"
|
|
765
|
+
},
|
|
766
|
+
title: {
|
|
767
|
+
fontFamily: "var(--sl-font-subtitle-condense-font-family)",
|
|
768
|
+
fontSize: "var(--sl-font-subtitle-condense-font-size)",
|
|
769
|
+
fontWeight: "var(--sl-font-subtitle-condense-font-weight)",
|
|
770
|
+
lineHeight: "var(--sl-font-subtitle-condense-line-height)",
|
|
771
|
+
letterSpacing: "var(--sl-font-subtitle-condense-letter-spacing)",
|
|
772
|
+
textStyle: null,
|
|
773
|
+
color: "var(--sl-text-primary)"
|
|
774
|
+
},
|
|
775
|
+
description: {
|
|
776
|
+
fontFamily: "var(--sl-font-body-condense-font-family)",
|
|
777
|
+
fontSize: "var(--sl-font-body-condense-font-size)",
|
|
778
|
+
fontWeight: "var(--sl-font-body-condense-font-weight)",
|
|
779
|
+
lineHeight: "var(--sl-font-body-condense-line-height)",
|
|
780
|
+
letterSpacing: "var(--sl-font-body-condense-letter-spacing)",
|
|
781
|
+
textStyle: null,
|
|
782
|
+
color: "var(--sl-text-secondary)",
|
|
783
|
+
maxWidth: "var(--sl-empty-description-max-width)"
|
|
784
|
+
},
|
|
785
|
+
indicator: {
|
|
786
|
+
width: "auto",
|
|
787
|
+
height: "auto",
|
|
788
|
+
background: "transparent",
|
|
789
|
+
color: "var(--sl-scope-chrome-on-soft)",
|
|
790
|
+
borderRadius: 0,
|
|
791
|
+
fontSize: "var(--sl-icon-size-condense)",
|
|
792
|
+
textStyle: null
|
|
793
|
+
}
|
|
794
|
+
},
|
|
795
|
+
md: {
|
|
796
|
+
root: {
|
|
797
|
+
px: "var(--sl-empty-padding-inline-standard)",
|
|
798
|
+
py: "var(--sl-empty-padding-block-standard)"
|
|
799
|
+
},
|
|
800
|
+
content: {
|
|
801
|
+
gap: "var(--sl-empty-gap-standard)",
|
|
802
|
+
flexDirection: "column"
|
|
803
|
+
},
|
|
804
|
+
title: {
|
|
805
|
+
fontFamily: "var(--sl-font-title-condense-font-family)",
|
|
806
|
+
fontSize: "var(--sl-font-title-condense-font-size)",
|
|
807
|
+
fontWeight: "var(--sl-font-title-condense-font-weight)",
|
|
808
|
+
lineHeight: "var(--sl-font-title-condense-line-height)",
|
|
809
|
+
letterSpacing: "var(--sl-font-title-condense-letter-spacing)",
|
|
810
|
+
textStyle: null,
|
|
811
|
+
color: "var(--sl-text-primary)"
|
|
812
|
+
},
|
|
813
|
+
description: {
|
|
814
|
+
fontFamily: "var(--sl-font-body-base-font-family)",
|
|
815
|
+
fontSize: "var(--sl-font-body-base-font-size)",
|
|
816
|
+
fontWeight: "var(--sl-font-body-base-font-weight)",
|
|
817
|
+
lineHeight: "var(--sl-font-body-base-line-height)",
|
|
818
|
+
letterSpacing: "var(--sl-font-body-base-letter-spacing)",
|
|
819
|
+
textStyle: null,
|
|
820
|
+
color: "var(--sl-text-secondary)",
|
|
821
|
+
maxWidth: "var(--sl-empty-description-max-width)"
|
|
822
|
+
},
|
|
823
|
+
indicator: {
|
|
824
|
+
width: "var(--sl-empty-media-size-standard)",
|
|
825
|
+
height: "var(--sl-empty-media-size-standard)",
|
|
826
|
+
background: "var(--sl-scope-chrome-soft)",
|
|
827
|
+
color: "var(--sl-scope-chrome-on-soft)",
|
|
828
|
+
borderRadius: "var(--sl-radius-pill)",
|
|
829
|
+
fontSize: "var(--sl-icon-size-magnify)",
|
|
830
|
+
textStyle: null
|
|
831
|
+
}
|
|
832
|
+
},
|
|
833
|
+
lg: {
|
|
834
|
+
root: {
|
|
835
|
+
px: "var(--sl-empty-padding-inline-spacious)",
|
|
836
|
+
py: "var(--sl-empty-padding-block-spacious)"
|
|
837
|
+
},
|
|
838
|
+
content: {
|
|
839
|
+
gap: "var(--sl-empty-gap-spacious)",
|
|
840
|
+
flexDirection: "column"
|
|
841
|
+
},
|
|
842
|
+
title: {
|
|
843
|
+
fontFamily: "var(--sl-font-title-magnify-font-family)",
|
|
844
|
+
fontSize: "var(--sl-font-title-magnify-font-size)",
|
|
845
|
+
fontWeight: "var(--sl-font-title-magnify-font-weight)",
|
|
846
|
+
lineHeight: "var(--sl-font-title-magnify-line-height)",
|
|
847
|
+
letterSpacing: "var(--sl-font-title-magnify-letter-spacing)",
|
|
848
|
+
textStyle: null,
|
|
849
|
+
color: "var(--sl-text-primary)"
|
|
850
|
+
},
|
|
851
|
+
description: {
|
|
852
|
+
fontFamily: "var(--sl-font-body-base-font-family)",
|
|
853
|
+
fontSize: "var(--sl-font-body-base-font-size)",
|
|
854
|
+
fontWeight: "var(--sl-font-body-base-font-weight)",
|
|
855
|
+
lineHeight: "var(--sl-font-body-base-line-height)",
|
|
856
|
+
letterSpacing: "var(--sl-font-body-base-letter-spacing)",
|
|
857
|
+
textStyle: null,
|
|
858
|
+
color: "var(--sl-text-secondary)",
|
|
859
|
+
maxWidth: "var(--sl-empty-description-max-width)"
|
|
860
|
+
},
|
|
861
|
+
indicator: {
|
|
862
|
+
width: "var(--sl-empty-media-size-spacious)",
|
|
863
|
+
height: "var(--sl-empty-media-size-spacious)",
|
|
864
|
+
background: "var(--sl-scope-chrome-soft)",
|
|
865
|
+
color: "var(--sl-scope-chrome-on-soft)",
|
|
866
|
+
borderRadius: "var(--sl-radius-pill)",
|
|
867
|
+
fontSize: "var(--sl-icon-size-maximize)",
|
|
868
|
+
textStyle: null
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
},
|
|
541
874
|
field: {
|
|
542
875
|
base: {
|
|
543
876
|
root: {
|
|
@@ -144,7 +144,7 @@ Looks: this brand can look 2 ways. With no `data-look` it is Mojave; `data-look=
|
|
|
144
144
|
|
|
145
145
|
## Components
|
|
146
146
|
|
|
147
|
-
The components are [Base UI](https://base-ui.com) parts styled by class name: `Accordion`, `AlertDialog`, `Autocomplete`, `Avatar`, `Button`, `Checkbox`, `CheckboxGroup`, `Collapsible`, `Combobox`, `ContextMenu`, `Dialog`, `Drawer`, `Field`, `Fieldset`, `Form`, `Input`, `Menu`, `Menubar`, `Meter`, `NavigationMenu`, `NumberField`, `OTPField`, `Popover`, `PreviewCard`, `Progress`, `Radio`, `ScrollArea`, `Select`, `Separator`, `Slider`, `Switch`, `Table`, `Tabs`, `Toast`, `Toggle`, `ToggleGroup`, `Toolbar`, `Tooltip`. Each component's README lists the classes its parts take and the data attributes they answer to (`data-size="sm|lg"`, `data-emphasis`, `data-color`).
|
|
147
|
+
The components are [Base UI](https://base-ui.com) parts styled by class name: `Accordion`, `AlertDialog`, `Autocomplete`, `Avatar`, `Badge`, `Button`, `Checkbox`, `CheckboxGroup`, `Collapsible`, `Collection`, `CollectionPagination`, `CollectionToolbar`, `Combobox`, `ContextMenu`, `DataList`, `DataTable`, `DatePicker`, `Dialog`, `Drawer`, `EditableList`, `EmptyState`, `Field`, `Fieldset`, `Form`, `Input`, `ListDetail`, `Menu`, `Menubar`, `Meter`, `MoneyField`, `NavigationMenu`, `NumberField`, `OTPField`, `Popover`, `PreviewCard`, `Progress`, `Radio`, `ScrollArea`, `Select`, `Separator`, `Slider`, `Splitter`, `Switch`, `Table`, `Tabs`, `Toast`, `Toggle`, `ToggleGroup`, `Toolbar`, `Tooltip`. Each component's README lists the classes its parts take and the data attributes they answer to (`data-size="sm|lg"`, `data-emphasis`, `data-color`).
|
|
148
148
|
|
|
149
149
|
Icons are Material Symbols Outlined by ligature name (`<span class="material-symbols-outlined">search</span>`, or `Loomiere.MaterialSymbol name="search"`), sized by the `.icon-<tier>` utilities to match the text beside them.
|
|
150
150
|
|
|
@@ -158,8 +158,8 @@ Load three things, in this order:
|
|
|
158
158
|
|
|
159
159
|
`window.Loomiere` holds two kinds of component:
|
|
160
160
|
|
|
161
|
-
- **Wrappers** put their own classes on, so use them bare: `Loomiere.Button`, `Loomiere.Input`, `Loomiere.Field`, `Loomiere.Fieldset`, `Loomiere.Form`, `Loomiere.NavigationMenu`, `Loomiere.Select`, `Loomiere.NumberField`, `Loomiere.OTPField`, `Loomiere.Autocomplete`, `Loomiere.Combobox`, `Loomiere.Checkbox`, `Loomiere.Radio`, `Loomiere.CheckboxGroup`, `Loomiere.Toggle`, `Loomiere.ToggleGroup`, `Loomiere.Dialog`, `Loomiere.AlertDialog`, `Loomiere.Meter`, `Loomiere.Progress`, `Loomiere.Slider`, `Loomiere.Menu`, `Loomiere.ContextMenu`, `Loomiere.Menubar`, `Loomiere.Popover`, `Loomiere.PreviewCard`, `Loomiere.Tooltip`, `Loomiere.Drawer`, `Loomiere.Accordion`, `Loomiere.Collapsible`, `Loomiere.Tabs`, `Loomiere.Switch`, `Loomiere.Toast`, `Loomiere.Avatar`, `Loomiere.Toolbar`, `Loomiere.ScrollArea`, `Loomiere.Separator`. `Loomiere.Button` also takes `emphasis` (`bold|standard|subtle|quiet`) and `palette` props, and a Button holding only an icon draws itself square (it sets `data-icon-only`). Wrapped parts that are buttons (`Dialog.Trigger`, `Menu.Trigger`, `Toolbar.Button`, `Drawer.Close`...) take the same `emphasis` and `palette` props and draw square the same way. `Popover.Trigger`, `Tooltip.Trigger`, `Select.Trigger` and `Dialog.Close` become Buttons only when they set `emphasis`, `palette` or `className="Button"`. A plain `.Button` on a bare part is drawn square when it has an `aria-label` and a single icon inside, or when you set `data-icon-only` on it.
|
|
162
|
-
- **Table
|
|
161
|
+
- **Wrappers** put their own classes on, so use them bare: `Loomiere.Button`, `Loomiere.Input`, `Loomiere.Field`, `Loomiere.Fieldset`, `Loomiere.Form`, `Loomiere.NavigationMenu`, `Loomiere.Select`, `Loomiere.NumberField`, `Loomiere.OTPField`, `Loomiere.Autocomplete`, `Loomiere.Combobox`, `Loomiere.Checkbox`, `Loomiere.Radio`, `Loomiere.CheckboxGroup`, `Loomiere.Toggle`, `Loomiere.ToggleGroup`, `Loomiere.Dialog`, `Loomiere.AlertDialog`, `Loomiere.Meter`, `Loomiere.Progress`, `Loomiere.Slider`, `Loomiere.Menu`, `Loomiere.ContextMenu`, `Loomiere.Menubar`, `Loomiere.Popover`, `Loomiere.PreviewCard`, `Loomiere.Tooltip`, `Loomiere.Drawer`, `Loomiere.Accordion`, `Loomiere.Collapsible`, `Loomiere.Tabs`, `Loomiere.Switch`, `Loomiere.Toast`, `Loomiere.Avatar`, `Loomiere.Toolbar`, `Loomiere.ScrollArea`, `Loomiere.Separator`, `Loomiere.Badge`, `Loomiere.DatePicker`, `Loomiere.MoneyField`, `Loomiere.Splitter`, `Loomiere.ListDetail`, `Loomiere.EmptyState`, `Loomiere.DataTable`, `Loomiere.DataList`, `Loomiere.CollectionToolbar`, `Loomiere.CollectionPagination`, `Loomiere.EditableList`. `Loomiere.Button` also takes `emphasis` (`bold|standard|subtle|quiet`) and `palette` props, and a Button holding only an icon draws itself square (it sets `data-icon-only`). Wrapped parts that are buttons (`Dialog.Trigger`, `Menu.Trigger`, `Toolbar.Button`, `Drawer.Close`...) take the same `emphasis` and `palette` props and draw square the same way. `Popover.Trigger`, `Tooltip.Trigger`, `Select.Trigger` and `Dialog.Close` become Buttons only when they set `emphasis`, `palette` or `className="Button"`. A plain `.Button` on a bare part is drawn square when it has an `aria-label` and a single icon inside, or when you set `data-icon-only` on it. `Loomiere.Badge` takes the same `emphasis` and `palette` props, plus `status`, `size` and `dot`.
|
|
162
|
+
- **Table, Badge, DatePicker, MoneyField, Splitter, ListDetail, EmptyState, DataTable, DataList, CollectionToolbar, CollectionPagination and EditableList are Loomiere components**, not Base UI parts. Table is plain HTML for a static table or a report: use the classes in its stylesheet. Badge is `Loomiere.Badge`. DatePicker is `Loomiere.DatePicker`; `Loomiere.Calendar` is the month grid on its own and `Loomiere.DatePresets` is the quick-selection list. MoneyField is `Loomiere.MoneyField`: an amount of money, stored as minor units. Splitter is `Loomiere.Splitter`. ListDetail is `Loomiere.ListDetail`. EmptyState is `Loomiere.EmptyState`. DataTable, DataList, CollectionToolbar and CollectionPagination come from `@scattered-light/loomiere-base-ui/custom/collection` and need `@tanstack/react-table` installed. EditableList comes from the package root or `./custom`.
|
|
163
163
|
|
|
164
164
|
`Loomiere.Base` holds the bare Base UI parts for the wrappers too (`Loomiere.Base.Button`), for when you need the part without its classes.
|
|
165
165
|
|
|
@@ -169,18 +169,19 @@ Pick by what the person is doing, not by look:
|
|
|
169
169
|
|
|
170
170
|
| Component | Use it to |
|
|
171
171
|
|---|---|
|
|
172
|
-
| `Button` | Run one action. Set its emphasis by how much the action matters. For a small, frequent action shown as an icon alone (
|
|
172
|
+
| `Button` | Run one action. Set its emphasis by how much the action matters. For a small, frequent action shown as an icon alone (the month arrows inside DatePicker, row actions), use a quiet neutral icon-only Button: `<Loomiere.Button emphasis="quiet" palette="neutral" data-size="xs" aria-label="Next month">` with one icon inside. |
|
|
173
173
|
| `Switch` | Turn one setting on or off, taking effect at once. |
|
|
174
174
|
| `Checkbox` | Turn one option on or off inside a form that is submitted later. |
|
|
175
175
|
| `Toggle` | A tool that stays pressed, such as Bold in a toolbar. |
|
|
176
|
-
| `ToggleGroup` | Switch between 2 to 5 short modes or views that apply at once (
|
|
176
|
+
| `ToggleGroup` | Switch between 2 to 5 short modes or views that apply at once (List / Grid). Picking a date or a period is DatePicker, not a toggle. |
|
|
177
177
|
| `Tabs` | Switch between panels of content in the same place. |
|
|
178
178
|
| `Radio` | Choose one of 2 to 6 options in a form, where each option can carry a label and description. |
|
|
179
179
|
| `CheckboxGroup` | Choose any number of a few visible options. |
|
|
180
180
|
| `Select` | Choose one of a fixed list too long to show (about 6 to 15 items). |
|
|
181
181
|
| `Combobox` | Choose one or more from a long list by typing to filter it. |
|
|
182
182
|
| `Autocomplete` | Type free text, with suggestions to speed it up. |
|
|
183
|
-
| `NumberField` | Enter an exact number, with steppers. |
|
|
183
|
+
| `NumberField` | Enter an exact number, with steppers. For an amount of money, use MoneyField. |
|
|
184
|
+
| `MoneyField` | Enter an amount of money in one or more currencies. Use NumberField for plain quantities and percentages. |
|
|
184
185
|
| `Slider` | Set a value in a range where roughly is good enough. |
|
|
185
186
|
| `OTPField` | Enter a one-time code. |
|
|
186
187
|
| `Menu` | Offer commands from a button. Menus run actions; they don't hold a value. |
|
|
@@ -194,11 +195,26 @@ Pick by what the person is doing, not by look:
|
|
|
194
195
|
| `Dialog` | A task that needs full attention before the page goes on. |
|
|
195
196
|
| `AlertDialog` | Confirm a destructive or hard-to-undo action. |
|
|
196
197
|
| `Drawer` | A side task or detail panel that keeps the page in view. |
|
|
198
|
+
| `Splitter` | Let people resize side-by-side or stacked areas, like a sidebar or a documents column. |
|
|
199
|
+
| `ListDetail` | Show the details of one item next to its list, falling back to a drawer or a page on narrow screens. Use Dialog when the detail must block the list. |
|
|
197
200
|
| `Accordion` | Several sections where only some need to be open. |
|
|
198
201
|
| `Collapsible` | One section to show or hide. |
|
|
199
202
|
| `Toast` | Report the result of an action, briefly. |
|
|
203
|
+
| `Badge` | Label a status or a count next to something else. Not clickable; use Button or Toggle for that. |
|
|
204
|
+
| `DatePicker` | Pick a date or a period, with quick selections. Use Input type=date only when you can't load React. Calendar is the grid on its own; DatePresets is the list of quick selections. |
|
|
205
|
+
| `EmptyState` | Show that a list, table or page has nothing in it yet, nothing matches, failed to load, or is all done. Pick the kind; write your own copy. |
|
|
206
|
+
| `DataList` | A list people work through: a review queue, inbox, search results. Default for narrow panes. |
|
|
207
|
+
| `DataTable` | Rows people compare across several columns. Use the plain Table for static tables and reports. |
|
|
208
|
+
| `EditableList` | Repeating form rows people add, edit and remove: line items, allocations. |
|
|
209
|
+
| `CollectionToolbar` | Search, tabs, filters and the selection bar for a DataTable or a DataList. |
|
|
210
|
+
| `CollectionPagination` | Which page of a long list you are on. It also works without a collection. |
|
|
211
|
+
| `EmptyState` | Don't use it for a message about something that just happened (use Toast) or a warning above content that still shows (use a notice or an inline alert). |
|
|
200
212
|
| `Progress` | Show how far a task has got. |
|
|
201
213
|
| `Meter` | Show a measured amount within known limits, such as storage used. |
|
|
202
214
|
|
|
203
|
-
A list of choices that stays on screen inside a panel, one of them selected (
|
|
215
|
+
A date or a period, including the quick selections beside the calendar, is DatePicker. Any other list of choices that stays on screen inside a panel, one of them selected (saved filters, views), has no Base UI part. Make each row a `<button aria-pressed>` drawn from the item concept: `--sl-item-padding-block`, `-padding-inline`, `-radius` and `-gap`, `--sl-item-background-hover` and `-color-hover` on hover, `--sl-item-background-selected` and `-color-selected` with the `-selected` text style when chosen. These are the same rows menus and selects use. When the choice is a form value, use Radio instead.
|
|
216
|
+
|
|
217
|
+
An empty state's title says what is empty in plain words ("No invoices yet"). The description says why, or what to do next, in one sentence. The action is a verb ("Create invoice", "Clear filters"). The first action is the main one: bold when the person is creating the first thing, standard everywhere else, and a secondary action quiet. Error and no-access stay straight: no jokes.
|
|
218
|
+
|
|
219
|
+
Use AG Grid only for spreadsheet work (cell-by-cell editing, ranges, tens of thousands of rows). A screen that is a list people work through uses DataList or DataTable, and the code should say why if it reaches for the grid.
|
|
204
220
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Badge
|
|
2
|
+
|
|
3
|
+
Loomiere component, not part of Base UI. A status or count label. Not a Base UI part, and not interactive: no hover or focus. Colors are the emphasis levels (--sl-e-bg, --sl-e-fg, --sl-e-border), so data-emphasis, data-status and data-color all recolor it. The default level is subtle, from DEFAULT_LEVELS. The shape is radius.pill. Sizes are badge.* (tokens/component/badge.json). Text is the trigger style of the same tier (trigger-minimize, trigger-condense, trigger-base): medium weight, and those three tiers already exist. subtitle is bold, which would shout, and label only exists at base. Icons use icon-size of that same tier (a badge icon is a mark beside the label, not a control that fills the line the way a Button icon does). Min width equals the height on every badge, so a single digit is a circle and a wider label is unchanged. Padding stays, so "12" does not touch the pill edges.
|
|
4
|
+
|
|
5
|
+
Use `Loomiere.Badge`, this package's component: it puts the class names on for you (`import { Badge } from '@scattered-light/loomiere-base-ui'`, or from `@scattered-light/loomiere-base-ui/custom`).
|
|
6
|
+
|
|
7
|
+
Not a Base UI part, so there is no base-ui.com page for it.
|
|
8
|
+
|
|
9
|
+
## Classes
|
|
10
|
+
|
|
11
|
+
| Class | Data attributes it answers to |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `Badge` | `data-size`: `minimize`, `base`; `data-dot` |
|
|
14
|
+
|
|
15
|
+
Base UI sets the state attributes (`data-checked`, `data-open`, `data-disabled`...) itself. Set `data-size`, `data-emphasis`, `data-variant` and `data-color` yourself; `data-color` takes any palette name (`primary`, `secondary`, `error`...) and repaints the part in it.
|
|
16
|
+
|
|
17
|
+
## Example
|
|
18
|
+
|
|
19
|
+
From the Badge stories (`Default`):
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
export const Default: Story = {
|
|
23
|
+
render: () => (
|
|
24
|
+
<div style={row}>
|
|
25
|
+
<Badge status="info">Info</Badge>
|
|
26
|
+
<Badge status="success">Success</Badge>
|
|
27
|
+
<Badge status="warning">Warning</Badge>
|
|
28
|
+
<Badge status="error">Error</Badge>
|
|
29
|
+
<Badge>3</Badge>
|
|
30
|
+
</div>
|
|
31
|
+
),
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The preview also shows `Emphasis`, `Statuses`, `Sizes`.
|