@starci/grammar 0.12.3 → 0.12.5
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/README.md +69 -21
- package/dist/.build-stamp.json +4 -4
- package/dist/common/components-avatar-group.css +7 -0
- package/dist/common/components-forms.css +7 -74
- package/dist/common/components-list-panel.css +36 -7
- package/dist/common/components-navigation.css +46 -157
- package/dist/common/components-overlays.css +1 -85
- package/dist/common/registry.d.ts +4 -4
- package/dist/common/renderers-navigation.d.ts +6 -5
- package/dist/common/renderers-navigation.d.ts.map +1 -1
- package/dist/common/renderers-navigation.js.map +1 -1
- package/dist/common/renderers.d.ts +4 -0
- package/dist/common/renderers.d.ts.map +1 -1
- package/dist/common/renderers.js +3 -0
- package/dist/common/renderers.js.map +1 -1
- package/dist/common/styles.css +7 -57
- package/dist/core/branch/AlertDialog/index.d.ts.map +1 -1
- package/dist/core/branch/AlertDialog/index.js +4 -1
- package/dist/core/branch/AlertDialog/index.js.map +1 -1
- package/dist/core/branch/DataTable/index.d.ts +0 -2
- package/dist/core/branch/DataTable/index.d.ts.map +1 -1
- package/dist/core/branch/DataTable/index.js +3 -2
- package/dist/core/branch/DataTable/index.js.map +1 -1
- package/dist/core/branch/Dialog/index.d.ts.map +1 -1
- package/dist/core/branch/Dialog/index.js +2 -1
- package/dist/core/branch/Dialog/index.js.map +1 -1
- package/dist/core/branch/DragItem/index.d.ts +2 -1
- package/dist/core/branch/DragItem/index.d.ts.map +1 -1
- package/dist/core/branch/DragItem/index.js +1 -1
- package/dist/core/branch/DragItem/index.js.map +1 -1
- package/dist/core/branch/Drawer/index.d.ts.map +1 -1
- package/dist/core/branch/Drawer/index.js +2 -1
- package/dist/core/branch/Drawer/index.js.map +1 -1
- package/dist/core/branch/DropdownMenu/index.d.ts +3 -0
- package/dist/core/branch/DropdownMenu/index.d.ts.map +1 -1
- package/dist/core/branch/DropdownMenu/index.js +4 -2
- package/dist/core/branch/DropdownMenu/index.js.map +1 -1
- package/dist/core/branch/FlowGraph/index.d.ts +4 -1
- package/dist/core/branch/FlowGraph/index.d.ts.map +1 -1
- package/dist/core/branch/FlowGraph/index.js +1 -1
- package/dist/core/branch/FlowGraph/index.js.map +1 -1
- package/dist/core/branch/ListBox/index.d.ts +22 -3
- package/dist/core/branch/ListBox/index.d.ts.map +1 -1
- package/dist/core/branch/ListBox/index.js +9 -5
- package/dist/core/branch/ListBox/index.js.map +1 -1
- package/dist/core/branch/Select/index.d.ts +3 -0
- package/dist/core/branch/Select/index.d.ts.map +1 -1
- package/dist/core/branch/Select/index.js +5 -1
- package/dist/core/branch/Select/index.js.map +1 -1
- package/dist/core/branch/SurfaceCard/index.d.ts.map +1 -1
- package/dist/core/branch/SurfaceCard/index.js +2 -1
- package/dist/core/branch/SurfaceCard/index.js.map +1 -1
- package/dist/core/branch/SurfaceListCard/index.d.ts.map +1 -1
- package/dist/core/branch/SurfaceListCard/index.js +2 -1
- package/dist/core/branch/SurfaceListCard/index.js.map +1 -1
- package/dist/core/branch/Tabs/classNames.d.ts +1 -3
- package/dist/core/branch/Tabs/classNames.d.ts.map +1 -1
- package/dist/core/branch/Tabs/classNames.js +1 -4
- package/dist/core/branch/Tabs/classNames.js.map +1 -1
- package/dist/core/branch/Tabs/index.d.ts +2 -6
- package/dist/core/branch/Tabs/index.d.ts.map +1 -1
- package/dist/core/branch/Tabs/index.js +5 -3
- package/dist/core/branch/Tabs/index.js.map +1 -1
- package/dist/core/buttonIntent.d.ts +27 -0
- package/dist/core/buttonIntent.d.ts.map +1 -0
- package/dist/core/buttonIntent.js +29 -0
- package/dist/core/buttonIntent.js.map +1 -0
- package/dist/core/collectionItem.d.ts +16 -0
- package/dist/core/collectionItem.d.ts.map +1 -0
- package/dist/core/collectionItem.js +12 -0
- package/dist/core/collectionItem.js.map +1 -0
- package/dist/core/composite/AvatarButton/index.d.ts +5 -4
- package/dist/core/composite/AvatarButton/index.d.ts.map +1 -1
- package/dist/core/composite/AvatarButton/index.js +2 -2
- package/dist/core/composite/AvatarButton/index.js.map +1 -1
- package/dist/core/composite/AvatarGroup/index.d.ts +6 -4
- package/dist/core/composite/AvatarGroup/index.d.ts.map +1 -1
- package/dist/core/composite/AvatarGroup/index.js +4 -3
- package/dist/core/composite/AvatarGroup/index.js.map +1 -1
- package/dist/core/composite/CollectionItem/index.d.ts +8 -0
- package/dist/core/composite/CollectionItem/index.d.ts.map +1 -0
- package/dist/core/composite/CollectionItem/index.js +5 -0
- package/dist/core/composite/CollectionItem/index.js.map +1 -0
- package/dist/core/composite/Fieldset/index.js +2 -2
- package/dist/core/composite/Fieldset/index.js.map +1 -1
- package/dist/core/composite/IdentityLockup/index.d.ts +2 -2
- package/dist/core/composite/IdentityLockup/index.d.ts.map +1 -1
- package/dist/core/composite/IdentityLockup/index.js +1 -1
- package/dist/core/composite/ItemActions/index.d.ts +8 -0
- package/dist/core/composite/ItemActions/index.d.ts.map +1 -0
- package/dist/core/composite/ItemActions/index.js +5 -0
- package/dist/core/composite/ItemActions/index.js.map +1 -0
- package/dist/core/composite/ListRow/index.d.ts.map +1 -1
- package/dist/core/composite/ListRow/index.js +2 -1
- package/dist/core/composite/ListRow/index.js.map +1 -1
- package/dist/core/composite/SegmentedControl/index.d.ts.map +1 -1
- package/dist/core/composite/SegmentedControl/index.js +2 -2
- package/dist/core/composite/SegmentedControl/index.js.map +1 -1
- package/dist/core/composite/TagGroup/index.d.ts +3 -3
- package/dist/core/composite/TagGroup/index.d.ts.map +1 -1
- package/dist/core/composite/TagGroup/index.js +1 -1
- package/dist/core/composite/TagGroup/index.js.map +1 -1
- package/dist/core/composite/ToolbarActions/index.d.ts +8 -0
- package/dist/core/composite/ToolbarActions/index.d.ts.map +1 -0
- package/dist/core/composite/ToolbarActions/index.js +5 -0
- package/dist/core/composite/ToolbarActions/index.js.map +1 -0
- package/dist/core/composition/ChatWorkspace/index.d.ts.map +1 -1
- package/dist/core/composition/ChatWorkspace/index.js +2 -1
- package/dist/core/composition/ChatWorkspace/index.js.map +1 -1
- package/dist/core/composition/NavigationFeatureNav/index.d.ts.map +1 -1
- package/dist/core/composition/NavigationFeatureNav/index.js +2 -1
- package/dist/core/composition/NavigationFeatureNav/index.js.map +1 -1
- package/dist/core/composition/Sidebar/index.d.ts +4 -0
- package/dist/core/composition/Sidebar/index.d.ts.map +1 -1
- package/dist/core/composition/Sidebar/index.js +5 -3
- package/dist/core/composition/Sidebar/index.js.map +1 -1
- package/dist/core/composition/TopBar/index.d.ts.map +1 -1
- package/dist/core/composition/TopBar/index.js +2 -1
- package/dist/core/composition/TopBar/index.js.map +1 -1
- package/dist/core/composition/WorkspaceShell/index.d.ts.map +1 -1
- package/dist/core/composition/WorkspaceShell/index.js +3 -2
- package/dist/core/composition/WorkspaceShell/index.js.map +1 -1
- package/dist/core/dna.d.ts +59 -2
- package/dist/core/dna.d.ts.map +1 -1
- package/dist/core/dna.js +34 -2
- package/dist/core/dna.js.map +1 -1
- package/dist/core/primitive/Avatar/index.d.ts +32 -24
- package/dist/core/primitive/Avatar/index.d.ts.map +1 -1
- package/dist/core/primitive/Avatar/index.js +57 -30
- package/dist/core/primitive/Avatar/index.js.map +1 -1
- package/dist/core/primitive/Button/index.d.ts +3 -1
- package/dist/core/primitive/Button/index.d.ts.map +1 -1
- package/dist/core/primitive/Button/index.js +4 -1
- package/dist/core/primitive/Button/index.js.map +1 -1
- package/dist/core/primitive/Field/index.d.ts +10 -1
- package/dist/core/primitive/Field/index.d.ts.map +1 -1
- package/dist/core/primitive/Field/index.js +16 -1
- package/dist/core/primitive/Field/index.js.map +1 -1
- package/dist/core/primitive/FileDropzone/index.d.ts.map +1 -1
- package/dist/core/primitive/FileDropzone/index.js +2 -2
- package/dist/core/primitive/FileDropzone/index.js.map +1 -1
- package/dist/core/primitive/GrammarRoot/index.d.ts.map +1 -1
- package/dist/core/primitive/GrammarRoot/index.js +3 -1
- package/dist/core/primitive/GrammarRoot/index.js.map +1 -1
- package/dist/core/primitive/IconButton/index.d.ts +6 -3
- package/dist/core/primitive/IconButton/index.d.ts.map +1 -1
- package/dist/core/primitive/IconButton/index.js +4 -1
- package/dist/core/primitive/IconButton/index.js.map +1 -1
- package/dist/core/primitive/Input/index.d.ts.map +1 -1
- package/dist/core/primitive/Input/index.js +3 -18
- package/dist/core/primitive/Input/index.js.map +1 -1
- package/dist/core/primitive/ListItem/index.d.ts.map +1 -1
- package/dist/core/primitive/ListItem/index.js +2 -1
- package/dist/core/primitive/ListItem/index.js.map +1 -1
- package/dist/core/primitive/Skeleton/index.js +1 -1
- package/dist/core/primitive/Skeleton/index.js.map +1 -1
- package/dist/core/primitive/Slider/index.d.ts.map +1 -1
- package/dist/core/primitive/Slider/index.js +2 -2
- package/dist/core/primitive/Slider/index.js.map +1 -1
- package/dist/core/primitive/Switch/index.d.ts +3 -6
- package/dist/core/primitive/Switch/index.d.ts.map +1 -1
- package/dist/core/primitive/Switch/index.js +1 -1
- package/dist/core/primitive/Switch/index.js.map +1 -1
- package/dist/core/styles.css +0 -2
- package/dist/heritage/dna.d.ts +62 -0
- package/dist/heritage/dna.d.ts.map +1 -0
- package/dist/heritage/dna.js +37 -0
- package/dist/heritage/dna.js.map +1 -0
- package/dist/offset-pop/dna.d.ts +56 -0
- package/dist/offset-pop/dna.d.ts.map +1 -1
- package/dist/offset-pop/dna.js +31 -0
- package/dist/offset-pop/dna.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -36,6 +36,25 @@ its root from one place. Heritage does not re-export Common. It exports `heritag
|
|
|
36
36
|
|
|
37
37
|
## Usage
|
|
38
38
|
|
|
39
|
+
### Button intent
|
|
40
|
+
|
|
41
|
+
Applications declare `intent` on `Button` and `IconButton`: `commit`, `alternative`, `dismiss`,
|
|
42
|
+
`neutral` or `destructive`. A destructive action may supply `step="entry" | "confirm"`; omitted
|
|
43
|
+
step means entry. The type permits `step` only for destructive intent. The family DNA's `intent`
|
|
44
|
+
mapping derives the variant. Explicit `variant` remains available to Grammar internals and stories.
|
|
45
|
+
The [generated button props catalog](docs/button-intent-props.generated.md) lists the published values.
|
|
46
|
+
|
|
47
|
+
Collection rows supply item placement automatically. Wrap a custom repeated card in
|
|
48
|
+
`CollectionItem`, or its action slot in `ItemActions`; both preserve the existing DOM. A repeated
|
|
49
|
+
next action resolves to secondary. `ToolbarActions` supplies chrome placement for custom persistent
|
|
50
|
+
toolbars without adding markup. Bars and panel headers supply chrome placement; neutral commands
|
|
51
|
+
are ghost there, while navbar icon actions stay tertiary. The default decision placement makes a
|
|
52
|
+
neutral command outline. Dialogs and drawers restore decision placement inside their surfaces.
|
|
53
|
+
|
|
54
|
+
Use a `Button` for final destructive confirmation. `AlertDialog` renders dismiss first, focuses it
|
|
55
|
+
on entry, then renders its destructive confirm last. The `Primitives/Button intent` stories show
|
|
56
|
+
the complete placement mapping in light and dark, including destination, pending and skeleton states.
|
|
57
|
+
|
|
39
58
|
### App shell
|
|
40
59
|
|
|
41
60
|
The [app-shell canon](../../knowledge/ui/composition/app-shell.yaml) owns `FE-APP-SHELL-1` through `FE-APP-SHELL-7`.
|
|
@@ -45,7 +64,7 @@ The `Compositions/App shell` stories show the fixed shell, grouped sidebar, icon
|
|
|
45
64
|
- `SidebarItem.badge`, `badgeLabel` and `badgeMax` show and announce unread counts in both sidebar presentations. `SidebarGroup.placement="end"` places settings groups after the main groups and pushes them to the bottom.
|
|
46
65
|
- The collapsed Sidebar uses Grammar's internal `AnchoredTooltip` on hover and focus. HeroUI Tooltip positions the annotation beside the selected collection item and portals it into the same family DOM scope, preserving HeroUI's collection anatomy. `onAction` runs for every activated destination, including the selected item, so a drawer can close consistently.
|
|
47
66
|
- A fixed `WorkspaceShell` frames its `compactHeader` slot as the mobile opener band; pass a client `Drawer` with an ellipsis `IconButton` trigger. The `navigationDrawer` form owns the same band when it supplies the opener.
|
|
48
|
-
- `AvatarButton seed` passes the stable identity id to Grammar's shared `Avatar`, which draws
|
|
67
|
+
- `AvatarButton seed` passes the stable identity id to Grammar's shared `Avatar`, which draws local DiceBear initials whenever `src` is absent; an uploaded `src` takes precedence.
|
|
49
68
|
- `DropdownMenuItem.mark` accepts a decorative identity mark and is mutually exclusive with `iconSource`. A destructive item uses `tone="danger"`.
|
|
50
69
|
|
|
51
70
|
Compose the interactive shell in a Client Component, where its glyph functions, callbacks and
|
|
@@ -78,7 +97,7 @@ import "@starci/grammar/common/styles.css"
|
|
|
78
97
|
export const App = () => (
|
|
79
98
|
<GrammarRoot theme="system">
|
|
80
99
|
<PageContainer>
|
|
81
|
-
<SurfaceCard label="Welcome"><Button>Start</Button></SurfaceCard>
|
|
100
|
+
<SurfaceCard label="Welcome"><Button intent="commit">Start</Button></SurfaceCard>
|
|
82
101
|
</PageContainer>
|
|
83
102
|
</GrammarRoot>
|
|
84
103
|
)
|
|
@@ -220,7 +239,7 @@ page of timestamps does not repeatedly interrupt assistive technology. Grammar o
|
|
|
220
239
|
`Intl.RelativeTimeFormat` for this primitive; other application date display follows FE-DATE.
|
|
221
240
|
|
|
222
241
|
**DropdownMenu entries.** `entries` is a list of items and sections; the app writes data and no markup, no separator, no
|
|
223
|
-
className and no size. An item takes `id`, `label`, `description`, `shortcut`, `href`, `isDisabled`, `submenu` and:
|
|
242
|
+
className and no size. An item takes `id`, `label`, `description`, `descriptionLines`, `shortcut`, `href`, `isDisabled`, `submenu` and:
|
|
224
243
|
|
|
225
244
|
- `iconSource`: a glyph component (the app's Heroicons). Grammar draws it in HeroUI's leading position at the canon icon size,
|
|
226
245
|
20px (`size-5`, `Icon` `leading`; the Heroicons rule R93 / FE-ICON). HeroUI's own docs example draws its sample glyph at
|
|
@@ -257,7 +276,7 @@ and `Select` are HeroUI's own list-box items (a `Label`, a `Description`, the it
|
|
|
257
276
|
DescriptionList, Disclosure, ListBox, Pagination, Stepper, Subnav, Tabs, TagGroup, Timeline.
|
|
258
277
|
|
|
259
278
|
`DataTable.getCellInteraction(row, columnId)` optionally supplies `onAction`, `onDragOver`,
|
|
260
|
-
`onDragLeave
|
|
279
|
+
`onDragLeave` and `onDrop`. Cells remain semantic
|
|
261
280
|
table cells under the existing arrow-key navigation. An actionable cell takes focus itself,
|
|
262
281
|
activates once with Enter/Space or a click on its plain content, and leaves nested controls to
|
|
263
282
|
their own actions. Native drag callbacks receive the actual inner content-frame event (`HTMLDivElement`); the caller owns
|
|
@@ -305,21 +324,30 @@ dismissal and focus return.
|
|
|
305
324
|
shape in any state, no hover effect, a zoom-out on press, a focus ring, and no zoom under
|
|
306
325
|
`prefers-reduced-motion`. `AvatarButton` is a circle-only avatar built on it (an account-menu
|
|
307
326
|
trigger) and `IdentityLockup` a mark beside a title and a muted subtitle with no caret (a workspace
|
|
308
|
-
switcher trigger). All three work as the `trigger` of `DropdownMenu` and `Popover`. `IdentityLockup`'s mark
|
|
327
|
+
switcher trigger). All three work as the `trigger` of `DropdownMenu` and `Popover`. `IdentityLockup`'s uploaded mark has a transparent box; without an image it uses Avatar's local DiceBear initials. The mark is an uncropped square by default (`markShape="rounded"` opts in to a
|
|
309
328
|
corner) and `Avatar` takes `shape="square" | "rounded"`.
|
|
310
329
|
|
|
311
|
-
Personal avatars are circles.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
330
|
+
Personal avatars are circles. `Avatar`, `AvatarButton` and each `AvatarGroup` member render the
|
|
331
|
+
bundled DiceBear `initials` style whenever `src` is absent. Initials use the first and last words
|
|
332
|
+
of `name`: `Tran Minh Khoa` becomes `TK`, and a single word contributes one letter. Pass the user
|
|
333
|
+
or entity id as `seed` for stable colours; otherwise the name determines the colour. Server and
|
|
334
|
+
client render the same local data URI, with no network request. The image follows the requested
|
|
335
|
+
Avatar shape and keeps contrasting text in light and dark themes. Images have `alt=""`; the
|
|
336
|
+
avatar shell carries its name, or `isDecorative` hides it beside a visible name. `AvatarButton`
|
|
337
|
+
names the button and keeps its inner avatar decorative. Apps install and import Grammar; its
|
|
338
|
+
pinned DiceBear runtime dependencies and avatar drawing stay inside the package.
|
|
339
|
+
|
|
340
|
+
`kind="person" | "agent"` defaults to `person` on `Avatar`, `AvatarButton` and `AvatarGroup` items.
|
|
341
|
+
Agent names are free text and use the same first-and-last-word initials: `Thao Van Mkt` becomes
|
|
342
|
+
`TM`. Agents add a bottom-right bot badge through HeroUI's Badge anchor, with a surface-colour
|
|
343
|
+
ring and `AI` in the accessible name. The badge is hidden below 32px, including group grid cells;
|
|
344
|
+
their initials and accessible identity remain available.
|
|
318
345
|
The package requires Node 22 or newer, as does the pinned DiceBear engine.
|
|
319
346
|
|
|
320
347
|
```tsx
|
|
321
348
|
<Avatar name={user.name} seed={user.id} isDecorative />
|
|
322
349
|
<AvatarButton name={user.name} seed={user.id} src={user.avatarUrl} />
|
|
350
|
+
<Avatar name="Thao Van Mkt" seed="agent-1" kind="agent" />
|
|
323
351
|
<AvatarGroup label="Team" items={members.map(user => ({ id: user.id, name: user.name, seed: user.id }))}
|
|
324
352
|
overflowLabel={count => `${count} more members`} />
|
|
325
353
|
```
|
|
@@ -353,32 +381,52 @@ canon's `FE_NESTED_VARIANT` rejects static field variants throughout app code an
|
|
|
353
381
|
Tabs inside a painted surface. `FE_GRAMMAR_LAYOUT_ONLY` rejects application paint utilities,
|
|
354
382
|
arbitrary paint properties and inline style paint; application CSS carries layout only.
|
|
355
383
|
|
|
356
|
-
ListBox defaults to `inset="panel"` inside the same context.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
space
|
|
384
|
+
ListBox defaults to `inset="panel"` inside the same context. Its box aligns with the panel's search
|
|
385
|
+
field and tabs boxes without negative margins or application padding wrappers (PADDING-0).
|
|
386
|
+
Content keeps HeroUI's list inset and item padding, rounded hover/pressed/selected backgrounds,
|
|
387
|
+
and selection-indicator space, including inside a scrolling panel. Outside a surface, the vendor list inset stays;
|
|
360
388
|
`inset="panel"` also selects the alignment explicitly. Pass flat `items` or named `sections`
|
|
361
389
|
(`ListBoxSection`), with unique item ids across the whole list. `FE_LIST_PANEL_PADDING` rejects
|
|
362
390
|
horizontal padding wrappers around a list or its section caption within the nearest painted Grammar surface.
|
|
363
391
|
Sidebar's expanded and collapsed
|
|
364
392
|
rows also retain HeroUI item padding.
|
|
365
393
|
|
|
394
|
+
A `ListBoxItem` is `label` (a string: the title, accessible name and typeahead text), optional `description`,
|
|
395
|
+
`leading` (a centred node in a fixed column before the copy, such as an avatar), `trailing` (after it, such as a count) and
|
|
396
|
+
`isDisabled`. Descriptions show one line with an ellipsis by default; `descriptionLines?: 1 | 2 | 3`
|
|
397
|
+
selects the visible line limit. The same prop and default apply to `DropdownMenuItem`, `SidebarItem`
|
|
398
|
+
and the `ListOption` descriptions used by Select and ComboBox. The packaged stylesheet clamps the
|
|
399
|
+
vendor `Description` slot; its full text stays available to assistive technology.
|
|
400
|
+
`ListBoxItem.emphasis="unread"` makes both the label and description strong using the active family's
|
|
401
|
+
DNA. Omit it for a read row, which keeps HeroUI's normal label and muted description.
|
|
402
|
+
Optional `labelLeading` puts a decorative glyph in the title line itself, inside HeroUI's `Label` before the
|
|
403
|
+
text and on its baseline, e.g. a status mark beside an item's name. Both glyph slots are
|
|
404
|
+
`aria-hidden` (A11Y-2), so the name stays `label`; pass an `Icon usage="chip"` to keep the title line's height.
|
|
405
|
+
`ListBox size="sm" | "md" | "lg"` defaults to `md` and reserves a leading column of 2rem, 2.5rem
|
|
406
|
+
or 3rem, respectively, so icons, avatars and group grids keep labels in one column. An item's
|
|
407
|
+
`size` overrides the list's size.
|
|
408
|
+
|
|
366
409
|
```tsx
|
|
367
410
|
<SurfaceCard ariaLabel="Conversations">
|
|
368
411
|
<Heading level={2}>Conversations</Heading>
|
|
369
412
|
<SearchField label="Find a conversation" />
|
|
370
413
|
<ListBox label="Conversations" sections={[
|
|
371
|
-
{ id: "recent", label: "Recent", items: [
|
|
414
|
+
{ id: "recent", label: "Recent", items: [
|
|
415
|
+
{ id: "team", label: "Design team", description: "Sam: The draft is ready", emphasis: "unread" },
|
|
416
|
+
] },
|
|
372
417
|
]} />
|
|
373
418
|
</SurfaceCard>
|
|
374
419
|
```
|
|
375
420
|
|
|
376
421
|
For a conversation or group identity, use `AvatarGroup layout="grid"` (COLLECTION-3, the Zalo
|
|
377
422
|
reference). It is one round Avatar-sized mark at `sm`, `md`, `lg` or `control`: two members split
|
|
378
|
-
the circle, three show one above two, and four use a 2 by 2 grid
|
|
379
|
-
members, the fourth cell shows
|
|
380
|
-
|
|
381
|
-
|
|
423
|
+
the circle, three show one above two, and four use a 2 by 2 grid. With five or more
|
|
424
|
+
members, three avatars remain and the fourth cell shows the total member count, such as `5` or `30`.
|
|
425
|
+
Each cell has a ring in the surface colour. Each member uses Avatar's
|
|
426
|
+
uploaded image or bundled DiceBear initials, accepts `seed`, `kind` and a custom uploaded-image `fallback`,
|
|
427
|
+
and the count uses the shared avatar renderer. `overflowLabel` receives the number of hidden members
|
|
428
|
+
in both layouts and names them accessibly; the grid's visible digits show the total. A single
|
|
429
|
+
person uses Avatar. The default `layout="row"` keeps the overlapping member row and its `+N` overflow count.
|
|
382
430
|
|
|
383
431
|
## Theming
|
|
384
432
|
|
package/dist/.build-stamp.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "starci/grammar-build-stamp@1",
|
|
3
3
|
"package": "@starci/grammar",
|
|
4
|
-
"version": "0.12.
|
|
4
|
+
"version": "0.12.5",
|
|
5
5
|
"algorithm": "starci/grammar-source-digest@1",
|
|
6
|
-
"sourceDigest": "sha256:
|
|
7
|
-
"distDigest": "sha256:
|
|
8
|
-
"builtAt": "2026-10-
|
|
6
|
+
"sourceDigest": "sha256:ffb4788560df9c19f27b314c79227eb27ffeab503001d9dfcef8412143ea8833",
|
|
7
|
+
"distDigest": "sha256:b3108e47d872028b103de19bdd2249105e1d355a294a22ec845b40e25bec3e70",
|
|
8
|
+
"builtAt": "2026-10-25T22:28:40.865Z"
|
|
9
9
|
}
|
|
@@ -16,6 +16,13 @@
|
|
|
16
16
|
background: var(--surface, Canvas);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/* Each member and the total-count cell retain a surface ring over uploaded or generated images. */
|
|
20
|
+
.starci-core-avatar-group-grid > .starci-core-avatar-group-member,
|
|
21
|
+
.starci-core-avatar-group-grid > .starci-core-avatar-group-count {
|
|
22
|
+
outline: 1px solid var(--surface, Canvas);
|
|
23
|
+
outline-offset: -1px;
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
.starci-core-avatar-group[data-grammar-avatar-cells="1"] > .starci-core-avatar-group-grid {
|
|
20
27
|
grid-template-columns: minmax(0, 1fr);
|
|
21
28
|
grid-template-rows: minmax(0, 1fr);
|
|
@@ -45,8 +45,6 @@
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
.starci-core-field-error {
|
|
48
|
-
margin: 0;
|
|
49
|
-
color: var(--danger, CanvasText);
|
|
50
48
|
font-size: 0.75rem;
|
|
51
49
|
font-weight: 600;
|
|
52
50
|
line-height: 1.4;
|
|
@@ -142,7 +140,6 @@
|
|
|
142
140
|
.starci-core-field-skeleton-control > .starci-core-skeleton {
|
|
143
141
|
block-size: 100%;
|
|
144
142
|
aspect-ratio: auto;
|
|
145
|
-
border-radius: var(--field-radius, calc(var(--radius, 0.5rem) * 1.5));
|
|
146
143
|
}
|
|
147
144
|
|
|
148
145
|
.starci-core-field-skeleton-control:is([data-grammar-field-skeleton="input"]) { block-size: 2.5rem; }
|
|
@@ -160,11 +157,8 @@
|
|
|
160
157
|
|
|
161
158
|
/* A checkbox box and a switch track beside their real labels. */
|
|
162
159
|
.starci-core-field-skeleton-control[data-grammar-field-skeleton="choice"] { flex: none; block-size: 1rem; inline-size: 1rem; }
|
|
163
|
-
.starci-core-field-skeleton-control[data-grammar-field-skeleton="choice"] > .starci-core-skeleton { border-radius: 0.25rem; }
|
|
164
160
|
.starci-core-field-skeleton-control[data-grammar-field-skeleton="switch"] { flex: none; block-size: 1.25rem; inline-size: 2rem; }
|
|
165
|
-
.starci-core-field-skeleton-control[data-grammar-field-skeleton="switch"]
|
|
166
|
-
.starci-core-field-skeleton-control[data-grammar-field-skeleton="switch"][data-grammar-switch-size="lg"] { block-size: 2.25rem; inline-size: 4rem; }
|
|
167
|
-
.starci-core-field-skeleton-control[data-grammar-field-skeleton="switch"][data-grammar-switch-size="control"] { block-size: var(--starci-core-control-min-size, 2.75rem); inline-size: 4.875rem; }
|
|
161
|
+
.starci-core-field-skeleton-control[data-grammar-field-skeleton="switch"][data-grammar-switch-size="lg"] { block-size: 1.5rem; inline-size: 3rem; }
|
|
168
162
|
|
|
169
163
|
.starci-core-field-skeleton-choice-label {
|
|
170
164
|
color: var(--foreground, CanvasText);
|
|
@@ -210,8 +204,11 @@
|
|
|
210
204
|
.starci-core-number-field-group,
|
|
211
205
|
.starci-core-date-group {
|
|
212
206
|
box-sizing: border-box;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.starci-core-input-field,
|
|
210
|
+
.starci-core-combo-box-group {
|
|
213
211
|
min-block-size: var(--starci-core-field-min-height, 2.5rem);
|
|
214
|
-
border-radius: var(--field-radius, calc(var(--radius, 0.5rem) * 1.5));
|
|
215
212
|
}
|
|
216
213
|
|
|
217
214
|
/* Owner 2026-10-25: Select has the same 2.5rem field height as Input. */
|
|
@@ -227,8 +224,7 @@
|
|
|
227
224
|
* are never both outlined. The frame keeps the ring for every way focus arrives (`:focus-within`), so keyboard
|
|
228
225
|
* focus stays visible; forced-colors draws it as a system outline on the same frame.
|
|
229
226
|
*/
|
|
230
|
-
|
|
231
|
-
outline: none;
|
|
227
|
+
.starci-core-combo-box-input:is(:focus, :focus-visible, [data-focused="true"], [data-focus-visible="true"]) {
|
|
232
228
|
box-shadow: none;
|
|
233
229
|
}
|
|
234
230
|
|
|
@@ -250,13 +246,11 @@
|
|
|
250
246
|
box-sizing: border-box;
|
|
251
247
|
flex: 1 1 0;
|
|
252
248
|
border-radius: inherit;
|
|
253
|
-
padding-inline: 0.75rem 1.75rem;
|
|
254
249
|
text-overflow: ellipsis;
|
|
255
250
|
}
|
|
256
251
|
|
|
257
252
|
.starci-core-combo-box-trigger {
|
|
258
253
|
inset-inline-end: 0;
|
|
259
|
-
padding-inline-end: 0.5rem;
|
|
260
254
|
}
|
|
261
255
|
|
|
262
256
|
.starci-core-date-input {
|
|
@@ -266,8 +260,6 @@
|
|
|
266
260
|
|
|
267
261
|
.starci-core-date-range-separator {
|
|
268
262
|
flex-shrink: 0;
|
|
269
|
-
padding-inline: 0.25rem;
|
|
270
|
-
color: var(--muted, GrayText);
|
|
271
263
|
}
|
|
272
264
|
|
|
273
265
|
/* --- List popover (Select, ComboBox) ---
|
|
@@ -315,55 +307,7 @@
|
|
|
315
307
|
}
|
|
316
308
|
|
|
317
309
|
/*
|
|
318
|
-
*
|
|
319
|
-
* `lg`: a 4rem by 2.25rem fully round track, a thumb the track height less 0.5rem inset 0.25rem, an optional glyph centred in the
|
|
320
|
-
* thumb. `control`: the same shape at the shared control height (2.75rem), so a theme switch lines up with the IconButtons and the
|
|
321
|
-
* avatar of a bar. Keyed on the stamps the component emits (`data-grammar-switch-size`, `data-grammar-switch-thumb`,
|
|
322
|
-
* `data-grammar-switch-icon`), never on vendor class names. The geometry is `!important` because consumers import this sheet on
|
|
323
|
-
* either side of `@heroui/styles`, so layer rank cannot decide against the vendor `.switch--*` size rules. The on position is a
|
|
324
|
-
* margin (as HeroUI's own thumb), the percentage resolving against the track: 100% - thumb - inset.
|
|
325
|
-
*/
|
|
326
|
-
[data-component="Switch"][data-grammar-switch-size="lg"] {
|
|
327
|
-
--grammar-switch-height: 2.25rem;
|
|
328
|
-
--grammar-switch-width: 4rem;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
[data-component="Switch"][data-grammar-switch-size="control"] {
|
|
332
|
-
--grammar-switch-height: var(--starci-core-control-min-size, 2.75rem);
|
|
333
|
-
--grammar-switch-width: 4.875rem;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
[data-component="Switch"]:is([data-grammar-switch-size="lg"], [data-grammar-switch-size="control"]) {
|
|
337
|
-
--grammar-switch-thumb: calc(var(--grammar-switch-height) - 0.5rem);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
[data-component="Switch"]:is([data-grammar-switch-size="lg"], [data-grammar-switch-size="control"]) [data-grammar-choice-control="switch"] {
|
|
341
|
-
block-size: var(--grammar-switch-height) !important;
|
|
342
|
-
inline-size: var(--grammar-switch-width) !important;
|
|
343
|
-
border-radius: 9999px !important;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
[data-component="Switch"]:is([data-grammar-switch-size="lg"], [data-grammar-switch-size="control"]) [data-grammar-switch-thumb] {
|
|
347
|
-
block-size: var(--grammar-switch-thumb) !important;
|
|
348
|
-
inline-size: var(--grammar-switch-thumb) !important;
|
|
349
|
-
border-radius: 9999px !important;
|
|
350
|
-
margin-inline-start: 0.25rem !important;
|
|
351
|
-
align-items: center;
|
|
352
|
-
justify-content: center;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
[data-component="Switch"]:is([data-grammar-switch-size="lg"], [data-grammar-switch-size="control"]):is([data-selected="true"], [aria-checked="true"]) [data-grammar-switch-thumb] {
|
|
356
|
-
margin-inline-start: calc(100% - var(--grammar-switch-thumb) - 0.25rem) !important;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/* The description and error align under the label, past the wider track. */
|
|
360
|
-
[data-component="Switch"]:is([data-grammar-switch-size="lg"], [data-grammar-switch-size="control"]) > :is([data-slot="description"], [data-slot="field-error"]) {
|
|
361
|
-
padding-inline-start: calc(var(--grammar-switch-width) + 0.75rem);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/*
|
|
365
|
-
* The thumb glyph box is the canon icon size, not whatever the vendor's thumb container leaves: 20px (size-5, `Icon` `leading`) on `lg`
|
|
366
|
-
* and `control`, 16px (`chip`) on `md`, whose thumb is 1rem tall. The glyph fills its box, centred in the thumb.
|
|
310
|
+
* The thumb glyph box is the canon icon size: 20px (size-5, `Icon` `leading`) on `lg`, 16px (`chip`) on `md`. The glyph fills its box, centred in the thumb.
|
|
367
311
|
*/
|
|
368
312
|
.starci-core-switch-icon {
|
|
369
313
|
display: inline-flex;
|
|
@@ -404,8 +348,6 @@
|
|
|
404
348
|
|
|
405
349
|
.starci-core-slider-output {
|
|
406
350
|
color: var(--muted, GrayText);
|
|
407
|
-
font-size: 0.875rem;
|
|
408
|
-
font-variant-numeric: tabular-nums;
|
|
409
351
|
}
|
|
410
352
|
|
|
411
353
|
/* --- SegmentedControl --- */
|
|
@@ -459,10 +401,6 @@
|
|
|
459
401
|
width: 100%;
|
|
460
402
|
margin: 0;
|
|
461
403
|
padding: 0;
|
|
462
|
-
color: var(--foreground, CanvasText);
|
|
463
|
-
font-size: 1rem;
|
|
464
|
-
font-weight: 700;
|
|
465
|
-
line-height: 1.3;
|
|
466
404
|
}
|
|
467
405
|
|
|
468
406
|
.starci-core-fieldset-legend + * {
|
|
@@ -564,11 +502,6 @@
|
|
|
564
502
|
overflow-wrap: anywhere;
|
|
565
503
|
}
|
|
566
504
|
|
|
567
|
-
/* --- Read-only reads as settled, not as unavailable --- */
|
|
568
|
-
[data-grammar-field="true"][data-grammar-readonly="true"] :where(.starci-core-combo-box-group, .starci-core-search-field-group, .starci-core-number-field-group, .starci-core-date-group, .starci-core-textarea-control) {
|
|
569
|
-
background: var(--surface-secondary, var(--field-background, Canvas));
|
|
570
|
-
}
|
|
571
|
-
|
|
572
505
|
/*
|
|
573
506
|
* THE 44px TOUCH FLOOR.
|
|
574
507
|
*
|
|
@@ -1,13 +1,42 @@
|
|
|
1
|
-
/* PADDING-0:
|
|
1
|
+
/* PADDING-0: panel list boxes share the field and tabs edge; HeroUI owns list and item padding. */
|
|
2
2
|
@layer starci-grammar-common {
|
|
3
3
|
.grammar-common-root .starci-core-list-box[data-grammar-list-inset="panel"] {
|
|
4
|
-
|
|
5
|
-
inline
|
|
6
|
-
margin-inline: -0.5rem;
|
|
7
|
-
padding-inline: 0 !important;
|
|
4
|
+
inline-size: 100%;
|
|
5
|
+
margin-inline: 0;
|
|
8
6
|
}
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
/* owner:item-description-one-line: clamp the vendor Description slot, preserving its text and paint. */
|
|
9
|
+
.grammar-common-root [data-slot="description"][data-grammar-item-description="true"] {
|
|
10
|
+
display: -webkit-box;
|
|
11
|
+
-webkit-box-orient: vertical;
|
|
12
|
+
-webkit-line-clamp: 1;
|
|
13
|
+
line-clamp: 1;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
white-space: normal;
|
|
16
|
+
text-overflow: ellipsis;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.grammar-common-root [data-slot="description"][data-grammar-description-lines="2"] {
|
|
20
|
+
-webkit-line-clamp: 2;
|
|
21
|
+
line-clamp: 2;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.grammar-common-root [data-slot="description"][data-grammar-description-lines="3"] {
|
|
25
|
+
-webkit-line-clamp: 3;
|
|
26
|
+
line-clamp: 3;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.grammar-common-root [data-grammar-sidebar-copy="true"] {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex: 1;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
min-width: 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.grammar-common-root [data-grammar-item-label="true"] {
|
|
37
|
+
max-inline-size: 100%;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
white-space: nowrap;
|
|
40
|
+
text-overflow: ellipsis;
|
|
12
41
|
}
|
|
13
42
|
}
|