@scattered-light/loomiere-mojave 0.18.0 → 0.20.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 +4 -3
- package/dist/exports/catalog.json +4 -0
- package/dist/exports/design-system/README.md +4 -3
- package/dist/exports/design-system/components/CollectionCards/README.md +58 -0
- package/dist/exports/design-system/components/CollectionCards/preview.html +19 -0
- package/dist/exports/design-system/components/CollectionToolbar/README.md +3 -1
- package/dist/exports/design-system/components/PickerButton/README.md +1 -1
- package/dist/exports/design-system/components/SplitButton/README.md +26 -0
- package/dist/exports/design-system/components/SplitButton/preview.html +19 -0
- package/dist/exports/design-system/components/StatCard/README.md +4 -1
- package/dist/exports/design-system/components/StatCard/preview.html +1 -1
- package/dist/exports/design-system/components/bundle.css +204 -66
- package/dist/exports/design-system/components/bundle.js +7 -7
- package/dist/exports/design-system/components/index.d.ts +1 -1
- package/dist/exports/figma.json +1 -1
- package/dist/exports/tokens.dtcg.json +8 -0
- package/dist/tokens.css +2 -0
- package/dist/tokens.d.ts +2 -0
- package/dist/tokens.js +2 -0
- package/dist/tokens.json +16 -0
- package/package.json +2 -2
package/dist/exports/AGENTS.md
CHANGED
|
@@ -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`, `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`, `PickerSplit`, `Popover`, `PreviewCard`, `Progress`, `Radio`, `ScrollArea`, `Select`, `Separator`, `Sheet`, `SideNav`, `Slider`, `Splitter`, `StatCard`, `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`).
|
|
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`, `CollectionCards`, `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`, `PickerSplit`, `Popover`, `PreviewCard`, `Progress`, `Radio`, `ScrollArea`, `Select`, `Separator`, `Sheet`, `SideNav`, `Slider`, `SplitButton`, `Splitter`, `StatCard`, `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.Sheet`, `Loomiere.StatFigure`, `Loomiere.StatCard`, `Loomiere.DescriptionList`, `Loomiere.AppBar`, `Loomiere.PickerButton`, `Loomiere.SideNav`. `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, StatCard, DescriptionList, AppBar, PickerButton and SideNav 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
|
|
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.CollectionCards`, `Loomiere.EditableList`, `Loomiere.Sheet`, `Loomiere.StatFigure`, `Loomiere.StatCard`, `Loomiere.DescriptionList`, `Loomiere.AppBar`, `Loomiere.PickerButton`, `Loomiere.SideNav`. `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, CollectionCards, EditableList, Sheet, StatFigure, StatCard, DescriptionList, AppBar, PickerButton and SideNav 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, CollectionPagination and CollectionCards come from `@scattered-light/loomiere-base-ui/custom/collection` and need `@tanstack/react-table` installed. EditableList, Sheet, StatFigure, StatCard, DescriptionList (with `Loomiere.DescriptionItem`), AppBar (with `Loomiere.AppBarSpacer`), PickerButton and SideNav (with `Loomiere.SideNavItem`, `Loomiere.SideNavGroup` and `Loomiere.SideNavToggle`) 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,7 @@ 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
|
+
| `CollectionCards` | The rows of a collection as a grid of cards, such as StatCards, with the same search, sort, filters and paging as the table. |
|
|
219
220
|
| `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
221
|
| `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
222
|
| `StatCard` | Show one item of a list (an Entity, an account) as a card with its name, a caption and a row of figures. Give it href or onOpen and the whole card opens. |
|
|
@@ -116,6 +116,8 @@
|
|
|
116
116
|
"design-system/components/Collapsible/README.md",
|
|
117
117
|
"design-system/components/Collapsible/preview.html",
|
|
118
118
|
"design-system/components/Collection/README.md",
|
|
119
|
+
"design-system/components/CollectionCards/README.md",
|
|
120
|
+
"design-system/components/CollectionCards/preview.html",
|
|
119
121
|
"design-system/components/CollectionPagination/README.md",
|
|
120
122
|
"design-system/components/CollectionToolbar/README.md",
|
|
121
123
|
"design-system/components/Combobox/README.md",
|
|
@@ -185,6 +187,8 @@
|
|
|
185
187
|
"design-system/components/SideNav/preview.html",
|
|
186
188
|
"design-system/components/Slider/README.md",
|
|
187
189
|
"design-system/components/Slider/preview.html",
|
|
190
|
+
"design-system/components/SplitButton/README.md",
|
|
191
|
+
"design-system/components/SplitButton/preview.html",
|
|
188
192
|
"design-system/components/Splitter/README.md",
|
|
189
193
|
"design-system/components/Splitter/preview.html",
|
|
190
194
|
"design-system/components/StatCard/README.md",
|
|
@@ -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`, `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`, `PickerSplit`, `Popover`, `PreviewCard`, `Progress`, `Radio`, `ScrollArea`, `Select`, `Separator`, `Sheet`, `SideNav`, `Slider`, `Splitter`, `StatCard`, `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`).
|
|
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`, `CollectionCards`, `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`, `PickerSplit`, `Popover`, `PreviewCard`, `Progress`, `Radio`, `ScrollArea`, `Select`, `Separator`, `Sheet`, `SideNav`, `Slider`, `SplitButton`, `Splitter`, `StatCard`, `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.Sheet`, `Loomiere.StatFigure`, `Loomiere.StatCard`, `Loomiere.DescriptionList`, `Loomiere.AppBar`, `Loomiere.PickerButton`, `Loomiere.SideNav`. `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, StatCard, DescriptionList, AppBar, PickerButton and SideNav 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
|
|
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.CollectionCards`, `Loomiere.EditableList`, `Loomiere.Sheet`, `Loomiere.StatFigure`, `Loomiere.StatCard`, `Loomiere.DescriptionList`, `Loomiere.AppBar`, `Loomiere.PickerButton`, `Loomiere.SideNav`. `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, CollectionCards, EditableList, Sheet, StatFigure, StatCard, DescriptionList, AppBar, PickerButton and SideNav 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, CollectionPagination and CollectionCards come from `@scattered-light/loomiere-base-ui/custom/collection` and need `@tanstack/react-table` installed. EditableList, Sheet, StatFigure, StatCard, DescriptionList (with `Loomiere.DescriptionItem`), AppBar (with `Loomiere.AppBarSpacer`), PickerButton and SideNav (with `Loomiere.SideNavItem`, `Loomiere.SideNavGroup` and `Loomiere.SideNavToggle`) 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,7 @@ 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
|
+
| `CollectionCards` | The rows of a collection as a grid of cards, such as StatCards, with the same search, sort, filters and paging as the table. |
|
|
211
212
|
| `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
213
|
| `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
214
|
| `StatCard` | Show one item of a list (an Entity, an account) as a card with its name, a caption and a row of figures. Give it href or onOpen and the whole card opens. |
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# CollectionCards
|
|
2
|
+
|
|
3
|
+
Loomiere component, not part of Base UI. The page of a collection as a grid. Columns fill the width, none narrower than --sl-collection-cards-min-width. Each card stretches to the row's height.
|
|
4
|
+
|
|
5
|
+
Use `Loomiere.CollectionCards` 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
|
+
|
|
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
|
+
| `CollectionCards` | |
|
|
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 CollectionCards stories (`Default`):
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
export const Default: Story = {
|
|
23
|
+
args: { collection: undefined as never, label: 'Entities', renderCard: () => null },
|
|
24
|
+
render: () => <Demo />,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function SegmentedDemo() {
|
|
28
|
+
const collection = useCollection<Entity>({
|
|
29
|
+
rows: entities,
|
|
30
|
+
getRowId: (r) => r.id,
|
|
31
|
+
pageSize: 6,
|
|
32
|
+
columns: [
|
|
33
|
+
{ id: 'name', header: 'Entity', value: (r) => r.name, searchable: true, sortable: true, rowHeader: true },
|
|
34
|
+
{ id: 'open', header: 'Most open', value: (r) => (r.open ? 'open' : 'none'), filter: { kind: 'select', options: [{ value: 'open', label: 'Open items' }, { value: 'none', label: 'Nothing open' }] }, hidden: true },
|
|
35
|
+
],
|
|
36
|
+
});
|
|
37
|
+
return (
|
|
38
|
+
<div style={{ display: 'grid', gap: '16px' }}>
|
|
39
|
+
<CollectionToolbar
|
|
40
|
+
collection={collection}
|
|
41
|
+
searchLabel="Find an Entity"
|
|
42
|
+
searchPlaceholder="Find an Entity"
|
|
43
|
+
ruled
|
|
44
|
+
segments={[
|
|
45
|
+
segmentFilter(collection, 'open', 'Filter', [{ value: 'all', label: 'All' }, { value: 'open', label: 'Open items' }, { value: 'none', label: 'Nothing open' }]),
|
|
46
|
+
{ ...segmentSort(collection, 'Sort', [{ value: 'name', label: 'A–Z' }]), showLabel: true, end: true },
|
|
47
|
+
]}
|
|
48
|
+
meta={`${collection.pageTotal} Entities`}
|
|
49
|
+
/>
|
|
50
|
+
<CollectionCards collection={collection} label="Entities" renderCard={(row) => <StatCard title={row.name} facts={[{ label: 'Open', value: row.open || '–' }]} />} />
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** `segments` turns the toolbar into search plus toggle groups for quick filters and sort. */
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The preview also shows `SegmentedToolbar`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- @dsCard group="Data" height=240 subtitle="Default / SegmentedToolbar" -->
|
|
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 v=Object.create;var d=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,F=Object.prototype.hasOwnProperty;var u=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),D=(t,e)=>{for(var o in e)d(t,o,{get:e[o],enumerable:!0})},R=(t,e,o,l)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of w(e))!F.call(t,r)&&r!==o&&d(t,r,{get:()=>e[r],enumerable:!(l=C(e,r))||l.enumerable});return t};var g=(t,e,o)=>(o=t!=null?v(x(t)):{},R(e||!t||!t.__esModule?d(o,"default",{value:t,enumerable:!0}):o,t));var b=u((k,y)=>{y.exports=window.Loomiere});var f=u(($,E)=>{E.exports=window.Loomiere});var p={};D(p,{Default:()=>L,SegmentedToolbar:()=>j,default:()=>m});var c=g(b(),1),n=g(f(),1);var s=window.React;function a(t,e,o){let{children:l,...r}=e||{};return o!==void 0&&(r.key=o),l===void 0?s.createElement(t,r):Array.isArray(l)?s.createElement(t,r,...l):s.createElement(t,r,l)}var H=s.Fragment;var h=Array.from({length:14},(t,e)=>({id:String(e+1),name:["North","Boreal","Cedar","Delta","Elm","Fjord","Grove"][e%7]+(e>6?" Holdings":" Company"),open:e*3%5})),O={title:"Components/Lib/CollectionCards",component:n.CollectionCards,parameters:{layout:"padded"},tags:["autodocs","ds:lib"]},m=O;function A(){let t=(0,n.useCollection)({rows:h,getRowId:e=>e.id,pageSize:6,columns:[{id:"name",header:"Entity",value:e=>e.name,searchable:!0,sortable:!0,rowHeader:!0},{id:"open",header:"Most open",value:e=>e.open,kind:"number",sortable:!0,hidden:!0}]});return a("div",{style:{display:"grid",gap:"16px"},children:[a(n.CollectionToolbar,{collection:t,searchLabel:"Find an Entity",searchPlaceholder:"Find an Entity",showSort:!0}),a(n.CollectionCards,{collection:t,label:"Entities",renderCard:e=>a(c.StatCard,{title:e.name,caption:"USD",href:`#${e.id}`,facts:[{label:"Open",value:e.open||"\u2013",tone:e.open?"accent":"default"}]})}),a(n.CollectionPagination,{page:t.page,pageCount:t.pageCount,pageSize:t.pageSize,total:t.pageTotal,filtered:t.isFiltered,onPageChange:t.setPage,label:"Entities"})]})}var L={args:{collection:void 0,label:"Entities",renderCard:()=>null},render:()=>a(A,{})};function N(){let t=(0,n.useCollection)({rows:h,getRowId:e=>e.id,pageSize:6,columns:[{id:"name",header:"Entity",value:e=>e.name,searchable:!0,sortable:!0,rowHeader:!0},{id:"open",header:"Most open",value:e=>e.open?"open":"none",filter:{kind:"select",options:[{value:"open",label:"Open items"},{value:"none",label:"Nothing open"}]},hidden:!0}]});return a("div",{style:{display:"grid",gap:"16px"},children:[a(n.CollectionToolbar,{collection:t,searchLabel:"Find an Entity",searchPlaceholder:"Find an Entity",ruled:!0,segments:[(0,n.segmentFilter)(t,"open","Filter",[{value:"all",label:"All"},{value:"open",label:"Open items"},{value:"none",label:"Nothing open"}]),{...(0,n.segmentSort)(t,"Sort",[{value:"name",label:"A\u2013Z"}]),showLabel:!0,end:!0}],meta:`${t.pageTotal} Entities`}),a(n.CollectionCards,{collection:t,label:"Entities",renderCard:e=>a(c.StatCard,{title:e.name,facts:[{label:"Open",value:e.open||"\u2013"}]})})]})}var j={args:{collection:void 0,label:"Entities",renderCard:()=>null},render:()=>a(N,{})};var i=window.React,S=m||{},z=["Default","SegmentedToolbar"];function M({id:t}){let e=p[t],o={...S.args||{},...e.args||{}};return(e.render||(r=>i.createElement(S.component,r)))(o,{args:o,id:t,name:t})}var P=z.map(t=>i.createElement("section",{key:t,className:"ds-story"},i.createElement("p",{className:"ds-story-name"},t.replace(/([a-z])([A-Z])/g,"$1 $2")),i.createElement("div",{className:"ds-story-body"},i.createElement(M,{id:t}))));window.ReactDOM.createRoot(document.getElementById("root")).render(i.createElement(i.Fragment,null,P));})();
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -10,7 +10,7 @@ Not a Base UI part, so there is no base-ui.com page for it.
|
|
|
10
10
|
|
|
11
11
|
| Class | Data attributes it answers to |
|
|
12
12
|
|---|---|
|
|
13
|
-
| `CollectionToolbar` | `data-narrow`; `data-search`: `fixed`; `data-framed` |
|
|
13
|
+
| `CollectionToolbar` | `data-narrow`; `data-search`: `fixed`; `data-framed`; `data-segmented`; `data-ruled` |
|
|
14
14
|
| `CollectionToolbarMain` | |
|
|
15
15
|
| `CollectionSelectionBar` | |
|
|
16
16
|
| `CollectionSort` | |
|
|
@@ -27,5 +27,7 @@ Not a Base UI part, so there is no base-ui.com page for it.
|
|
|
27
27
|
| `CollectionCount` | |
|
|
28
28
|
| `CollectionToolbarMeta` | |
|
|
29
29
|
| `CollectionToolbarMetaEnd` | |
|
|
30
|
+
| `CollectionSegment` | `data-end` |
|
|
31
|
+
| `CollectionSegmentLabel` | |
|
|
30
32
|
|
|
31
33
|
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.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PickerButton
|
|
2
2
|
|
|
3
|
-
Loomiere component, not part of Base UI. A trigger with a caps label before the current choice: CLIENT Alpha Services. The field look and states of a Select trigger; the label is caps-condense in picker-button.label-color, the choice is cut with an ellipsis at picker-button.max-width and the chevron turns while its popup is open. Label and choice
|
|
3
|
+
Loomiere component, not part of Base UI. A trigger with a caps label before the current choice: CLIENT Alpha Services. The field look and states of a Select trigger; the label is caps-condense in picker-button.label-color, the choice is cut with an ellipsis at picker-button.max-width and the chevron turns while its popup is open. Label and choice are centered on the control's height, so a caps label and its choice sit level at any font size; picker-button.text-offset nudges both down for a typeface that sits high. Tokens: picker-button.* (tokens/component/picker-button.json) and field.*.
|
|
4
4
|
|
|
5
5
|
Use `Loomiere.PickerButton`, this package's component: it puts the class names on for you (`import { PickerButton } from '@scattered-light/loomiere-base-ui'`, or from `@scattered-light/loomiere-base-ui/custom`).
|
|
6
6
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# SplitButton
|
|
2
|
+
|
|
3
|
+
Loomiere component, not part of Base UI. A Button and a square Menu trigger side by side, joined into one outline: the inner corners are square and the trigger overlaps the main part's border by one stroke.
|
|
4
|
+
|
|
5
|
+
Use `Loomiere.SplitButton`, this package's component: it puts the class names on for you (`import { SplitButton } 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
|
+
| `SplitButton` | |
|
|
14
|
+
| `Button` | |
|
|
15
|
+
|
|
16
|
+
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.
|
|
17
|
+
|
|
18
|
+
## Example
|
|
19
|
+
|
|
20
|
+
From the SplitButton stories (`Default`):
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
export const Default: Story = {};
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The preview also shows `Disabled`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- @dsCard group="Actions" height=240 subtitle="Default / Disabled" -->
|
|
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 y=Object.create;var s=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var S=Object.getPrototypeOf,f=Object.prototype.hasOwnProperty;var g=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),w=(e,t)=>{for(var o in t)s(e,o,{get:t[o],enumerable:!0})},E=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of u(t))!f.call(e,a)&&a!==o&&s(e,a,{get:()=>t[a],enumerable:!(n=b(t,a))||n.enumerable});return e};var k=(e,t,o)=>(o=e!=null?y(S(e)):{},E(t||!e||!e.__esModule?s(o,"default",{value:e,enumerable:!0}):o,e));var d=g((L,m)=>{m.exports=window.Loomiere});var c={};w(c,{Default:()=>B,Disabled:()=>D,default:()=>l});var i=k(d(),1),x={title:"Components/Lib/SplitButton",component:i.SplitButton,parameters:{layout:"padded"},tags:["autodocs","ds:lib"],args:{label:"Add Transaction",onClick:()=>{},moreLabel:"More ways to add transactions",items:[{label:"Bank connection (not yet available)",onSelect:()=>{},disabled:!0},{label:"Import CSV",onSelect:()=>{}},{label:"Import Excel workbook",onSelect:()=>{}}]}},l=x,B={},D={args:{disabled:!0}};var r=window.React,p=l||{},M=["Default","Disabled"];function R({id:e}){let t=c[e],o={...p.args||{},...t.args||{}};return(t.render||(a=>r.createElement(p.component,a)))(o,{args:o,id:e,name:e})}var C=M.map(e=>r.createElement("section",{key:e,className:"ds-story"},r.createElement("p",{className:"ds-story-name"},e.replace(/([a-z])([A-Z])/g,"$1 $2")),r.createElement("div",{className:"ds-story-body"},r.createElement(R,{id:e}))));window.ReactDOM.createRoot(document.getElementById("root")).render(r.createElement(r.Fragment,null,C));})();
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -10,7 +10,7 @@ Not a Base UI part, so there is no base-ui.com page for it.
|
|
|
10
10
|
|
|
11
11
|
| Class | Data attributes it answers to |
|
|
12
12
|
|---|---|
|
|
13
|
-
| `StatCard` | `data-interactive` |
|
|
13
|
+
| `StatCard` | `data-interactive`; `data-detailed` |
|
|
14
14
|
| `StatCardHeader` | |
|
|
15
15
|
| `StatCardHeading` | |
|
|
16
16
|
| `StatCardTag` | |
|
|
@@ -19,6 +19,9 @@ Not a Base UI part, so there is no base-ui.com page for it.
|
|
|
19
19
|
| `StatCardLink` | |
|
|
20
20
|
| `StatCardFacts` | |
|
|
21
21
|
| `StatCardFooter` | |
|
|
22
|
+
| `DescriptionList` | |
|
|
23
|
+
| `StatCardBar` | |
|
|
24
|
+
| `StatCardStatus` | |
|
|
22
25
|
|
|
23
26
|
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.
|
|
24
27
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<body>
|
|
13
13
|
<div id="root"></div>
|
|
14
14
|
<script>
|
|
15
|
-
(()=>{var f=Object.create;var i=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var b=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var v=(e
|
|
15
|
+
(()=>{var f=Object.create;var i=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var b=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var v=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),w=(t,e)=>{for(var o in e)i(t,o,{get:e[o],enumerable:!0})},E=(t,e,o,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of S(e))!x.call(t,a)&&a!==o&&i(t,a,{get:()=>e[a],enumerable:!(n=g(e,a))||n.enumerable});return t};var h=(t,e,o)=>(o=t!=null?f(b(t)):{},E(e||!t||!t.__esModule?i(o,"default",{value:t,enumerable:!0}):o,t));var u=v((T,d)=>{d.exports=window.Loomiere});var p={};w(p,{AsButton:()=>C,Default:()=>R,Detailed:()=>j,Static:()=>B,TwoFigures:()=>A,WithFooter:()=>F,WithTag:()=>N,default:()=>m});var l=h(u(),1);var c=window.React;function s(t,e,o){let{children:n,...a}=e||{};return o!==void 0&&(a.key=o),n===void 0?c.createElement(t,a):Array.isArray(n)?c.createElement(t,a,...n):c.createElement(t,a,n)}var U=c.Fragment;var D={title:"Components/Lib/StatCard",component:l.StatCard,parameters:{layout:"padded"},tags:["autodocs","ds:lib"],args:{title:"North Company",caption:"USD \xB7 1 account",facts:[{label:"Questions",value:"1",tone:"accent"},{label:"Docs",value:"\u2013"},{label:"Review",value:"2",tone:"accent"}]}},m=D,O={display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(18rem, 1fr))",gap:"16px"},R={render:t=>s("div",{style:O,children:[s(l.StatCard,{...t,href:"#north"}),s(l.StatCard,{...t,title:"Boreal Company",caption:"USD \xB7 3 accounts",facts:[{label:"Questions",value:"\u2013"},{label:"Docs",value:"4",tone:"accent"},{label:"Review",value:"12",tone:"accent"}],href:"#boreal"})]})},C={args:{onOpen:()=>{}}},B={},F={args:{footer:"Last reconciled Oct 29"}},A={args:{facts:[{label:"Book balance",value:"75.00",caption:"DR"},{label:"Unposted",value:"2",tone:"accent"}]}},N={args:{tag:"2 new",footer:"1 account \xB7 Cash 75.00 Dr"}},j={args:{details:[["Last activity","Oct 29"],["Open since","Oct 3"]],status:"Waiting on client",actions:s("button",{type:"button",className:"Button","data-emphasis":"quiet",children:"Open Entity \u2192"})}};var r=window.React,y=m||{},L=["Default","AsButton","Static","WithFooter"];function W({id:t}){let e=p[t],o={...y.args||{},...e.args||{}};return(e.render||(a=>r.createElement(y.component,a)))(o,{args:o,id:t,name:t})}var k=L.map(t=>r.createElement("section",{key:t,className:"ds-story"},r.createElement("p",{className:"ds-story-name"},t.replace(/([a-z])([A-Z])/g,"$1 $2")),r.createElement("div",{className:"ds-story-body"},r.createElement(W,{id:t}))));window.ReactDOM.createRoot(document.getElementById("root")).render(r.createElement(r.Fragment,null,k));})();
|
|
16
16
|
|
|
17
17
|
</script>
|
|
18
18
|
</body>
|