@scattered-light/loomiere-mojave 0.7.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/exports/AGENTS.md +8 -5
- package/dist/exports/catalog.json +10 -0
- package/dist/exports/design-system/README.md +8 -5
- package/dist/exports/design-system/components/AppBar/README.md +58 -0
- package/dist/exports/design-system/components/AppBar/preview.html +19 -0
- package/dist/exports/design-system/components/ContextMenu/README.md +1 -1
- package/dist/exports/design-system/components/ContextMenu/preview.html +1 -1
- package/dist/exports/design-system/components/DataList/README.md +1 -1
- package/dist/exports/design-system/components/DataList/preview.html +1 -1
- package/dist/exports/design-system/components/DataTable/README.md +1 -1
- package/dist/exports/design-system/components/DataTable/preview.html +38 -38
- package/dist/exports/design-system/components/DescriptionList/README.md +41 -0
- package/dist/exports/design-system/components/DescriptionList/preview.html +19 -0
- package/dist/exports/design-system/components/Drawer/README.md +1 -1
- package/dist/exports/design-system/components/PickerButton/README.md +56 -0
- package/dist/exports/design-system/components/PickerButton/preview.html +19 -0
- package/dist/exports/design-system/components/ScrollArea/preview.html +2 -2
- package/dist/exports/design-system/components/Sheet/README.md +46 -0
- package/dist/exports/design-system/components/Sheet/preview.html +19 -0
- package/dist/exports/design-system/components/StatFigure/README.md +38 -0
- package/dist/exports/design-system/components/StatFigure/preview.html +19 -0
- package/dist/exports/design-system/components/Table/README.md +2 -2
- package/dist/exports/design-system/components/Table/preview.html +2 -2
- package/dist/exports/design-system/components/ToggleGroup/README.md +2 -2
- package/dist/exports/design-system/components/ToggleGroup/preview.html +1 -1
- package/dist/exports/design-system/components/bundle.css +743 -85
- package/dist/exports/design-system/components/bundle.js +7 -7
- package/dist/exports/design-system/components/index.d.ts +1 -1
- package/dist/exports/design-system/tokens.json +35 -0
- package/dist/exports/figma.json +1 -1
- package/dist/exports/tailwind.css +105 -0
- package/dist/exports/tokens.dtcg.json +383 -26
- package/dist/tokens.css +182 -29
- package/dist/tokens.d.ts +98 -0
- package/dist/tokens.js +99 -1
- package/dist/tokens.json +707 -27
- package/dist/utilities.css +30 -0
- package/package.json +2 -2
package/dist/exports/AGENTS.md
CHANGED
|
@@ -114,8 +114,8 @@ Families: display 'Funnel Display', sans-serif, body 'Barlow Semi Condensed', sa
|
|
|
114
114
|
All text uses one whole text style, never a size or weight on its own: `class="text-style-<name>"`, or the `--sl-font-<name>-*` variables (font-family, font-size, font-weight, line-height, letter-spacing) together. Styles come in tiers named for why the text is that size:
|
|
115
115
|
|
|
116
116
|
- **minimize**: the smallest functional text: captions, fine print, dense metadata. Roles: `body`, `trigger`, `selected`, `link`, `subtitle`, `eyebrow`.
|
|
117
|
-
- **condense**: compact UI: small controls, table cells, secondary labels. Roles: `code`, `body`, `trigger`, `selected`, `link`, `subtitle`, `eyebrow`, `title`.
|
|
118
|
-
- **base**: the default UI and body text. Roles: `body`, `selected`, `label`, `link`, `subtitle`, `trigger`, `title`.
|
|
117
|
+
- **condense**: compact UI: small controls, table cells, secondary labels. Roles: `code`, `figures`, `body`, `trigger`, `selected`, `link`, `subtitle`, `eyebrow`, `caps`, `title`.
|
|
118
|
+
- **base**: the default UI and body text. Roles: `body`, `selected`, `label`, `link`, `subtitle`, `trigger`, `title`, `figures`.
|
|
119
119
|
- **magnify**: emphasized body text: lead paragraphs, larger controls. Roles: `body`, `trigger`, `title`.
|
|
120
120
|
- **amplify**: titles of dialogs, drawers and page sections. Roles: `title`.
|
|
121
121
|
- **maximize**: the page head. Roles: `title`.
|
|
@@ -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`, `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`).
|
|
155
|
+
The components are [Base UI](https://base-ui.com) parts styled by class name: `Accordion`, `AlertDialog`, `AppBar`, `Autocomplete`, `Avatar`, `Badge`, `Button`, `Checkbox`, `CheckboxGroup`, `Collapsible`, `Collection`, `CollectionPagination`, `CollectionToolbar`, `Combobox`, `ContextMenu`, `DataList`, `DataTable`, `DatePicker`, `DescriptionList`, `Dialog`, `Drawer`, `EditableList`, `EmptyState`, `Field`, `Fieldset`, `Form`, `Input`, `ListDetail`, `Menu`, `Menubar`, `Meter`, `MoneyField`, `NavigationMenu`, `NumberField`, `OTPField`, `PickerButton`, `Popover`, `PreviewCard`, `Progress`, `Radio`, `ScrollArea`, `Select`, `Separator`, `Sheet`, `Slider`, `Splitter`, `StatFigure`, `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.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
|
|
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.Sheet`, `Loomiere.StatFigure`, `Loomiere.DescriptionList`, `Loomiere.AppBar`, `Loomiere.PickerButton`. `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, EditableList, Sheet, StatFigure, DescriptionList, AppBar and PickerButton 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, Sheet, StatFigure, DescriptionList (with `Loomiere.DescriptionItem`), AppBar (with `Loomiere.AppBarSpacer`) and PickerButton come 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
|
|
|
@@ -216,6 +216,9 @@ Pick by what the person is doing, not by look:
|
|
|
216
216
|
| `EditableList` | Repeating form rows people add, edit and remove: line items, allocations. |
|
|
217
217
|
| `CollectionToolbar` | Search, tabs, filters and the selection bar for a DataTable or a DataList. |
|
|
218
218
|
| `CollectionPagination` | Which page of a long list you are on. It also works without a collection. |
|
|
219
|
+
| `Sheet` | Frame a section of a working page (open items, a profile, periods) with a ruled top and an optional tab label. A table or list inside runs edge to edge. |
|
|
220
|
+
| `StatFigure` | Lead a page with one figure that matters (a balance, a count to act on), with a caps label and a caption. Give a final total the double underline. |
|
|
221
|
+
| `DescriptionList` | Show label and value pairs, such as a profile. variant="leader" runs dotted leaders to values at the end of the row, as on a working paper. |
|
|
219
222
|
| `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). |
|
|
220
223
|
| `Progress` | Show how far a task has got. |
|
|
221
224
|
| `Meter` | Show a measured amount within known limits, such as storage used. |
|
|
@@ -99,6 +99,8 @@
|
|
|
99
99
|
"design-system/components/Accordion/preview.html",
|
|
100
100
|
"design-system/components/AlertDialog/README.md",
|
|
101
101
|
"design-system/components/AlertDialog/preview.html",
|
|
102
|
+
"design-system/components/AppBar/README.md",
|
|
103
|
+
"design-system/components/AppBar/preview.html",
|
|
102
104
|
"design-system/components/Autocomplete/README.md",
|
|
103
105
|
"design-system/components/Autocomplete/preview.html",
|
|
104
106
|
"design-system/components/Avatar/README.md",
|
|
@@ -126,6 +128,8 @@
|
|
|
126
128
|
"design-system/components/DataTable/preview.html",
|
|
127
129
|
"design-system/components/DatePicker/README.md",
|
|
128
130
|
"design-system/components/DatePicker/preview.html",
|
|
131
|
+
"design-system/components/DescriptionList/README.md",
|
|
132
|
+
"design-system/components/DescriptionList/preview.html",
|
|
129
133
|
"design-system/components/Dialog/README.md",
|
|
130
134
|
"design-system/components/Dialog/preview.html",
|
|
131
135
|
"design-system/components/Drawer/README.md",
|
|
@@ -158,6 +162,8 @@
|
|
|
158
162
|
"design-system/components/NumberField/preview.html",
|
|
159
163
|
"design-system/components/OTPField/README.md",
|
|
160
164
|
"design-system/components/OTPField/preview.html",
|
|
165
|
+
"design-system/components/PickerButton/README.md",
|
|
166
|
+
"design-system/components/PickerButton/preview.html",
|
|
161
167
|
"design-system/components/Popover/README.md",
|
|
162
168
|
"design-system/components/Popover/preview.html",
|
|
163
169
|
"design-system/components/PreviewCard/README.md",
|
|
@@ -172,10 +178,14 @@
|
|
|
172
178
|
"design-system/components/Select/preview.html",
|
|
173
179
|
"design-system/components/Separator/README.md",
|
|
174
180
|
"design-system/components/Separator/preview.html",
|
|
181
|
+
"design-system/components/Sheet/README.md",
|
|
182
|
+
"design-system/components/Sheet/preview.html",
|
|
175
183
|
"design-system/components/Slider/README.md",
|
|
176
184
|
"design-system/components/Slider/preview.html",
|
|
177
185
|
"design-system/components/Splitter/README.md",
|
|
178
186
|
"design-system/components/Splitter/preview.html",
|
|
187
|
+
"design-system/components/StatFigure/README.md",
|
|
188
|
+
"design-system/components/StatFigure/preview.html",
|
|
179
189
|
"design-system/components/Switch/README.md",
|
|
180
190
|
"design-system/components/Switch/preview.html",
|
|
181
191
|
"design-system/components/Table/README.md",
|
|
@@ -106,8 +106,8 @@ Families: display 'Funnel Display', sans-serif, body 'Barlow Semi Condensed', sa
|
|
|
106
106
|
All text uses one whole text style, never a size or weight on its own: `class="text-style-<name>"`, or the `--sl-font-<name>-*` variables (font-family, font-size, font-weight, line-height, letter-spacing) together. Styles come in tiers named for why the text is that size:
|
|
107
107
|
|
|
108
108
|
- **minimize**: the smallest functional text: captions, fine print, dense metadata. Roles: `body`, `trigger`, `selected`, `link`, `subtitle`, `eyebrow`.
|
|
109
|
-
- **condense**: compact UI: small controls, table cells, secondary labels. Roles: `code`, `body`, `trigger`, `selected`, `link`, `subtitle`, `eyebrow`, `title`.
|
|
110
|
-
- **base**: the default UI and body text. Roles: `body`, `selected`, `label`, `link`, `subtitle`, `trigger`, `title`.
|
|
109
|
+
- **condense**: compact UI: small controls, table cells, secondary labels. Roles: `code`, `figures`, `body`, `trigger`, `selected`, `link`, `subtitle`, `eyebrow`, `caps`, `title`.
|
|
110
|
+
- **base**: the default UI and body text. Roles: `body`, `selected`, `label`, `link`, `subtitle`, `trigger`, `title`, `figures`.
|
|
111
111
|
- **magnify**: emphasized body text: lead paragraphs, larger controls. Roles: `body`, `trigger`, `title`.
|
|
112
112
|
- **amplify**: titles of dialogs, drawers and page sections. Roles: `title`.
|
|
113
113
|
- **maximize**: the page head. Roles: `title`.
|
|
@@ -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`, `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`).
|
|
147
|
+
The components are [Base UI](https://base-ui.com) parts styled by class name: `Accordion`, `AlertDialog`, `AppBar`, `Autocomplete`, `Avatar`, `Badge`, `Button`, `Checkbox`, `CheckboxGroup`, `Collapsible`, `Collection`, `CollectionPagination`, `CollectionToolbar`, `Combobox`, `ContextMenu`, `DataList`, `DataTable`, `DatePicker`, `DescriptionList`, `Dialog`, `Drawer`, `EditableList`, `EmptyState`, `Field`, `Fieldset`, `Form`, `Input`, `ListDetail`, `Menu`, `Menubar`, `Meter`, `MoneyField`, `NavigationMenu`, `NumberField`, `OTPField`, `PickerButton`, `Popover`, `PreviewCard`, `Progress`, `Radio`, `ScrollArea`, `Select`, `Separator`, `Sheet`, `Slider`, `Splitter`, `StatFigure`, `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.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
|
|
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.Sheet`, `Loomiere.StatFigure`, `Loomiere.DescriptionList`, `Loomiere.AppBar`, `Loomiere.PickerButton`. `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, EditableList, Sheet, StatFigure, DescriptionList, AppBar and PickerButton 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, Sheet, StatFigure, DescriptionList (with `Loomiere.DescriptionItem`), AppBar (with `Loomiere.AppBarSpacer`) and PickerButton come 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
|
|
|
@@ -208,6 +208,9 @@ Pick by what the person is doing, not by look:
|
|
|
208
208
|
| `EditableList` | Repeating form rows people add, edit and remove: line items, allocations. |
|
|
209
209
|
| `CollectionToolbar` | Search, tabs, filters and the selection bar for a DataTable or a DataList. |
|
|
210
210
|
| `CollectionPagination` | Which page of a long list you are on. It also works without a collection. |
|
|
211
|
+
| `Sheet` | Frame a section of a working page (open items, a profile, periods) with a ruled top and an optional tab label. A table or list inside runs edge to edge. |
|
|
212
|
+
| `StatFigure` | Lead a page with one figure that matters (a balance, a count to act on), with a caps label and a caption. Give a final total the double underline. |
|
|
213
|
+
| `DescriptionList` | Show label and value pairs, such as a profile. variant="leader" runs dotted leaders to values at the end of the row, as on a working paper. |
|
|
211
214
|
| `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). |
|
|
212
215
|
| `Progress` | Show how far a task has got. |
|
|
213
216
|
| `Meter` | Show a measured amount within known limits, such as storage used. |
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# AppBar
|
|
2
|
+
|
|
3
|
+
Loomiere component, not part of Base UI. The bar across the top of an app window, one row on a line in the rule color. The line is app-bar.border-width while rule.width is 0, and the thicker of the two once a brand turns the rule on, so an ink-rule brand gets the working-paper rule under its app bar. AppBarSpacer pushes what follows it to the end. A vertical Separator inside is a short divider between groups of icon actions. Tokens: app-bar.* (tokens/component/app-bar.json).
|
|
4
|
+
|
|
5
|
+
Use `Loomiere.AppBar`, this package's component: it puts the class names on for you (`import { AppBar } 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
|
+
| `AppBar` | |
|
|
14
|
+
| `AppBarSpacer` | |
|
|
15
|
+
| `Separator` | `data-orientation`: `vertical` |
|
|
16
|
+
|
|
17
|
+
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.
|
|
18
|
+
|
|
19
|
+
## Example
|
|
20
|
+
|
|
21
|
+
From the AppBar stories (`Default`):
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
export const Default: Story = {
|
|
25
|
+
render: function Render() {
|
|
26
|
+
const [module, setModule] = React.useState('accounting');
|
|
27
|
+
return (
|
|
28
|
+
<AppBar>
|
|
29
|
+
<strong style={{ fontSize: '1.5rem', fontWeight: 700 }}>Ledgerly</strong>
|
|
30
|
+
<Button emphasis="quiet">My Clients</Button>
|
|
31
|
+
<PickerButton label="Client" value="Alpha Services" />
|
|
32
|
+
<PickerButton label="Entity" value="North Company" />
|
|
33
|
+
<AppBarSpacer />
|
|
34
|
+
<ToggleGroup
|
|
35
|
+
data-variant="segmented"
|
|
36
|
+
aria-label="Modules"
|
|
37
|
+
value={[module]}
|
|
38
|
+
onValueChange={(next) => next[0] && setModule(next[0])}
|
|
39
|
+
>
|
|
40
|
+
<Toggle value="accounting">Accounting</Toggle>
|
|
41
|
+
<Toggle value="tax">Tax</Toggle>
|
|
42
|
+
</ToggleGroup>
|
|
43
|
+
<Button emphasis="quiet" aria-label="Documents">
|
|
44
|
+
<DocumentIcon />
|
|
45
|
+
</Button>
|
|
46
|
+
<Separator orientation="vertical" />
|
|
47
|
+
<Button emphasis="quiet" aria-label="More">
|
|
48
|
+
<MoreIcon />
|
|
49
|
+
</Button>
|
|
50
|
+
</AppBar>
|
|
51
|
+
);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** Only a wordmark and actions, as on a home screen with no context chosen. */
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The preview also shows `Minimal`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- @dsCard group="Layout" height=240 subtitle="Default / Minimal" -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<style>
|
|
7
|
+
body { margin: 0; padding: var(--sl-space-4, 16px); background: var(--sl-surface-canvas); color: var(--sl-text-primary); }
|
|
8
|
+
#root { display: grid; gap: var(--sl-space-5, 20px); }
|
|
9
|
+
.ds-story-name { margin: 0 0 var(--sl-space-2, 8px); font: var(--sl-font-label-minimize-font, 500 10px sans-serif); color: var(--sl-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; }
|
|
10
|
+
</style>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
<script>
|
|
15
|
+
(()=>{var S=Object.create;var l=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var E=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var p=(t,r)=>()=>(r||t((r={exports:{}}).exports,r),r.exports),R=(t,r)=>{for(var a in r)l(t,a,{get:r[a],enumerable:!0})},C=(t,r,a,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of M(r))!A.call(t,n)&&n!==a&&l(t,n,{get:()=>r[n],enumerable:!(s=b(r,n))||s.enumerable});return t};var d=(t,r,a)=>(a=t!=null?S(E(t)):{},C(r||!t||!t.__esModule?l(a,"default",{value:t,enumerable:!0}):a,t));var y=p((N,g)=>{g.exports=window.React});var f=p((F,h)=>{h.exports=window.Loomiere});var u={};R(u,{Default:()=>T,Minimal:()=>k,default:()=>m});var v=d(y(),1),o=d(f(),1);var i=window.React;function e(t,r,a){let{children:s,...n}=r||{};return a!==void 0&&(n.key=a),s===void 0?i.createElement(t,n):Array.isArray(s)?i.createElement(t,n,...s):i.createElement(t,n,s)}var I=i.Fragment;var D={title:"Components/Lib/AppBar",component:o.AppBar,parameters:{layout:"fullscreen"},tags:["autodocs","ds:lib"]},m=D,x=()=>e("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8","aria-hidden":"true",children:[e("path",{d:"M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"}),e("path",{d:"M14 3v5h5"})]}),B=()=>e("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true",children:[e("circle",{cx:"5",cy:"12",r:"1.8"}),e("circle",{cx:"12",cy:"12",r:"1.8"}),e("circle",{cx:"19",cy:"12",r:"1.8"})]}),T={render:function(){let[r,a]=v.useState("accounting");return e(o.AppBar,{children:[e("strong",{style:{fontSize:"1.5rem",fontWeight:700},children:"Ledgerly"}),e(o.Button,{emphasis:"quiet",children:"My Clients"}),e(o.PickerButton,{label:"Client",value:"Alpha Services"}),e(o.PickerButton,{label:"Entity",value:"North Company"}),e(o.AppBarSpacer,{}),e(o.ToggleGroup,{"data-variant":"segmented","aria-label":"Modules",value:[r],onValueChange:s=>s[0]&&a(s[0]),children:[e(o.Toggle,{value:"accounting",children:"Accounting"}),e(o.Toggle,{value:"tax",children:"Tax"})]}),e(o.Button,{emphasis:"quiet","aria-label":"Documents",children:e(x,{})}),e(o.Separator,{orientation:"vertical"}),e(o.Button,{emphasis:"quiet","aria-label":"More",children:e(B,{})})]})}},k={render:()=>e(o.AppBar,{children:[e("strong",{style:{fontSize:"1.5rem",fontWeight:700},children:"Ledgerly"}),e(o.AppBarSpacer,{}),e(o.Button,{emphasis:"quiet","aria-label":"Documents",children:e(x,{})}),e(o.Separator,{orientation:"vertical"}),e(o.Button,{emphasis:"quiet","aria-label":"More",children:e(B,{})})]})};var c=window.React,w=m||{},q=["Default","Minimal"];function j({id:t}){let r=u[t],a={...w.args||{},...r.args||{}};return(r.render||(n=>c.createElement(w.component,n)))(a,{args:a,id:t,name:t})}var z=q.map(t=>c.createElement("section",{key:t,className:"ds-story"},c.createElement("p",{className:"ds-story-name"},t.replace(/([a-z])([A-Z])/g,"$1 $2")),c.createElement("div",{className:"ds-story-body"},c.createElement(j,{id:t}))));window.ReactDOM.createRoot(document.getElementById("root")).render(c.createElement(c.Fragment,null,z));})();
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -44,7 +44,7 @@ export const Default: Story = {
|
|
|
44
44
|
alignItems: 'center',
|
|
45
45
|
justifyContent: 'center',
|
|
46
46
|
border: '2px dashed var(--sl-border-strong)',
|
|
47
|
-
borderRadius: '
|
|
47
|
+
borderRadius: 'var(--sl-radius-surface)',
|
|
48
48
|
background: 'var(--sl-surface-overlay)',
|
|
49
49
|
cursor: 'context-menu'
|
|
50
50
|
}}>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<body>
|
|
13
13
|
<div id="root"></div>
|
|
14
14
|
<script>
|
|
15
|
-
(()=>{var R=Object.create;var d=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var f=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var x=(o,n)=>()=>(n||o((n={exports:{}}).exports,n),n.exports),S=(o,n)=>{for(var a in n)d(o,a,{get:n[a],enumerable:!0})},v=(o,n,a,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of k(n))!P.call(o,r)&&r!==a&&d(o,r,{get:()=>n[r],enumerable:!(s=y(n,r))||s.enumerable});return o};var
|
|
15
|
+
(()=>{var R=Object.create;var d=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var f=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var x=(o,n)=>()=>(n||o((n={exports:{}}).exports,n),n.exports),S=(o,n)=>{for(var a in n)d(o,a,{get:n[a],enumerable:!0})},v=(o,n,a,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of k(n))!P.call(o,r)&&r!==a&&d(o,r,{get:()=>n[r],enumerable:!(s=y(n,r))||s.enumerable});return o};var C=(o,n,a)=>(a=o!=null?R(f(o)):{},v(n||!o||!o.__esModule?d(a,"default",{value:o,enumerable:!0}):a,o));var I=x((W,p)=>{p.exports=window.React});var b=x((V,h)=>{h.exports=window.Loomiere});var l={};S(l,{Default:()=>N,WithCheckboxes:()=>T,WithDisabledItems:()=>_,WithRadioGroup:()=>E,WithSubmenu:()=>L,default:()=>m});var c=C(I(),1),t=C(b(),1);var u=window.React;function e(o,n,a){let{children:s,...r}=n||{};return a!==void 0&&(r.key=a),s===void 0?u.createElement(o,r):Array.isArray(s)?u.createElement(o,r,...s):u.createElement(o,r,s)}var A=u.Fragment;var w={title:"Components/Lib/ContextMenu",component:t.ContextMenu.Root,parameters:{layout:"centered"},tags:["autodocs","ds:lib"]},m=w,N={render:()=>e(t.ContextMenu.Root,{children:[e(t.ContextMenu.Trigger,{children:e("div",{style:{width:"300px",height:"200px",display:"flex",alignItems:"center",justifyContent:"center",border:"2px dashed var(--sl-border-strong)",borderRadius:"var(--sl-radius-surface)",background:"var(--sl-surface-overlay)",cursor:"context-menu"},children:"Right-click here"})}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{children:e(t.ContextMenu.Popup,{children:[e(t.ContextMenu.Item,{children:"Copy"}),e(t.ContextMenu.Item,{children:"Cut"}),e(t.ContextMenu.Item,{children:"Paste"}),e(t.ContextMenu.Separator,{}),e(t.ContextMenu.Item,{children:"Delete"})]})})})]})},T={render:()=>{let[o,n]=c.useState(!1),[a,s]=c.useState(!0),[r,g]=c.useState(!1);return e(t.ContextMenu.Root,{children:[e(t.ContextMenu.Trigger,{children:e("div",{style:{width:"300px",height:"200px",display:"flex",alignItems:"center",justifyContent:"center",border:"2px dashed var(--sl-border-strong)",borderRadius:"var(--sl-radius-surface)",background:"var(--sl-surface-overlay)",cursor:"context-menu"},children:"Right-click for view options"})}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{children:e(t.ContextMenu.Popup,{children:[e(t.ContextMenu.CheckboxItem,{checked:o,onCheckedChange:n,children:[e(t.ContextMenu.CheckboxItemIndicator,{children:e("span",{className:"material-symbols-outlined ContextMenuCheckboxItemIndicatorIcon",children:"check"})}),"Show toolbar"]}),e(t.ContextMenu.CheckboxItem,{checked:a,onCheckedChange:s,children:[e(t.ContextMenu.CheckboxItemIndicator,{children:e("span",{className:"material-symbols-outlined ContextMenuCheckboxItemIndicatorIcon",children:"check"})}),"Show sidebar"]}),e(t.ContextMenu.CheckboxItem,{checked:r,onCheckedChange:g,children:[e(t.ContextMenu.CheckboxItemIndicator,{children:e("span",{className:"material-symbols-outlined ContextMenuCheckboxItemIndicatorIcon",children:"check"})}),"Show footer"]})]})})})]})}},E={render:()=>{let[o,n]=c.useState("light");return e(t.ContextMenu.Root,{children:[e(t.ContextMenu.Trigger,{children:e("div",{style:{width:"300px",height:"200px",display:"flex",alignItems:"center",justifyContent:"center",border:"2px dashed var(--sl-border-strong)",borderRadius:"var(--sl-radius-surface)",background:"var(--sl-surface-overlay)",cursor:"context-menu"},children:"Right-click to change theme"})}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{children:e(t.ContextMenu.Popup,{children:e(t.ContextMenu.Group,{children:[e(t.ContextMenu.GroupLabel,{children:"Theme"}),e(t.ContextMenu.RadioGroup,{value:o,onValueChange:n,children:[e(t.ContextMenu.RadioItem,{value:"light",children:[e(t.ContextMenu.RadioItemIndicator,{children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",style:{fontVariationSettings:'"FILL" 1'},children:"radio_button_checked"})}),e("span",{className:"ContextMenuRadioItemIndicator","data-unchecked":!0,children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",children:"radio_button_unchecked"})}),"Light"]}),e(t.ContextMenu.RadioItem,{value:"dark",children:[e(t.ContextMenu.RadioItemIndicator,{children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",style:{fontVariationSettings:'"FILL" 1'},children:"radio_button_checked"})}),e("span",{className:"ContextMenuRadioItemIndicator","data-unchecked":!0,children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",children:"radio_button_unchecked"})}),"Dark"]}),e(t.ContextMenu.RadioItem,{value:"system",children:[e(t.ContextMenu.RadioItemIndicator,{children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",style:{fontVariationSettings:'"FILL" 1'},children:"radio_button_checked"})}),e("span",{className:"ContextMenuRadioItemIndicator","data-unchecked":!0,children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",children:"radio_button_unchecked"})}),"System"]})]})]})})})})]})}},L={render:()=>e(t.ContextMenu.Root,{children:[e(t.ContextMenu.Trigger,{children:e("div",{style:{width:"300px",height:"200px",display:"flex",alignItems:"center",justifyContent:"center",border:"2px dashed var(--sl-border-strong)",borderRadius:"var(--sl-radius-surface)",background:"var(--sl-surface-overlay)",cursor:"context-menu"},children:"Right-click for nested menu"})}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{children:e(t.ContextMenu.Popup,{children:[e(t.ContextMenu.Item,{children:"New File"}),e(t.ContextMenu.Item,{children:"New Folder"}),e(t.ContextMenu.Separator,{}),e(t.ContextMenu.SubmenuRoot,{children:[e(t.ContextMenu.SubmenuTrigger,{children:"Share"}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{children:e(t.ContextMenu.Popup,{children:[e(t.ContextMenu.Item,{children:"Email"}),e(t.ContextMenu.Item,{children:"Copy Link"}),e(t.ContextMenu.Item,{children:"Social Media"})]})})})]})]})})})]})},_={render:()=>e(t.ContextMenu.Root,{children:[e(t.ContextMenu.Trigger,{children:e("div",{style:{width:"300px",height:"200px",display:"flex",alignItems:"center",justifyContent:"center",border:"2px dashed var(--sl-border-strong)",borderRadius:"var(--sl-radius-surface)",background:"var(--sl-surface-overlay)",cursor:"context-menu"},children:"Right-click here"})}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{children:e(t.ContextMenu.Popup,{children:[e(t.ContextMenu.Item,{children:"Copy"}),e(t.ContextMenu.Item,{disabled:!0,children:"Cut (disabled)"}),e(t.ContextMenu.Item,{disabled:!0,children:"Paste (disabled)"}),e(t.ContextMenu.Separator,{}),e(t.ContextMenu.Item,{children:"Delete"})]})})})]})};var i=window.React,M=m||{},F=["Default","WithCheckboxes","WithRadioGroup","WithSubmenu"];function j({id:o}){let n=l[o],a={...M.args||{},...n.args||{}};return(n.render||(r=>i.createElement(M.component,r)))(a,{args:a,id:o,name:o})}var D=F.map(o=>i.createElement("section",{key:o,className:"ds-story"},i.createElement("p",{className:"ds-story-name"},o.replace(/([a-z])([A-Z])/g,"$1 $2")),i.createElement("div",{className:"ds-story-body"},i.createElement(j,{id:o}))));window.ReactDOM.createRoot(document.getElementById("root")).render(i.createElement(i.Fragment,null,D));})();
|
|
16
16
|
|
|
17
17
|
</script>
|
|
18
18
|
</body>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# DataList
|
|
2
2
|
|
|
3
|
-
Loomiere component, not part of Base UI. The same rows as the table, in one container with the table's borders, hover, selected and current states. Not a stack of floating cards: the two views should read as one family. variant=cards adds the surface radius and a gap when a queue should read as separate items.
|
|
3
|
+
Loomiere component, not part of Base UI. The same rows as the table, in one container with the table's borders, hover, selected and current states. Not a stack of floating cards: the two views should read as one family. variant=cards adds the surface radius and a gap when a queue should read as separate items. The working-paper rule (rule.width, 0 by default) replaces the top border with a heavier line in rule.color: on the first row, or on each card's top edge.
|
|
4
4
|
|
|
5
5
|
Use `Loomiere.DataList` from `@scattered-light/loomiere-base-ui/custom/collection`. Install `@tanstack/react-table` (peer, optional). It is not on the main entry, so an app that only imports Badge does not need it.
|
|
6
6
|
|
|
@@ -468,7 +468,7 @@ Unable to find an `+(n===!1?"accessible ":"")+'element with the role "'+t+'"'+l+
|
|
|
468
468
|
`)),i+=d+n[l+1]}),i}var H9=U9,_c=xa({...zE},{intercept:(e,t)=>t[0]==="fireEvent"||e.startsWith("find")||e.startsWith("waitFor")});_c.screen=new Proxy(_c.screen,{get(e,t,r){return we.warn(H9`
|
|
469
469
|
You are using Testing Library's \`screen\` object. Use \`within(canvasElement)\` instead.
|
|
470
470
|
More info: https://storybook.js.org/docs/essentials/interactions
|
|
471
|
-
`),Reflect.get(e,t,r)}});var{buildQueries:lV,configure:uV,createEvent:cV,fireEvent:dV,findAllByAltText:pV,findAllByDisplayValue:fV,findAllByLabelText:mV,findAllByPlaceholderText:hV,findAllByRole:yV,findAllByTestId:bV,findAllByText:gV,findAllByTitle:vV,findByAltText:EV,findByDisplayValue:_V,findByLabelText:RV,findByPlaceholderText:wV,findByRole:CV,findByTestId:SV,findByText:AV,findByTitle:TV,getAllByAltText:PV,getAllByDisplayValue:OV,getAllByLabelText:qV,getAllByPlaceholderText:xV,getAllByRole:MV,getAllByTestId:NV,getAllByText:jV,getAllByTitle:IV,getByAltText:DV,getByDisplayValue:FV,getByLabelText:LV,getByPlaceholderText:BV,getByRole:kV,getByTestId:$V,getByText:UV,getByTitle:HV,getConfig:VV,getDefaultNormalizer:zV,getElementError:GV,getNodeText:YV,getQueriesForElement:WV,getRoles:KV,getSuggestedQuery:XV,isInaccessible:JV,logDOM:QV,logRoles:ZV,prettyDOM:e8,queries:t8,queryAllByAltText:r8,queryAllByAttribute:n8,queryAllByDisplayValue:o8,queryAllByLabelText:a8,queryAllByPlaceholderText:i8,queryAllByRole:s8,queryAllByTestId:l8,queryAllByText:u8,queryAllByTitle:c8,queryByAltText:d8,queryByAttribute:p8,queryByDisplayValue:f8,queryByLabelText:m8,queryByPlaceholderText:h8,queryByRole:y8,queryByTestId:b8,queryByText:g8,queryByTitle:v8,queryHelpers:E8,screen:_8,waitFor:R8,waitForElementToBeRemoved:w8,within:tn,prettyFormat:C8}=_c,{userEvent:or}=xa({userEvent:$9},{intercept:!0}),{expect:Et}=xa({expect:VE},{getKeys:(e,t)=>{let r=["assert","__methods","__flags","_obj"];if(e.constructor===x){let n=Object.keys(Object.getPrototypeOf(e)).filter(o=>!r.includes(o));return t>2?n:[...n,"not"]}return Object.keys(e)},intercept:e=>e!=="expect"}),V9=({parameters:e})=>{e?.test?.mockReset===!0?y5():e?.test?.clearMocks===!0?h5():e?.test?.restoreMocks!==!1&&b5()},Rc=(e,t=0,r)=>{if(t>5||e==null)return e;if(jE(e))return r&&e.mockName(r),e;if(typeof e=="function"&&"isAction"in e&&e.isAction&&!("implicit"in e&&e.implicit)){let n=f5(e);return r&&n.mockName(r),n}if(Array.isArray(e)){t++;for(let n=0;n<e.length;n++)e[n]=Rc(e[n],t)}if(typeof e=="object"&&e.constructor===Object){t++;for(let[n,o]of Object.entries(e))Object.getOwnPropertyDescriptor(e,n)?.writable&&(e[n]=Rc(o,t,n));return e}return e},z9=({initialArgs:e})=>{Rc(e)},G9=e=>{globalThis.HTMLElement&&e.canvasElement instanceof globalThis.HTMLElement&&(e.canvas=tn(e.canvasElement))};Ie.__STORYBOOK_TEST_LOADERS__=[V9,z9,G9];Ie.__STORYBOOK_TEST_ON_MOCK_CALL__=p5;var Bt=on(Gd(),1);var Wd=on(gs(),1),Jo=on(Gd(),1),st=on(Yd(),1);var Ui=window.React;function re(e,t,r){let{children:n,...o}=t||{};return r!==void 0&&(o.key=r),n===void 0?Ui.createElement(e,o):Array.isArray(n)?Ui.createElement(e,o,...n):Ui.createElement(e,o,n)}var Tz=Ui.Fragment;var Q1=["Joshua Tree","Mojave Preserve","Death Valley","Joshua Tree"],Z1=["Chase","Visitor fee","Camp store","Unassigned"],qt=Array.from({length:40},(e,t)=>({id:`fee-${t+1}`,date:`2026-10-${String(t%27+1).padStart(2,"0")}`,party:Z1[t%Z1.length]??"Chase",memo:t%5===0?"entrance fee":"reservation",park:Q1[t%Q1.length]??"Joshua Tree",amount:t%7===0?"-12.00":(8+t%9+t/100).toFixed(2),status:t%3===0?"posted":"for_review"})),eR=(0,st.defineColumns)([{id:"date",header:"Date",value:e=>e.date,kind:"date",sortable:!0,width:"min"},{id:"party",header:"Party / description",value:e=>e.party,searchable:e=>[e.memo,e.id],rowHeader:!0,sortable:!0},{id:"park",header:"Park",value:e=>e.park,searchable:!0,filter:{kind:"multi-select",label:"Park"}},{id:"amount",header:"Amount",value:e=>e.amount,kind:"money",currency:"USD",negative:"parens",sortable:!0,total:"sum",width:"min"},{id:"status",header:"Status",value:e=>e.status,filter:{kind:"tabs",options:[{value:"",label:"All",all:!0},{value:"for_review",label:"For Review"},{value:"posted",label:"Posted"}]},cell:e=>re(Jo.Badge,{status:e.status==="posted"?"success":"warning",children:e.status==="posted"?"Posted":"For Review"})}]);function tR({rows:e=qt,pageSize:t=10,canSelect:r,groupBy:n,showSort:o,empty:a,loading:i,stickyHeader:s,stickyRowHeader:l,narrow:c,size:u,activeRowId:d,onRowActivate:m,rowActions:p,getSubRows:h,initialFilters:g,getRowHref:y}){let
|
|
471
|
+
`),Reflect.get(e,t,r)}});var{buildQueries:lV,configure:uV,createEvent:cV,fireEvent:dV,findAllByAltText:pV,findAllByDisplayValue:fV,findAllByLabelText:mV,findAllByPlaceholderText:hV,findAllByRole:yV,findAllByTestId:bV,findAllByText:gV,findAllByTitle:vV,findByAltText:EV,findByDisplayValue:_V,findByLabelText:RV,findByPlaceholderText:wV,findByRole:CV,findByTestId:SV,findByText:AV,findByTitle:TV,getAllByAltText:PV,getAllByDisplayValue:OV,getAllByLabelText:qV,getAllByPlaceholderText:xV,getAllByRole:MV,getAllByTestId:NV,getAllByText:jV,getAllByTitle:IV,getByAltText:DV,getByDisplayValue:FV,getByLabelText:LV,getByPlaceholderText:BV,getByRole:kV,getByTestId:$V,getByText:UV,getByTitle:HV,getConfig:VV,getDefaultNormalizer:zV,getElementError:GV,getNodeText:YV,getQueriesForElement:WV,getRoles:KV,getSuggestedQuery:XV,isInaccessible:JV,logDOM:QV,logRoles:ZV,prettyDOM:e8,queries:t8,queryAllByAltText:r8,queryAllByAttribute:n8,queryAllByDisplayValue:o8,queryAllByLabelText:a8,queryAllByPlaceholderText:i8,queryAllByRole:s8,queryAllByTestId:l8,queryAllByText:u8,queryAllByTitle:c8,queryByAltText:d8,queryByAttribute:p8,queryByDisplayValue:f8,queryByLabelText:m8,queryByPlaceholderText:h8,queryByRole:y8,queryByTestId:b8,queryByText:g8,queryByTitle:v8,queryHelpers:E8,screen:_8,waitFor:R8,waitForElementToBeRemoved:w8,within:tn,prettyFormat:C8}=_c,{userEvent:or}=xa({userEvent:$9},{intercept:!0}),{expect:Et}=xa({expect:VE},{getKeys:(e,t)=>{let r=["assert","__methods","__flags","_obj"];if(e.constructor===x){let n=Object.keys(Object.getPrototypeOf(e)).filter(o=>!r.includes(o));return t>2?n:[...n,"not"]}return Object.keys(e)},intercept:e=>e!=="expect"}),V9=({parameters:e})=>{e?.test?.mockReset===!0?y5():e?.test?.clearMocks===!0?h5():e?.test?.restoreMocks!==!1&&b5()},Rc=(e,t=0,r)=>{if(t>5||e==null)return e;if(jE(e))return r&&e.mockName(r),e;if(typeof e=="function"&&"isAction"in e&&e.isAction&&!("implicit"in e&&e.implicit)){let n=f5(e);return r&&n.mockName(r),n}if(Array.isArray(e)){t++;for(let n=0;n<e.length;n++)e[n]=Rc(e[n],t)}if(typeof e=="object"&&e.constructor===Object){t++;for(let[n,o]of Object.entries(e))Object.getOwnPropertyDescriptor(e,n)?.writable&&(e[n]=Rc(o,t,n));return e}return e},z9=({initialArgs:e})=>{Rc(e)},G9=e=>{globalThis.HTMLElement&&e.canvasElement instanceof globalThis.HTMLElement&&(e.canvas=tn(e.canvasElement))};Ie.__STORYBOOK_TEST_LOADERS__=[V9,z9,G9];Ie.__STORYBOOK_TEST_ON_MOCK_CALL__=p5;var Bt=on(Gd(),1);var Wd=on(gs(),1),Jo=on(Gd(),1),st=on(Yd(),1);var Ui=window.React;function re(e,t,r){let{children:n,...o}=t||{};return r!==void 0&&(o.key=r),n===void 0?Ui.createElement(e,o):Array.isArray(n)?Ui.createElement(e,o,...n):Ui.createElement(e,o,n)}var Tz=Ui.Fragment;var Q1=["Joshua Tree","Mojave Preserve","Death Valley","Joshua Tree"],Z1=["Chase","Visitor fee","Camp store","Unassigned"],qt=Array.from({length:40},(e,t)=>({id:`fee-${t+1}`,date:`2026-10-${String(t%27+1).padStart(2,"0")}`,party:Z1[t%Z1.length]??"Chase",memo:t%5===0?"entrance fee":"reservation",park:Q1[t%Q1.length]??"Joshua Tree",amount:t%7===0?"-12.00":(8+t%9+t/100).toFixed(2),status:t%3===0?"posted":"for_review"})),eR=(0,st.defineColumns)([{id:"date",header:"Date",value:e=>e.date,kind:"date",sortable:!0,width:"min"},{id:"party",header:"Party / description",value:e=>e.party,searchable:e=>[e.memo,e.id],rowHeader:!0,sortable:!0},{id:"park",header:"Park",value:e=>e.park,searchable:!0,filter:{kind:"multi-select",label:"Park"}},{id:"amount",header:"Amount",value:e=>e.amount,kind:"money",currency:"USD",negative:"parens",sortable:!0,total:"sum",width:"min"},{id:"status",header:"Status",value:e=>e.status,filter:{kind:"tabs",options:[{value:"",label:"All",all:!0},{value:"for_review",label:"For Review"},{value:"posted",label:"Posted"}]},cell:e=>re(Jo.Badge,{status:e.status==="posted"?"success":"warning",children:e.status==="posted"?"Posted":"For Review"})}]);function tR({rows:e=qt,pageSize:t=10,canSelect:r,groupBy:n,showSort:o,empty:a,loading:i,stickyHeader:s,stickyRowHeader:l,narrow:c,size:u,activeRowId:d,onRowActivate:m,rowActions:p,getSubRows:h,initialFilters:g,getRowHref:y,totalStyle:b}){let v=(0,Wd.useMemo)(()=>eR,[]),C=(0,st.useCollection)({rows:e,columns:v,getRowId:S=>S.id,pageSize:t,initialSort:{id:"date",desc:!0},initialFilters:g??{status:"for_review"},canSelect:r,groupBy:n,getSubRows:h});return re("div",{children:[re(st.CollectionToolbar,{collection:C,searchLabel:"Find fee",showSort:o,actions:re(Jo.Button,{emphasis:"standard",children:"Add fee"}),bulkActions:re(Jo.Button,{emphasis:"standard",children:"Post selected"})}),re(st.DataTable,{collection:C,label:"Park fees",onRowActivate:m,getRowHref:y,activeRowId:d,rowActions:p,empty:a,loading:i,stickyHeader:s,stickyRowHeader:l,narrow:c,size:u,totalStyle:b}),t?re(st.CollectionPagination,{page:C.page,pageCount:C.pageCount,pageSize:C.pageSize,total:C.filteredCount,filtered:C.isFiltered,label:"Park fees",onPageChange:C.setPage}):null]})}function Pr({rows:e=qt,extra:t,groupBy:r}){let n=(0,Wd.useMemo)(()=>eR,[]),o=(0,st.useCollection)({rows:e,columns:n,getRowId:a=>a.id,initialSort:{id:"date",desc:!0},initialFilters:{status:"for_review"},canSelect:a=>a.status==="for_review",groupBy:r});return re("div",{children:[re(st.CollectionToolbar,{collection:o,searchLabel:"Find fee",showSort:!0}),re(st.DataList,{collection:o,label:"For Review",onRowActivate:()=>{},renderItemExtra:t?()=>re("span",{"data-subtle":"",children:"Inline review"}):void 0})]})}async function Kd({canvasElement:e}){let t=tn(e),r=t.getByRole("searchbox",{name:"Find fee"});await Et(t.queryByRole("button",{name:"Clear search"})).toBeNull(),r.focus(),await or.keyboard("zzz"),await Et(e.querySelector(".CollectionToolbar")?.textContent).not.toContain("Clear filters");let n=await t.findByRole("button",{name:"Clear search"});await or.tab(),await Et(n).toHaveFocus(),await or.keyboard("{Enter}"),await Et(r).toHaveValue(""),await Et(r).toHaveFocus(),await Et(t.queryByRole("button",{name:"Clear search"})).toBeNull(),await or.keyboard("chase"),await or.keyboard("{Escape}"),await Et(r).toHaveValue("")}async function rR({canvasElement:e}){let t=tn(e);await Et(await t.findByRole("button",{name:"Clear filters"})).toBeTruthy(),await Et(e.querySelector(".CollectionToolbar")?.textContent).not.toContain("Clear filters")}var ar=on(Yd(),1);var Y9={title:"Components/Lib/DataList",parameters:{layout:"padded"},tags:["autodocs"]},Xd=Y9,W9={render:()=>re("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:24},children:[re(tR,{pageSize:5}),re(Pr,{rows:qt.slice(0,8)})]})},K9={render:()=>re(e6,{})};function X9(){let[e,t]=(0,nR.useState)(0);return re("div",{children:[re("output",{"data-testid":"activated",children:e}),re(J9,{onActivate:()=>t(r=>r+1)})]})}function J9({onActivate:e}){let t=(0,ar.defineColumns)([{id:"party",header:"Party",value:n=>n.party,rowHeader:!0}]),r=(0,ar.useCollection)({rows:qt.slice(0,3),columns:t,getRowId:n=>n.id});return re(ar.DataList,{collection:r,label:"For Review",onRowActivate:e,renderItemExtra:()=>re("span",{children:"Plain note"})})}var Q9={render:()=>re(X9,{}),play:async({canvasElement:e})=>{let t=tn(e);await or.click(t.getByText("Plain note")),await Et(t.getByTestId("activated").textContent).toBe("0")}},Z9={render:()=>re(Pr,{rows:qt.slice(0,6)}),play:async({canvasElement:e})=>{let t=tn(e);await or.click(t.getByRole("button",{name:/Sort direction/}))}};function e6(){let e=(0,ar.defineColumns)([{id:"party",header:"Party",value:r=>r.party,rowHeader:!0,searchable:!0},{id:"amount",header:"Amount",value:r=>r.amount,kind:"money",currency:"USD"},{id:"status",header:"Status",value:r=>r.status,filter:{kind:"tabs",options:[{value:"for_review",label:"For Review"}]}}]),t=(0,ar.useCollection)({rows:qt.slice(0,6),columns:e,getRowId:r=>r.id,initialFilters:{status:"for_review"}});return re(ar.DataList,{collection:t,label:"For Review",onRowActivate:()=>{},renderItemExtra:()=>re(Bt.Select.Root,{items:[{value:"fees",label:"Fees"}],defaultValue:"fees",children:[re(Bt.Select.Trigger,{"aria-label":"Account",children:[re(Bt.Select.Value,{}),re(Bt.Select.Icon,{children:re("span",{className:"material-symbols-outlined",children:"expand_more"})})]}),re(Bt.Select.Portal,{children:re(Bt.Select.Positioner,{children:re(Bt.Select.Popup,{children:re(Bt.Select.List,{children:re(Bt.Select.Item,{value:"fees",children:"Fees"})})})})})]})})}var t6={render:()=>re(Pr,{rows:qt.slice(0,8),groupBy:"park"})},r6={render:()=>re(Pr,{rows:[]})},n6={render:()=>re(Pr,{rows:qt.slice(0,1).map(e=>({...e,party:"Posted only",status:"posted"}))}),play:rR},o6={render:()=>re(Pr,{rows:qt.slice(0,8)}),play:Kd},a6={render:()=>re("div",{style:{width:280},children:re(Pr,{rows:qt.slice(0,4)})}),play:Kd};var rn=window.React,oR=Xd||{},i6=["BesideTheTable","ReviewQueue","ExtraDoesNotActivate","Sort"];function s6({id:e}){let t=Jd[e],r={...oR.args||{},...t.args||{}};return(t.render||(o=>rn.createElement(oR.component,o)))(r,{args:r,id:e,name:e})}var l6=i6.map(e=>rn.createElement("section",{key:e,className:"ds-story"},rn.createElement("p",{className:"ds-story-name"},e.replace(/([a-z])([A-Z])/g,"$1 $2")),rn.createElement("div",{className:"ds-story-body"},rn.createElement(s6,{id:e}))));window.ReactDOM.createRoot(document.getElementById("root")).render(rn.createElement(rn.Fragment,null,l6));})();
|
|
472
472
|
|
|
473
473
|
</script>
|
|
474
474
|
</body>
|