@nadicodeai/design-system 12.1.102 → 12.1.103
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/DESIGN.md +459 -342
- package/dist/css/host.css +45 -36
- package/dist/css/index.css +52 -71
- package/dist/css/tokens.css +44 -35
- package/dist/tailwind/nadicode.tailwind.json +10 -6
- package/dist/tokens/nadicode.dtcg-resolved.json +306 -190
- package/dist/tokens/nadicode.dtcg.json +306 -190
- package/package.json +2 -1
package/DESIGN.md
CHANGED
|
@@ -156,10 +156,10 @@ colors:
|
|
|
156
156
|
dark-canvas-soft-2: "#1a1a1a"
|
|
157
157
|
dark-material-workspace: "#000000"
|
|
158
158
|
dark-material-solid: "#000000"
|
|
159
|
-
dark-material-resting: "#
|
|
160
|
-
dark-material-raised: "#
|
|
161
|
-
dark-material-floating: "#
|
|
162
|
-
dark-material-modal: "#
|
|
159
|
+
dark-material-resting: "#0c0c0c"
|
|
160
|
+
dark-material-raised: "#111111"
|
|
161
|
+
dark-material-floating: "#151515"
|
|
162
|
+
dark-material-modal: "#151515"
|
|
163
163
|
dark-ink: "#ededed"
|
|
164
164
|
dark-body: "#a1a1a1"
|
|
165
165
|
dark-muted: "#9e9e9e"
|
|
@@ -366,13 +366,13 @@ typography:
|
|
|
366
366
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
367
367
|
fontSize: 16px
|
|
368
368
|
fontWeight: 500
|
|
369
|
-
lineHeight:
|
|
369
|
+
lineHeight: 24px
|
|
370
370
|
letterSpacing: 0px
|
|
371
371
|
button:
|
|
372
372
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
373
373
|
fontSize: 14px
|
|
374
374
|
fontWeight: 500
|
|
375
|
-
lineHeight:
|
|
375
|
+
lineHeight: 21px
|
|
376
376
|
letterSpacing: 0px
|
|
377
377
|
button-xs:
|
|
378
378
|
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
|
|
@@ -480,6 +480,7 @@ typography:
|
|
|
480
480
|
rounded:
|
|
481
481
|
none: 0px
|
|
482
482
|
xs: 2px
|
|
483
|
+
xs-plus: 4px
|
|
483
484
|
sm: 6px
|
|
484
485
|
md: 8px
|
|
485
486
|
lg: 12px
|
|
@@ -510,6 +511,9 @@ spacing:
|
|
|
510
511
|
control-height-lg: 40px
|
|
511
512
|
control-height-xs: 24px
|
|
512
513
|
control-padding-inline: 12px
|
|
514
|
+
button-padding-inline-sm: 6px
|
|
515
|
+
button-padding-inline: 10px
|
|
516
|
+
button-padding-inline-lg: 14px
|
|
513
517
|
card-padding: 20px
|
|
514
518
|
touch-target: 44px
|
|
515
519
|
|
|
@@ -523,7 +527,7 @@ nadicode puts AI Agents to work inside small and mid-sized companies. Its sites
|
|
|
523
527
|
|
|
524
528
|
- **Neutral structure.** Chrome, controls and text sit on an achromatic spine, so a desaturated screen loses nothing structural. The strongest contrast on a screen belongs to the action.
|
|
525
529
|
- **Colour as stage.** The five identity hues appear at full strength only in the places "Colour as stage" lists, the colour of Agents among them, and never as a section's ground. They carry the brand; they never decorate a control. Semantic colour identifies statuses, categories and named actions through the component palette below.
|
|
526
|
-
- **Real depth.** Surfaces sit at four heights.
|
|
530
|
+
- **Real depth.** Surfaces sit at four heights. In light, an edge and shadows that grow with the height show it; in dark, each height is a step lighter, lit along its top edge. Glass floats over content that scrolls or moves under it.
|
|
527
531
|
|
|
528
532
|
The products are still: only Agents move on their own. The website moves with purpose: the product at work, Agents and its few shader objects ("Motion").
|
|
529
533
|
|
|
@@ -543,9 +547,10 @@ The neutral spine carries grounds, chrome, text and every control: `{colors.ink}
|
|
|
543
547
|
|
|
544
548
|
- **Action** (`{colors.action}`, `{colors.action-foreground}`, `{colors.action-hover}`, `{colors.action-active}`): the primary control is ink with a white label in light, and dark ink `{colors.dark-action}` with a near-black `{colors.dark-action-foreground}` label in dark, never pure white. The shadcn `primary` role maps here.
|
|
545
549
|
- **Text**: `{colors.ink}` for headings and primary text, `{colors.body}` for supporting text, which clears AA on every canvas. `{colors.muted}` is for placeholders and disabled or inactive text only, never for descriptions, labels or help. These roles distinguish purpose, not a guaranteed contrast step: their similar neutrals keep supporting text and placeholders near the Geist reference while both meet our AA text floor.
|
|
546
|
-
- **Lines**: `{colors.line}` is the one decorative 1 px divider and is deliberately quiet. `{colors.input}` is the boundary of a field or any control whose edge identifies it (an input, a select, a checkbox, a radio), and clears the 3:1 non-text floor. A button is identified by its label, so an outline or secondary button's edge is the `{colors.line}` hairline, never `{colors.input}`. Never darken a decorative line locally to make it act as a control edge.
|
|
550
|
+
- **Lines**: `{colors.line}` is the one decorative 1 px divider and is deliberately quiet. `{colors.input}` is the boundary of a field or any control whose edge identifies it (an input, a select, a checkbox, a radio), and clears the 3:1 non-text floor. A button is identified by its label, so an outline or secondary button's edge is the `{colors.line}` hairline, never `{colors.input}`. Never darken a decorative line locally to make it act as a control edge. Each border is drawn once: a divider sits inside the border of the surface that holds it and never doubles an edge where the two meet.
|
|
547
551
|
- **Focus** (`{colors.focus-ring}`): a full-opacity outline of `{spacing.focus-outline-width}` at `{spacing.focus-outline-offset}`, the maximum-contrast neutral on each ground, never a box-shadow ring and never a hue.
|
|
548
|
-
- **
|
|
552
|
+
- **Blue on a choice** is info and appears only where Geist puts it: the on switch, the filled part of a slider, and a selected choice tile (border, tint, words, corner mark). Checkbox, radio, segmented control and toggle group stay neutral, and a disabled switch or slider fill turns grey, never a faded blue.
|
|
553
|
+
- **Interaction states** are contrast steps on the spine. Hover takes the `accent` role (`{colors.canvas-soft-2}`) and a selected row the `muted` role (`{colors.canvas-soft}`); a control's own hover is a step inside its family, as `{colors.action-hover}` is. Persistent navigation marks the current destination with `{colors.navigation-selection-bg}` and `{colors.navigation-selection-fg}`, and local tabs mark the current view with the same pair through the `selection` role. A segmented choice, `SegmentedControl` and the theme switcher's tiles, marks its chosen option with that pair too (with the resting elevation), and the fill never comes without its foreground: on the `selection` ground, a radio's on-primary label reads white on near-white in light and black on black in dark.
|
|
549
554
|
- **Scrim** (`{colors.scrim}`): the modal overlay, black in both themes at the `scrim-opacity` material value, never blurred: the page behind steps back and the panel in front keeps its full contrast; an overlay never greys the page.
|
|
550
555
|
|
|
551
556
|
### Colour as stage
|
|
@@ -608,9 +613,9 @@ Every chart and KPI card is a stock shadcn registry component owned by `@nadicod
|
|
|
608
613
|
- A multi-series chart has a legend below the plot, left-aligned and wrapping: a round dot and the entity name, in series order.
|
|
609
614
|
- A signed comparison keeps a visible zero line so losses and gains share one baseline, and colours each bar by its consequence: `success` where the value is favourable, `destructive` where it is not.
|
|
610
615
|
- A chart is a named section: its card title is the heading that names the plot.
|
|
611
|
-
- Every chart card has one header, the same on every page (`ChartCard`): its title and its period on the left ("Usage", "Per day · today is partial"), its controls, such as the metric switch, on the right. The period's choice sits on the page's title row where the page has one. The footer holds the reading time on the left, "Read at 12:42", and
|
|
616
|
+
- Every chart card has one header, the same on every page (`ChartCard`): its title and its period on the left ("Usage", "Per day · today is partial"), its controls, such as the metric switch, on the right, then the way to its owner as a small ghost link ending in a chevron, as OpenRouter's "Explore ›" ("Explore", or "Open in Analytics" when the owner is another page), which stays top right on a phone. The period's choice sits on the page's title row where the page has one. The footer holds the reading time on the left, "Read at 12:42", and at most a command on the reading on the right, such as Refresh. A daily axis labels every second day from the first, fewer in a half-width card, and the y axis five round ticks. A ranked list beside a chart is one line per entity (place, colour, name, share, figure), so it never stands taller than the chart; a category axis is as wide as its longest name up to 128 px, a longer name wrapping to a second line; a short window's activity calendar draws larger cells and shares its row with a sibling card, never a lone narrow card.
|
|
612
617
|
|
|
613
|
-
No pie, donut, radar
|
|
618
|
+
No pie, donut, radar or dual-axis chart, and no mark or logo inside a legend. The one ring is `Gauge`, a control for a single ratio out of 100 against a fixed maximum, not a chart.
|
|
614
619
|
|
|
615
620
|
### Palette and assignment
|
|
616
621
|
|
|
@@ -628,7 +633,8 @@ A hue follows its entity, never its rank or position: one assignment per surface
|
|
|
628
633
|
|
|
629
634
|
### Meters, deltas and labels
|
|
630
635
|
|
|
631
|
-
- **Meter**: the stock `Progress` in one tone, default, warning or critical, with an accessible name and the real value printed beside it. Over its cap it is a full bar in the critical tone; the printed figure states the overage.
|
|
636
|
+
- **Meter**: the stock `Progress` in one tone, default, secondary, success, warning or critical, with an accessible name and the real value printed beside it; `stops` mark genuine stages, each named. Over its cap it is a full bar in the critical tone; the printed figure states the overage.
|
|
637
|
+
- **Gauge**: a ring for one ratio out of 100 where the comparison is the point (a hit rate, an uptime), in one product-chosen tone from the same set, with an adjacent label that names the measure and carries the unit. Its figure is the bare number, never a percent sign. It has no indeterminate form: an unknown wait is the waiting line.
|
|
632
638
|
- **Delta**: an outline Badge with a trend icon (`TrendingUp`, `TrendingDown`, `Minus`) and the signed value, followed by a muted "vs {period}". Direction crossed with whether up is good sets the tone; a neutral direction stays neutral. Never bare signed text, colour alone, or a ▲▼ glyph. A figure with no comparison shows no badge.
|
|
633
639
|
- **Labels**: legend, axis and label text are ink roles and never wear the series colour. A single series is titled, not legended. Tooltips enhance a chart and never hold the only copy of a value; where a page needs the numbers as text, it shows a real table built from the same data.
|
|
634
640
|
|
|
@@ -648,27 +654,27 @@ Geist and Geist Mono are the two families. The role scale follows the measured [
|
|
|
648
654
|
| `{typography.heading-sm}` | 20 / 26 px | Card, settings section or dialog title. |
|
|
649
655
|
| `{typography.heading-xs}` | 16 / 24 px | Compact card or group title. |
|
|
650
656
|
| `{typography.heading-compact}` | 14 / 20 px | Dense subsection title. |
|
|
651
|
-
| `{typography.button-lg}` | 16 /
|
|
652
|
-
| `{typography.button}` | 14 /
|
|
653
|
-
| `{typography.button-xs}` | 12 / 16 px |
|
|
654
|
-
| `{typography.label-display}` | 20 / 32 px | Large single-line label. |
|
|
655
|
-
| `{typography.label-lg}` | 18 / 20 px | Prominent single-line label. |
|
|
656
|
-
| `{typography.label-md}` | 16 / 20 px | Object or item label. |
|
|
657
|
-
| `{typography.label}` | 14 / 20 px | Menu, navigation and field label. |
|
|
658
|
-
| `{typography.label-sm}` | 13 / 16 px |
|
|
657
|
+
| `{typography.button-lg}` | 16 / 24 px | Large button label. |
|
|
658
|
+
| `{typography.button}` | 14 / 21 px | Default and small button label, only inside a component that renders a button. |
|
|
659
|
+
| `{typography.button-xs}` | 12 / 16 px | Label of a tiny button inside a field, nowhere else. |
|
|
660
|
+
| `{typography.label-display}` | 20 / 32 px | Large single-line label beside an icon. |
|
|
661
|
+
| `{typography.label-lg}` | 18 / 20 px | Prominent single-line label beside an icon. |
|
|
662
|
+
| `{typography.label-md}` | 16 / 20 px | Object or item label on one line. |
|
|
663
|
+
| `{typography.label}` | 14 / 20 px | Menu, navigation and field label on one line beside an icon. |
|
|
664
|
+
| `{typography.label-sm}` | 13 / 16 px | The secondary line under a label, with tabular digits. |
|
|
659
665
|
| `{typography.caption}` | 12 / 16 px | Tertiary label or badge. |
|
|
660
|
-
| `{typography.label-mono-lg}` | 14 / 20 px | Mono beside
|
|
661
|
-
| `{typography.label-mono-md}` | 13 / 20 px | Mono beside 14 px
|
|
662
|
-
| `{typography.label-mono}` | 12 / 16 px | Compact identifier
|
|
666
|
+
| `{typography.label-mono-lg}` | 14 / 20 px | Mono beside text larger than 14 px; a default `Kbd`. |
|
|
667
|
+
| `{typography.label-mono-md}` | 13 / 20 px | Mono beside 14 px text. |
|
|
668
|
+
| `{typography.label-mono}` | 12 / 16 px | Compact identifier; a `sm` `Kbd`. |
|
|
663
669
|
| `{typography.body-display}` | 24 / 36 px | Large marketing lead. |
|
|
664
670
|
| `{typography.body-lead}` | 20 / 36 px | Marketing lead. |
|
|
665
671
|
| `{typography.body-lg}` | 18 / 28 px | Long lead or quotation. |
|
|
666
|
-
| `{typography.body-md}` | 16 / 24 px |
|
|
667
|
-
| `{typography.body-sm}` | 14 / 20 px |
|
|
668
|
-
| `{typography.body-compact}` | 13 / 18 px |
|
|
672
|
+
| `{typography.body-md}` | 16 / 24 px | Copy for roomy views: dialogs and entry instructions. |
|
|
673
|
+
| `{typography.body-sm}` | 14 / 20 px | The default for multi-line copy and product descriptions. |
|
|
674
|
+
| `{typography.body-compact}` | 13 / 18 px | Tight secondary copy. |
|
|
669
675
|
| `{typography.code}` | 13 / 18 px | Inline code or code block. |
|
|
670
676
|
|
|
671
|
-
A token has one size at every width; nothing is sized in `vw` or `vh`. A role includes family, size, line height, weight and tracking together. Use the shared `nc-type-*` classes or the generated `text-<token>` utilities, such as `text-display-md`, with `font-label-mono` for the `label-mono` family and `font-code` for `code`, rather than assembling role metrics at a call site. Existing `text-xs`, `text-sm` and `text-base` body sizes match `caption`, `body-sm` and `body-md`. Card, panel and section titles are sentence-case Geist. Headings use weight 600 and their optical negative tracking. A softer run inside a heading uses 500; a strong run inside a label uses 500; strong paragraph copy uses 550. Labels align single lines and icons; paragraphs use the copy roles and can wrap. Headings and the heading and display roles wrap balanced, so no line of a title is left short; copy wraps pretty, so a paragraph never ends on a lone word; centred copy wraps balanced, whatever its role. The type layer applies this, Nadia's skin takes it with the roles and Alveare's type adapter with its type steps, so a screen sets text wrapping only to depart from it. Numeric comparisons use tabular digits, and identifiers use mono. Semantic heading levels express document structure independently of visual size. Never shrink type to fit: wrap, reflow or move supporting detail.
|
|
677
|
+
A token has one size at every width; nothing is sized in `vw` or `vh`. A role includes family, size, line height, weight and tracking together. Use the shared `nc-type-*` classes or the generated `text-<token>` utilities, such as `text-display-md`, with `font-label-mono` for the `label-mono` family and `font-code` for `code`, rather than assembling role metrics at a call site. Existing `text-xs`, `text-sm` and `text-base` body sizes match `caption`, `body-sm` and `body-md`. Card, panel and section titles are sentence-case Geist. Headings use weight 600 and their optical negative tracking. A softer run inside a heading uses 500; a strong run inside a label uses 500; strong paragraph copy uses 550. A softer or stronger run is made by nesting a `<strong>` under the type role, whether the role is written as `nc-type-<role>` or as the `text-<role>` utility; a second weight class on the `<strong>` is never added. Labels align single lines and icons; paragraphs use the copy roles and can wrap. Headings and the heading and display roles wrap balanced, so no line of a title is left short; copy wraps pretty, so a paragraph never ends on a lone word; centred copy wraps balanced, whatever its role. The type layer applies this, Nadia's skin takes it with the roles and Alveare's type adapter with its type steps, so a screen sets text wrapping only to depart from it. Numeric comparisons use tabular digits, and identifiers use mono. Semantic heading levels express document structure independently of visual size. Never shrink type to fit: wrap, reflow or move supporting detail.
|
|
672
678
|
|
|
673
679
|
### The website's text
|
|
674
680
|
|
|
@@ -714,19 +720,21 @@ Where a picture may stand:
|
|
|
714
720
|
|
|
715
721
|
## Layout
|
|
716
722
|
|
|
717
|
-
Every gap, pad and stack step a page, section or composition sets is a rung of the spacing ladder, `{spacing.xxs}` 4 px through `{spacing.6xl}` 128 px; a layout picks the rungs it needs and never interpolates between them. Inside a component, the stock shadcn registry's own spacing stands. Every visible line has one owner: a seam is `{spacing.guide}` in `{colors.line}`, a control edge is `{colors.
|
|
723
|
+
Every gap, pad and stack step a page, section or composition sets is a rung of the spacing ladder, `{spacing.xxs}` 4 px through `{spacing.6xl}` 128 px; a layout picks the rungs it needs and never interpolates between them. Inside a component, the stock shadcn registry's own spacing stands. Every visible line has one owner: a seam is `{spacing.guide}` in `{colors.line}`, a control edge is `{colors.line}`, a field's and a button's alike, and focus is the focus outline.
|
|
718
724
|
|
|
719
725
|
Control geometry is the same in every product:
|
|
720
726
|
|
|
721
727
|
| Token | Owns |
|
|
722
728
|
| --- | --- |
|
|
723
|
-
| `{spacing.control-height}` | The
|
|
724
|
-
| `{spacing.control-
|
|
729
|
+
| `{spacing.control-height}` | The default control, and every control in product chrome but a tab |
|
|
730
|
+
| `{spacing.control-height-xs}`, `{spacing.control-height-sm}`, `{spacing.control-height-lg}` | The 24, 32 and 40 px sizes a control and a field share |
|
|
731
|
+
| `{spacing.control-padding-inline}` | A field's inline padding (input, select, textarea, combobox, hover card) |
|
|
732
|
+
| `{spacing.button-padding-inline-sm}`, `{spacing.button-padding-inline}`, `{spacing.button-padding-inline-lg}` | A button's inline padding at its small, default and large size |
|
|
725
733
|
| `{spacing.touch-target}` | The minimum target on coarse or non-hover input, whatever the visual size |
|
|
726
734
|
| `{spacing.icon-stroke}`, `{spacing.icon-stroke-sm}` | The icon line ("Iconography") |
|
|
727
735
|
| `{spacing.focus-outline-width}`, `{spacing.focus-outline-offset}` | The focus outline |
|
|
728
736
|
|
|
729
|
-
Product chrome uses the 36 px control. Compact controls use 32 px and prominent controls 40 px; 24 px
|
|
737
|
+
Product chrome uses the 36 px control. Compact controls use 32 px and prominent controls 40 px; an embedded text button inside a field is 24 px (`InputGroupButton` `xs`); an embedded icon button fills the field's row and sits flush against its edge, except the combobox's open-list button, which is 30 px high and centred at the default size and fills the row at 32 and 40 px, as in Geist. A page header, a toolbar, a card's header and footer, a filter row and a collection row's actions take `{spacing.control-height}` with a `{typography.button}` label, and so does the three-dot trigger, wherever it stands; a button's `sm` and `xs` sizes are for a control nested inside dense content, such as a notice's or a banner's one action, a descriptive item's trailing controls, a composer or an input group, and never for chrome. A `SegmentedControl` has options 24, 28 or 32 px high (`{spacing.control-height-xs}`, 28 px, `{spacing.control-height-sm}`) inside a 4 px padded track, so the control itself is 32, 36 or 40 px high like every other control.
|
|
730
738
|
|
|
731
739
|
### The website column
|
|
732
740
|
|
|
@@ -748,9 +756,10 @@ The Portal, Nadia and Alveare are product shells: persistent navigation on the l
|
|
|
748
756
|
| Getting the app | Above the account | Downloads, an outlined row | The update card, only when there is one | The update card |
|
|
749
757
|
| The page's actions | The page's title row | Secondary, primary, the three dots | The window header's trailing edge: the Agent's three dots, after the chat switcher | The channel header's trailing edge |
|
|
750
758
|
|
|
751
|
-
- **The sidebar swaps, and is never joined by a second.** Inside an object, the
|
|
759
|
+
- **The sidebar swaps, and is never joined by a second.** Inside an object, the same column shows a back link, what you are in (its identity mark at 24 px and its name) and its sections, and the top bar keeps the path (`SidebarSections`). No rail, second column or tab row of an object's sections appears beside it. In the Portal an Agent is the exception, because she is a deployment: the sidebar stays on the places, and her sections stand as the `TabsNav` band under the top bar, as Vercel draws a deployment's tabs, at most six (Overview, Scheduled tasks, Usage, Capabilities, Messaging, Settings); a tab that holds several sections opens on the first and shows them as line tabs at the top of its content. Her Overview is her `ObjectPage`: her facts, then rows of checks, each summed up by `CheckCounts` and closed by a `CheckState`.
|
|
760
|
+
- **An area whose pages are siblings opens as a sub-menu, as Vercel's sidebar does.** Vercel marks such a row with a › at its end ("Logs", "Observability", "Firewall", "Settings"), and its press replaces the places with one row, a ‹ at its start and the area's name centred, above the area's pages as words alone, the open one filled like a selected row; a row that only opens a page has no ›. In the Portal these areas are Settings (nadicode), Company (whoever manages a company) and Library (everyone who sees it: Agent templates, Skills, Plugins), each with its › row, and Account, opened from the account menu; their pages are never tabs (`SidebarSections` without an identity, its row ending in `SidebarMenuChevron`). “Tabs imply the views share scope, URL parent, and data model” (https://vercel.com/geist/tabs): Library's pages hold different objects with different lists and different ways to add, so they are a sub-menu, as Vercel's AI Gateway is. A destination whose pages are views of one reading, Analytics, keeps its tabs, as Vercel's Analytics and OpenRouter's Activity do. The ‹ returns to where the person opened the area from.
|
|
752
761
|
- **The top bar holds only the path, never an action.** It names where the open page sits, ending at the place or the object, and never the page's own title; an object's own status sits beside its name in the path and nowhere else on the page. A top bar that only says where you are cannot be mistaken for a toolbar.
|
|
753
|
-
- **Find goes to places.** It opens from the outlined field at the top of the sidebar and on ⌘K, and names every sidebar place, chat and settings page; it never runs a command.
|
|
762
|
+
- **Find goes to places.** It opens from the outlined field at the top of the sidebar and on ⌘K, and names every sidebar place, chat and settings page; it never runs a command. Its field names what it searches, never a bare "Search"; ⌘K or Ctrl+K opens it and no other field takes that binding; a shortcut on a row is a `CommandShortcut`; and a polite live region reads how many results remain as the person types.
|
|
754
763
|
- **The account lives at the sidebar's foot.** `AccountMenu` names who is signed in and for whom, opens the account's settings from its gear, and holds Theme, Language and Sign out; the offer to get or update the app stands just above it.
|
|
755
764
|
- **Navigation names stable destinations.** An object opened from search or a link still shows its parent in the path; a return link remembers a visit and never replaces the parent. A scope selector keeps the current section when the next object has it, and otherwise opens its overview.
|
|
756
765
|
- **Compact screens keep the same relationships.** Tabs scroll horizontally, primary content stacks before supporting facts, and no second sidebar appears.
|
|
@@ -762,7 +771,7 @@ The Portal, Nadia and Alveare are product shells: persistent navigation on the l
|
|
|
762
771
|
- **The company's pages**, Wiki and Skills, are rows under Scheduled tasks at the top of the list, each its own page with its own title and its actions on that title's row, never tabs under the company's name.
|
|
763
772
|
- **Scheduled tasks** is a place: one page of every Agent's scheduled work, each row with its Agent's orb, its schedule and its last or next run, failures first, filtered by Agent, with New task on the title row; a task opens for editing in its row. The row carries a red count of the tasks that failed (`SidebarMenuBadge tone="attention"`), so the person sees a failure before looking for it.
|
|
764
773
|
- **⋯ → Edit** stays as it is: it swaps the list to the Agent's Profile, Skills, Apps, MCP, Messaging, Plugins and Passwords. The chat switcher by her name stays as it is.
|
|
765
|
-
- **Settings** is what is set once rather than worked in: how the app behaves on this computer (its language, look, notifications, services and updates) and the company's Memory, Mail and Alveare. It opens from the account menu's
|
|
774
|
+
- **Settings** is what is set once rather than worked in: how the app behaves on this computer (its language, look, notifications, services and updates) and the company's Memory, Mail and Alveare. It opens from the account menu's gear and swaps the list to a back link to the Agents and its sections, each its own page: General, Appearance, Notifications, and the company's Memory, Mail and Alveare, then Updates; the account menu holds the gear in its header, then Usage (only once billing has answered with its page), Theme, Language and Sign out, and never a second Settings row.
|
|
766
775
|
- **The window header** is the Agent's title row: her orb and name, the chat switcher, then, on a chat, the side panel's toggle, and her three dots last (New chat, Edit, Open in Portal, Delete).
|
|
767
776
|
- **The side panel is opened, never pushed.** On a chat, the header's toggle opens the window's right side on the panel the person last chose: the Browser, or Artifacts, the images, documents and links in the Agent's chats, as Hermes names them, newest first, one opening large in their place. Its 44 px band names the panel, then the switch between the two, then ×; while she browses behind Artifacts or with the panel closed, the toggle and the switch's Browser carry a dot, and nothing moves by itself. × or Esc closes it and gives focus back to the toggle, while a page she is browsing keeps loading behind. Opened, it takes 44% of the window, held between 28rem and 48rem, and yields first: by its drag edge it narrows to 352 px and widens only as far as leaves the Agents list and 360 px of chat; under 1024 px it lies over the chat at the same width, without a drag edge. It is not a `Sheet`: it never blocks the chat, takes focus or dims the page.
|
|
768
777
|
- **The list narrows.** From 640 to 899 px it becomes a column of 48 px squares: Find, Scheduled tasks, Wiki and Skills, then the orbs, each named with its state line in a tooltip; under 640 px it leaves for a sheet the header's sidebar button opens.
|
|
@@ -776,16 +785,16 @@ A product page is one of five page compositions, each answering one question fir
|
|
|
776
785
|
| Composition | Owner | First answer | Structure |
|
|
777
786
|
| --- | --- | --- | --- |
|
|
778
787
|
| Overview | `OverviewPage` | What needs attention? | The period on the title row; the figures in one row of `KpiCard`s; the chart cards, each with its one header; then the exceptions that need a person, a `RecordList` with its heading, each row opening its owner. Never a stack of previews of every section. |
|
|
779
|
-
| Collection | `CollectionPage` | Which record? | The title with the page's actions on its row and nothing under it; the page's sibling collections as line tabs, when it has them; one toolbar (search, filters, sort); then one line per record (`RecordList`, "Tables and missing values"). One row is one hover and one open target. |
|
|
780
|
-
| Object | `ObjectPage` | What is this, what can I do? | The parent in the path and its sections in the sidebar; then the object's header
|
|
781
|
-
| Settings | `SettingsPage` | What can I change? |
|
|
782
|
-
| Library | `LibraryShelf` | What reusable thing can I use? |
|
|
788
|
+
| Collection | `CollectionPage` | Which record? | The title with the page's actions on its row and nothing under it; the page's sibling collections as line tabs, when it has them; one toolbar (search, filters, sort); then one line per record (`RecordList`, "Tables and missing values"). One row is one hover and one open target. The Portal's Agents are its exception, because an Agent is a deployment: they are Vercel's Deployments list, a `DataTable` with `rows="entities"` under the same title row and toolbar: no headings, one 72 px entity row per Agent (her orb at 32 and her name over her model, or over why she needs a look when she does; her status as a `StatusDot` and its word; her Customer as a `Tag`; her Installation in mono with its system's mark; when she last synced). Below the width those columns need, her status, her Customer, her Installation's name and that time stand in the one muted line under her name, so two Agents of one name on two machines stay told apart on a phone. A collection whose reader must also see what waits on them across all its records, as nadicode's Customers and Partners and a Partner's Customers do, takes a `rail`: under the toolbar, from 1280 px, a 300 px column of titled cards at the left of the records, as Vercel's Projects page stands Usage, Alerts and Recent Previews beside its projects; each card has its title above it at `{typography.heading-xs}`, an optional 44 px muted summary row whose one outline button stands at its end, never in a row of its own, then its items, 36 px for a figure (its title, its number at the trailing edge) and a 24 px mark over a title and a muted line that wraps to a second before it is cut, for a record, the item opening its record, or its `cleared` or `nothingYet` line, one 44 px row like an item (`EmptyState` `scope="line"`), never a tall empty tile. Beside a rail the records are Vercel's project rows (`RecordList` `layout="line"`), one line from a 448 px card: the 32 px mark and the name over its address, then the facts and the exception's status on one muted line joined by a middle dot ("5 of 5 Agents active · Partner Alpha"), left out first on a card under 576 px, then the time, the checklist ring and the three dots, which keep even a lone command; only on a phone do the facts and the time move under the name, as one muted line joined by middle dots in the same row, with no labels and no rule between them. Below 1280 px the records come first and the rail follows. The records' card takes no heading of its own: the page's title names it. |
|
|
789
|
+
| Object | `ObjectPage` | What is this, what can I do? | The parent in the path and its sections in the sidebar; then the object card, as Vercel's Deployment Details: a header bar with its name and, at the end, one secondary action, then the three dots, never a primary; under it its identity mark at 64 px centred in a 300 px tile on the muted ground, and beside it one optional line saying what it is and its key facts in a grid of four columns (two on phones), each a muted label over its value; then, in a card of its own 12 px under it, the rows that open one by one, chevron first and summary at the end (`CheckCounts`, `CheckState`, whose pass is a blue check); then its sections, each a card only where it owns a decision. An Agent is the exception: her first section, Profile, opens with her card, the same in every product (`AgentProfileCard`): on the left her orb at 64 px, her name with a ghost pencil that turns her name, description and, where the product holds it, her look into fields in place, saved by the card's own Save, with no drawer or overlay, her description, read whole and never cut, and her facts (status, last activity, the template she was made from); on the right her model, drawn with its maker's mark, her reasoning and, where the product holds them, her permissions, saved from the card's footer; her instructions follow as the next card. The page's commands sit in the window's three dots where the product has one, and otherwise at the end of her name's row. |
|
|
790
|
+
| Settings | `SettingsPage` | What can I change? | The page's title row, then section cards across the content width 24 px apart, each with its title and one-line description (the card's only help) and a label above each control; a card of choices applies each as it is made, and a card of typed values has its own Save in its footer. | The danger zone closes the page: transfer, pause, delete.
|
|
791
|
+
| Library | `LibraryShelf` for Agent templates; `CollectionPage` for Skills and Plugins | What reusable thing can I use? | Agent templates as Vercel's Templates gallery: the search, then `AgentCard`s three to a row. Skills and Plugins as an entity collection: the search and the category filter, then one row per entry (its picture or its kind's tile, its name over one line, who it is for and which Agents have it, Add, the three dots), staff's hub beside them as the collection's rail; detail shows content, requirements, source and revision, with Add as its filled primary. |
|
|
783
792
|
|
|
784
793
|
The pages share the parts below them, each with one owner: one line per record is `RecordList`, which `CollectionPage`, an overview's exceptions and an object's "Needs attention" section draw; an absence is `EmptyState` ("Elevation & Depth"); an overlay is the owner its job names ("Menus and commands"); what happened is `ActivityFeed` ("Activity"); a record's mark is `IdentityMark` ("Identity marks").
|
|
785
794
|
|
|
786
|
-
Every setting is that Settings composition, whether it belongs to the person, to the platform or to one record's Settings tab, so the column keeps its width and its field layout from one entry of a settings menu to the next, and each section saves its own fields from its own footer ("Cards and sections").
|
|
795
|
+
Every setting is that Settings composition, whether it belongs to the person, to the platform or to one record's Settings tab, so the column keeps its width and its field layout from one entry of a settings menu to the next, and each section saves its own fields from its own footer ("Cards and sections"). In the Portal the settings cards take the content's width under the page's title row, as every other page does and as Vercel's settings cards fill their column; Nadia keeps its settings column at most 42rem. The sections stand 24 px apart. Inputs are bounded at 20rem under their labels, and related fields may share two columns when the section can accommodate them. Section headings use heading-sm. The header and fields share one uninterrupted body; only the local save footer has a divider. A profile avatar is the upload button in the section header. Structured tables keep visible column names and remain tabular while their container can accommodate the data; only compact containers move supporting facts beneath the identity, and a matrix whose every column must stay, such as notification audiences by group, keeps them all and lets its names wrap instead.
|
|
787
796
|
|
|
788
|
-
Collections and working pages open with the same header (`PageHeader`), which the product's chrome or the composition's `title` draws. Settings pages open directly with their section cards and retain a screen-reader h1 for the destination; an extra visible title would duplicate the navigation and delay the first setting. The top bar holds only the path to the page ("Product shells"): its sidebar group or its parents, ending at the destination or the object, such as "Business › Agents" or "Beta Studio › Beta Desk", and never the page's own title. The content then starts with the title at `{typography.heading-md}`, on the left, and on the same row at the trailing edge the page's actions: an overview's period first, then at most one `outline` secondary action, then the `default` primary action, then the three dots at the trailing edge. `PageActions` is their only owner: it takes a `period`, a `secondary`, a `primary` and a `menu`, and draws their order and variants. The menu is data, the record it acts on and its commands, drawn by `ActionMenu`, and a page's three dots open only for two commands or more; one command is a button. An action always sits on the title of the thing it acts on, never on a tab's. Navigation remains a visible link or part of the navigation, never an overflow command. Nothing sits under the title: no line introduces, explains or counts the page, and the toolbar, the list or the page follows the title row directly.
|
|
797
|
+
Collections and working pages open with the same header (`PageHeader`), which the product's chrome or the composition's `title` draws. Settings pages open directly with their section cards and retain a screen-reader h1 for the destination; an extra visible title would duplicate the navigation and delay the first setting. The top bar holds only the path to the page ("Product shells"): its sidebar group or its parents, ending at the destination or the object, such as "Business › Agents" or "Beta Studio › Beta Desk", and never the page's own title. The content then starts with the title at `{typography.heading-md}`, on the left, and on the same row at the trailing edge the page's actions: an overview's period first, then at most one `outline` secondary action, then the `default` primary action, then the three dots at the trailing edge. On a phone the title keeps one action on its row, as Vercel's does; the actions wrap under the title only when they would leave it less than 128 px. `PageActions` is their only owner: it takes a `period`, a `secondary`, a `primary` and a `menu`, and draws their order and variants. The menu is data, the record it acts on and its commands, drawn by `ActionMenu`, and a page's three dots open only for two commands or more; one command is a button. An action always sits on the title of the thing it acts on, never on a tab's. Navigation remains a visible link or part of the navigation, never an overflow command. Nothing sits under the title: no line introduces, explains or counts the page, and the toolbar, the list or the page follows the title row directly. Inside an object worked from a section sidebar, the title is the section's name ("Apps"); a page that opens with the object's own header or card, such as an Agent's Profile (`AgentProfileCard`), has it as its title and no title row above it.
|
|
789
798
|
|
|
790
799
|
A collection is named once, by the page's title, and the collection's card never adds a header that only describes it. A populated collection carries no picture; its first use shows one, in every product ("Elevation & Depth"). The table's footer holds only a count or the paging, never a help sentence: guidance a step needs lives in that step.
|
|
791
800
|
|
|
@@ -795,44 +804,50 @@ A section earns a card when it owns a decision, not for every label and value. A
|
|
|
795
804
|
|
|
796
805
|
Product UI sits on one continuous workspace ground, `{colors.material-workspace}` (true black in dark), and solid objects rise above it at four heights: `nc-elevation-resting` for resting content, then `nc-elevation-raised`, `nc-elevation-floating` and `nc-elevation-modal` when an object is physically raised, floating or modal. Physical role chooses the height, never the importance of the content. Each recipe carries its own edge, so an elevated surface never adds a border, a ring or a second shadow.
|
|
797
806
|
|
|
798
|
-
**
|
|
807
|
+
**In light, shadows carry height** (the owner's adoption of the depth-and-glass board, 16 October 2026: [depth and glass](../../docs/adr/2026-09-23-the-nadicode-design-system/depth-and-glass.html)). Each recipe opens with the same 1 px edge, black at 8%, then a tight contact shadow where the surface touches the one below and a soft ambient shadow, pushed down with negative spread so it stays under the surface, that grows with each height: resting 8 px, raised 32 px, floating 64 px, modal 128 px of blur, at 5% to 26% black. Shadows stay black: a tinted shadow belongs only to a product view on a colour ground of the website.
|
|
799
808
|
|
|
800
|
-
**
|
|
809
|
+
**Only a tooltip has a stem.** A tooltip points at its trigger with a small triangle; no other floating surface (menu, popover, select, hover card, dialog) draws a pointer, so a surface that opens from a trigger is placed beside it with its offset alone.
|
|
810
|
+
|
|
811
|
+
**In dark, surfaces stay black and light carries height** (the owner's ruling of 16 October 2026: perspective, elevation and glass, never a grey surface). The page is `{colors.dark-canvas}`; each surface a small shade above it, as the depth-and-glass page steps them, and never past `{colors.dark-material-modal}`, well below the grey a large panel would read as: resting `{colors.dark-material-resting}`, raised `{colors.dark-material-raised}`, floating `{colors.dark-material-floating}`, modal `{colors.dark-material-modal}`. Height shows in light, not in a grey fill: a 1 px line of light along the top edge inside, a white hairline outside the surface where no header or footer of its own can cover it (14% on what floats, as Vercel's edges are), a black shadow under it, all stronger with each height; floating and modal surfaces are also lit from above, a white wash that fades out over their first 120 px, so a menu, a dialog or a drawer reads as lifted toward the light; glass on what floats over content. A field inside a surface is a darker well of it (that surface mixed 45% toward black) inside its edge, so every field stays visible; a footer or striped row is a quarter darker. The design-system checks fail a height darker than the one below it or past 1.16:1 against the page. `{colors.dark-ink}` and `{colors.dark-muted}` keep the WCAG AA text floor on the top step. Hover and selected fills step up from the surface they sit on. A component names only its height and its role (`bg-card`, `bg-popover`); `@nadicodeai/ui/globals.css` sets those roles to the height's tone on the element.
|
|
801
812
|
|
|
802
813
|
| Surface | Fill | Height | Use |
|
|
803
814
|
| --- | --- | --- | --- |
|
|
804
815
|
| Workspace | `{colors.material-workspace}` | None | The work area behind product objects. |
|
|
805
816
|
| Resting | `{colors.material-resting}` | `nc-elevation-resting` | Cards, KPIs, chart cards, tables, settings. The default. |
|
|
806
817
|
| Raised | `{colors.material-raised}` | `nc-elevation-raised` | Active or selected work, an attached inspector. |
|
|
807
|
-
| Floating | `{colors.material-floating}` | `nc-elevation-floating` |
|
|
818
|
+
| Floating | `{colors.material-floating}` | `nc-elevation-floating` | Tooltips and hover cards; menus, popovers, selects and toasts, which add glass. |
|
|
808
819
|
| Modal | `{colors.material-modal}` | `nc-elevation-modal` | Dialogs, sheets, drawers. |
|
|
809
820
|
| Outlined | `{colors.material-solid}` | None; one `line` border | A flat panel: fact cells inside a record, the website's explanatory cards. |
|
|
810
821
|
| Plain | `{colors.material-solid}` | None | A structural card with no edge of its own. |
|
|
811
822
|
|
|
812
|
-
**Glass** is a material, not a height: the floating fill at 60% over a 20 px backdrop blur at 180% saturation, so colour behind it comes through saturated rather than grey. Its edge
|
|
823
|
+
**Glass** is a material, not a height: the floating fill at 60% over a 20 px backdrop blur at 180% saturation, so colour behind it comes through saturated rather than grey. Its edge is the glass recipe (`nc-glass`): a line of light along the top, an inner hairline, an outer edge and the floating height's shadows, and a 5% monochrome grain keeps the blurred colour from banding. Glass goes on floating chrome, where something behind it moves or carries colour:
|
|
813
824
|
|
|
814
|
-
- floating chrome over our own content: popovers, selects, comboboxes, the
|
|
825
|
+
- floating chrome over our own content: menus, popovers, selects, comboboxes, the command palette, toasts and control bars, including a collection's toolbar over the rows that scroll under it (on a page whose rows never pass under it, the toolbar is the plain row, with no fill or edge of its own) and Nadia's chat bar over her conversation;
|
|
815
826
|
- the website header as the page scrolls under it;
|
|
816
827
|
- a small floating card over moving Agents.
|
|
817
828
|
|
|
818
|
-
Content stays solid: cards, KPIs, tables, chat, forms, and dialog, sheet and drawer bodies
|
|
829
|
+
Content stays solid: cards, KPIs, tables, chat, forms, and dialog, sheet and drawer bodies; a toast with a tone keeps its solid fill. A dropdown menu and a context menu are both glass, so one set of commands reached both ways looks the same both ways. Glass over a plain white or black ground shows nothing, so it never goes there. Reduced transparency and browsers without backdrop-filter replace glass with the same solid surface at the same height. Transparency never reduces the opacity of labels or controls.
|
|
819
830
|
|
|
820
831
|
**Product views on the website** preserve the real interface. Nadia uses captures of the running application, with the unchanged full-size image linked and capture provenance recorded in the repository, following the founder's 12 October correction of invented UI. Portal and Alveare may use inert scenes built from real components with fictional example data recorded in the repository. Never invent interface controls or frame a view in a device mockup. A product window takes the raised height on its ground; a card that overlaps it floats. Live components use dark mode in a black section; captures preserve the application's captured theme.
|
|
821
832
|
|
|
822
|
-
Absence follows its container, and only a first use has a picture. In every product, the Portal included, a collection's first use shows its section's picture, and
|
|
833
|
+
Absence follows its container, and only a first use has a picture. In every product, the Portal included, a collection's first use shows its section's picture, and every other kind of absence goes without one. A picture sits on a working screen only there: never in a populated collection, a row or any other card; whole-page moments keep theirs ("Entry screens"). A page or region absence is a resting card with its own edge, never a dashed boundary; an absence inside a card is unframed, because the card already owns the edge, and `CollectionPage` puts every absence it draws in its card. `EmptyState` (`@nadicodeai/ui/components/empty-state`) is the only owner of an absence: nothing else draws one (`empty-state-owner`), its `scope` (`page`, `region` or `card`) sets that frame, and it has no presentation option, so every product draws each kind the same way. A composition takes its absences as props (`empty`, `noMatch`, `failed`), as a `DataTable` takes `empty`. Its kind determines the cause it names, the mark or picture and the recovery:
|
|
834
|
+
|
|
835
|
+
- `firstUse`: a collection with no records yet, whoever the viewer is and however the collection fills. Its section's picture from the approved set in `@nadicodeai/design-system/assets/empty`, 240 × 176 on a page and 200 × 144 in a region or a card, which arrives once as it first renders ("Motion"); a title and one line saying what will live there; and, when this viewer can add the first record, the one action that adds it, as the filled primary button, beside an optional outline second path, as Vercel's Connect draws *Create Connector* beside *Browse Connectors* in its empty card; the page's title row keeps that same action as its filled primary whether the collection is empty or not. A create action carries the leading +. The set's pictures share one canvas, one ground line and one grammar, which [the art direction](../../skills/design/art-direction/references/surfaces.md#the-empty-state-set) keeps. One link to the product's documentation stands beside the action when the section has a page that explains it.
|
|
836
|
+
- `nothingYet`: a list that is empty now and fills by itself. One line, no picture, nothing to press.
|
|
837
|
+
- `noResults`: a search or filter that matches nothing. One line and Clear filters (or Clear search), no picture. A single typed query is quoted in curly quotes.
|
|
838
|
+
- `cleared`: work that is finished. The success mark and one line.
|
|
839
|
+
- `denied`: this viewer's role or plan does not open the page or region. The lock mark, a title (a heading), one line naming the feature and, when the plan gates it, the plan, and the one way out. One gated tile inside an open page is a `MessageNotice`, never a `denied`.
|
|
840
|
+
- `failed`: a read that failed where content would be. The warning mark, the message's title and body, at most two controls with Retry first, and, for a failure on our side, its identifier in a collapsed disclosure, in monospace, with a copy button. A failure that fills a page moves focus to its first control. A card-sized failure is `failed` with `scope="card"`; there is no `ErrorCard`.
|
|
823
841
|
|
|
824
|
-
|
|
825
|
-
- `nothingYet`: a list whose kind has no picture of its own, such as invoices or history, or a table inside a page. One line, with no picture and nothing to press.
|
|
826
|
-
- `noResults`: a search or filter that matches nothing. One line and Clear filters (or Clear search), with no picture.
|
|
827
|
-
- `failed`: a read that failed where content would be. The warning mark, the message's title and body, and its controls, Retry among them.
|
|
842
|
+
The quiet lines (`nothingYet`, `noResults`, `cleared`) carry no live role of their own: the wrapper that stays mounted while rows and absence swap announces them, once.
|
|
828
843
|
|
|
829
|
-
A persistent notice sits in the section it concerns, action feedback is a toast, and field validation stays with its field. A notice, a failed read, a confirmation's error and a toast each show a message its product's catalogue worded, never a sentence written where it shows: `MessageNotice` under the control whose write failed (`action`) or atop the section it concerns (`section`), `EmptyState` `failed`, `ConfirmDialog`'s error and the toast. Each wraps a long word, never truncates, and shows a body only when it says more than the title ([the decision](../../docs/adr/2026-10-08-every-message-a-customer-reads-is-a-code-its-products-catalogue-words.md)).
|
|
844
|
+
A persistent notice sits in the section it concerns, action feedback is a toast, and field validation stays with its field. A notice carries one action, a 32 px outline button, and at most a second one after it, such as Nadia's Ask Nadia after Try again, and has no close button: it stays until the state changes, and one note stands for one concept. A section notice is always the framed note, with or without its action; the page or the account gets a `NoticeBanner`, which carries its one fix as a command (never a ready-made button), reads at 16 px and draws its button as a pill. A toast leaves after 6 s, which is also the Undo window; a failure the person must handle is never a toast alone but a very short toast beside a persistent notice. A notice, a failed read, a confirmation's error and a toast each show a message its product's catalogue worded, never a sentence written where it shows: `MessageNotice` under the control whose write failed (`action`) or atop the section it concerns (`section`), `EmptyState` `failed`, `ConfirmDialog`'s error and the toast. Each wraps a long word, never truncates, closes its title with a full stop before a body that follows on the same line, and shows a body only when it says more than the title ([the decision](../../docs/adr/2026-10-08-every-message-a-customer-reads-is-a-code-its-products-catalogue-words.md)).
|
|
830
845
|
|
|
831
846
|
Modal overlays use the scrim with no blur. Focus is not elevation: it is always the focus outline.
|
|
832
847
|
|
|
833
848
|
## Shapes
|
|
834
849
|
|
|
835
|
-
A corner follows what the thing is, on one scale: buttons, inputs, badges, tabs and menu rows take `{rounded.sm}` (6 px), and a line tab takes
|
|
850
|
+
A corner follows what the thing is, on one scale: buttons, inputs, badges, tabs and menu rows take `{rounded.sm}` (6 px), a large (40 px) control takes `{rounded.md}` (8 px), and the 24 px icon button, a keyboard key and a breadcrumb link take `{rounded.xs-plus}` (4 px); a line tab takes `{rounded.none}`, standing on its underline. A surface takes its corner with its material: resting and plain cards and tables take `{rounded.sm}` (6 px); a raised card and any medium or large surface take `{rounded.lg}` (12 px), as do menus, popovers, dialogs, sheets and toasts, and a drawer on each edge not flush with the window; tooltips take `{rounded.sm}` (6 px); a surface that fills the window takes `{rounded.xl}` (16 px); a collection's glass toolbar takes `{rounded.lg}` (12 px); a conversation bubble takes `{rounded.2xl}` (20 px); Nadia's chat bar takes `{rounded.3xl}` (24 px). A checkbox mark is a square at `{rounded.xs-plus}` (4 px), still distinct from a circular radio. A segmented control's track takes `{rounded.sm}` (6 px), `{rounded.md}` (8 px) at 40 px, and its chosen option `{rounded.xs-plus}` (4 px), `{rounded.sm}` at 32 px. A slider thumb is a 6 by 14 px bar at `{rounded.xs}`. A corner is never chosen at the call site: it comes with the surface or the control. A corner nested inside another takes the outer radius minus the gap between them. Full-bleed sections take `{rounded.none}`. `{rounded.full}` is for avatars, switch and radio marks, filter chips, tags, the conversation's send button, and pill and circle buttons (show more, a banner's call to action, a scroller's buttons, the theme switcher). The other radii are for inner marks and geometry a component owns, such as a progress track.
|
|
836
851
|
|
|
837
852
|
## Motion
|
|
838
853
|
|
|
@@ -854,7 +869,7 @@ The default transition in every product is `confirm`, 180 ms, `out-strong`. Unde
|
|
|
854
869
|
| `msg-in` 240 ms | A message arriving in a conversation |
|
|
855
870
|
| `transition` 240 ms | Property transitions on a working surface, and the Portal's one page transition, which carries an Agent's orb from a list row into its page |
|
|
856
871
|
| `arrive` 300 ms | A first use's picture coming into focus, once |
|
|
857
|
-
| `drawer-swipe` 400 ms, `drawer` 450 ms | Sheets and
|
|
872
|
+
| `drawer-swipe` 400 ms, `drawer` 450 ms | Sheets, and the phone drawer that follows the finger |
|
|
858
873
|
| `wait` 1.6 s | Every waiting indicator: the waiting line, on every screen, a kept Hermes screen's included |
|
|
859
874
|
|
|
860
875
|
The easings are `emphasized`, `out-strong`, `in-out-strong` and `drawer`; the waiting line alone travels at constant speed (`linear`). A CSS transition or animation takes its duration and easing from these tokens; the design system's own stylesheets are held to it by a guard.
|
|
@@ -872,12 +887,12 @@ answer keeps its component, density, value format and action placement.
|
|
|
872
887
|
| Information | Component and context |
|
|
873
888
|
| --- | --- |
|
|
874
889
|
| Records a person finds one of and acts on | `RecordList`, inside `CollectionPage` on a page of its own: one line per record that names itself, a few facts, the exception, the time, the row's command and its menu. |
|
|
875
|
-
| Records with the same comparable facts | `DataTable`: one identity per row, typed columns, visible headings, and a menu when secondary mutations exist. |
|
|
876
|
-
| A descriptive item with supporting prose | `ItemGroup` and `Item`: identity, description and trailing actions, rather than invented table columns. |
|
|
890
|
+
| Records with the same comparable facts | `DataTable`: one identity per row, typed columns each with a `size` (one column takes the rest), visible headings, sortable headings when the headings sort, and a menu when secondary mutations exist. |
|
|
891
|
+
| A descriptive item with supporting prose | `ItemGroup` and `Item`: identity, description and at most two trailing actions, rather than invented table columns. |
|
|
877
892
|
| What happened, in order | `ActivityFeed`: one row per event under its day ("Activity"). |
|
|
878
893
|
| The identity of a record in a collection | `RecordIdentity`: its name, one muted line and its `IdentityMark`; the containing list owns navigation. |
|
|
879
894
|
| Facts about one object | `ObjectPage`'s facts, `ObjectFacts` or `SettingsFactsSection`: labelled values in one coherent section. A relation uses its same identity or `Tag`; it does not become a separate card. |
|
|
880
|
-
| A coherent set of changes | `SettingsSection` with its `save` and `SettingsField`: the section owns its fields, help, recovery and local Save, and compares its fields with what is saved. |
|
|
895
|
+
| A coherent set of changes | `SettingsSection` with its `save` and `SettingsField`: the section owns its fields, its one-line help, recovery and local Save, with no help line under a field (a card of several fields gives a row that needs it an (i) with a tooltip), and compares its fields with what is saved. |
|
|
881
896
|
| A classification, lifecycle or operation | `Badge`, `StatusBadge` or `ActionStatus`, according to the existing state contract. A missing value, an empty list and a failed read remain distinct. |
|
|
882
897
|
| Another view or sibling collection of the current scope | `TabsNav` or line `Tabs` ("Controls"). A tab never introduces a new scope or a second collection owner. |
|
|
883
898
|
| A measurement over time or across objects | The existing KPI or chart composition for the reading; a named comparison uses the same `DataTable`, with units and visible headings. |
|
|
@@ -900,7 +915,7 @@ Every component has a usage page, as Geist documents each of its own: what it is
|
|
|
900
915
|
|
|
901
916
|
The page is written in the component's own source, as the TSDoc of its main export (`@family`, `@when`, `@instead`, `@behaviour`, `@words`, `@access`), so an editor shows it on hover in every product; `@nadicodeai/ui`'s showcase renders every page, family by family, with the component drawn in its states. A component without its usage page, or a page without its specimen, fails the package's checks. A usage page applies the rules in this file and never restates one.
|
|
902
917
|
|
|
903
|
-
The table below maps all
|
|
918
|
+
The table below maps all 73 entries in the [Geist component reference](https://vercel.com/geist/introduction) to our shared owners; how each owner is used is on its usage page. **Component** means a public owner exists for the job; it does not promise every Geist prop. **Composition** means existing parts provide the presentation together. An **enhanced capability gap** names specific behavior, not the absence of a matching component name. Use our exported APIs and names, not Geist's prop names: for example, our Button appearance is `variant`, while HTML submission behavior is `type`. A dedicated name in Geist does not require another primitive in our library; prefer existing compositions before adding another registry or dependency.
|
|
904
919
|
|
|
905
920
|
Use the [complete compositions](#complete-compositions) before assembling primitives. Component mechanics and supported props live in [the shared UI source](../ui/src/components); product adapters supply data, routes, translations, permissions and persistence. A component's visual owner supplies its geometry, typography, colour, focus and surface zones. A caller supplies layout and content.
|
|
906
921
|
|
|
@@ -908,77 +923,78 @@ Every example and consuming surface covers its reachable populated, empty, loadi
|
|
|
908
923
|
|
|
909
924
|
| Geist reference | Shared owner |
|
|
910
925
|
| --- | --- |
|
|
911
|
-
| [
|
|
912
|
-
| [
|
|
913
|
-
| [
|
|
926
|
+
| [Address Input](https://vercel.com/geist/address-input) | Composition: `Field` parts in a `FieldGroup` 16 px apart: a `NativeSelect` country first, a street `Combobox` (or `Input` when there is no lookup), Address line 2 with (optional) written in its label, then pairs such as State and ZIP or Postal code and City two-up. A failed lookup always ends in the manual fields, never a dead end. No dedicated export: it needs a provider only a product has. |
|
|
927
|
+
| [Avatar](https://vercel.com/geist/avatar) | Component: `Avatar` (16, 24, 32 and 48 px), `AvatarImage`, `AvatarFallback`, `AvatarGroup` (`members`, `limit`, `reverse`, `overlap`, one `label`; it draws its own `+N` count), `AvatarWithIcon` (name required, optional `label` for the state), `AvatarBadge` in `avatar.tsx`, and `avatarInitials`; a record's mark, a person's included, is `IdentityMark`, and an Agent is her `AgentOrb`. Not adopted: the loading `placeholder` (a still skeleton is ours), git-provider avatars and the username fetch. |
|
|
928
|
+
| [Badge](https://vercel.com/geist/badge) | Component: `Badge` (`sm` 16, `md` 20, `lg` 24 px; one `icon`; `pill` as the link look through `render`); `StatusBadge` for state; `Tag` for a categorical fact. Kept ours: sentence case, and the tone mark on every `StatusBadge` so a status reads without colour. Choose a typed tone; the owner supplies label geometry. |
|
|
929
|
+
| [Banner](https://vercel.com/geist/banner) | Component: `NoticeBanner`; no announcement strip. |
|
|
914
930
|
| [Book](https://vercel.com/geist/book) | Optional composition: `Card` / `PictureLabel` + `AspectRatio` and cover artwork. No dedicated book-frame export. |
|
|
915
|
-
| [Breadcrumbs](https://vercel.com/geist/breadcrumbs) | Component: `Breadcrumb`, `BreadcrumbList`, `BreadcrumbItem`, `BreadcrumbLink
|
|
931
|
+
| [Breadcrumbs](https://vercel.com/geist/breadcrumbs) | Component: `Breadcrumb`, `BreadcrumbList`, `BreadcrumbItem`, `BreadcrumbLink` (with `disabled` for an ancestor the person may not open), `BreadcrumbPage`, `BreadcrumbSeparator`, `BreadcrumbEllipsis`. The menu type (each crumb opens its siblings) is not built. |
|
|
916
932
|
| [Browser](https://vercel.com/geist/browser) | Optional composition: `Card` + `AspectRatio` and decorative browser chrome. `DesktopShell` remains real product chrome. |
|
|
917
|
-
| [Button](https://vercel.com/geist/button) | Component: `Button`, `
|
|
918
|
-
| [Calendar](https://vercel.com/geist/calendar) | Component: `Calendar
|
|
919
|
-
| [Checkbox](https://vercel.com/geist/checkbox) | Component: `Checkbox` + `FieldSet`, `FieldLegend`, `FieldLabel`. |
|
|
920
|
-
| [Choicebox](https://vercel.com/geist/choicebox) |
|
|
921
|
-
| [Clearable Input](https://vercel.com/geist/clearable-input) |
|
|
933
|
+
| [Button](https://vercel.com/geist/button) | Component: `Button` with `loading`, `loadingLabel`, `prefix`, `suffix` and `shape`; `ButtonLink` for links drawn as buttons; `buttonVariants` for elements that are neither. Our appearance prop is `variant`, submission is `type`. No `CustomButton` and no `warning` look: colour is ours. |
|
|
934
|
+
| [Calendar](https://vercel.com/geist/calendar) | Component: `Calendar` (month grid, `minValue`/`maxValue` for the data window); `DateRangeControl` for metric windows, one button that opens the presets as buttons beside the calendar. |
|
|
935
|
+
| [Checkbox](https://vercel.com/geist/checkbox) | Component: `Checkbox` + `FieldSet`, `FieldLegend`, `FieldLabel`. A box is named by `aria-label`, `aria-labelledby` or the `id` of its `FieldLabel`; one with none does not compile. Mixed is an unfilled box with a grey dash. |
|
|
936
|
+
| [Choicebox](https://vercel.com/geist/choicebox) | Component: `ChoiceboxGroup` with `ChoiceboxGroupItem`; `type` is `radio` or `checkbox`, each tile has a title, a required description, optional grey `specs` chips, one `badge` such as Recommended, a `disabledReason` and selected-only content. Tiles share one row and wrap to a column on a narrow screen. The selected tile is the one place blue sits on a choice: border, tint behind the row, words and corner mark; an unavailable tile stays grey. |
|
|
937
|
+
| [Clearable Input](https://vercel.com/geist/clearable-input) | Component: `ClearableInput` (clear button once there is text, Escape empties and keeps focus, `onClear`, `label` and `error` as on `Input`, optional `shortcut` keys that become Esc); other fixed parts are `InputGroup` compositions. |
|
|
922
938
|
| [Code](https://vercel.com/geist/code) | Composition: semantic `code` with the shared mono typography roles. Conversation `MarkdownText` already owns its inline code; no standalone `Code` export is required for that use. |
|
|
923
|
-
| [Code Block](https://vercel.com/geist/code-block) |
|
|
924
|
-
| [Collapse](https://vercel.com/geist/collapse) | Component: `Accordion
|
|
925
|
-
| [Combobox](https://vercel.com/geist/combobox) | Component: `Combobox`, input/content/list/item/group/label/empty/chips parts. |
|
|
926
|
-
| [Command Menu](https://vercel.com/geist/command-menu) | Component: `CommandDialog
|
|
927
|
-
| [Context Card](https://vercel.com/geist/context-card) | Component: `HoverCard`, `HoverCardTrigger`, `HoverCardContent
|
|
939
|
+
| [Code Block](https://vercel.com/geist/code-block) | `CodeBlock`: numbered lines that link to themselves, `highlightedLinesNumbers`, `addedLinesNumbers`, `removedLinesNumbers`, `hideLineNumbers` (marks still show and are announced), a `switcher` (select) or `tabs` for the language, a header only with a `filename`, `switcher` or `tabs`, and a `CopyButton` (32 px, not Geist's 28 px: CopyButton has no 28 px size). No syntax colour until a highlighter is adopted. Conversation `MarkdownText` keeps its job; `FileDiff` computes a before and after. |
|
|
940
|
+
| [Collapse](https://vercel.com/geist/collapse) | Component: `Accordion` (`size` default, small, large; `multiple` for independent sections), `Collapsible`; complete `Disclosure`. Closed panels stay in the page, hidden until found, so find-in-page opens them; `hiddenUntilFound={false}` mounts a heavy panel only when open. A collapse never nests in another. |
|
|
941
|
+
| [Combobox](https://vercel.com/geist/combobox) | Component: `Combobox`, input (sizes `sm`/default/`lg`, fills its container, leading search mark, named open-list and clear buttons)/content/list/item/group/label/empty/loading/chips parts. The list opens 8 px under the box at its width (a narrower width centres), in a 6 px inset, up to 210 px tall, rows 36 px with no gap and a 16 px check; the open-list and clear buttons are muted until hovered. |
|
|
942
|
+
| [Command Menu](https://vercel.com/geist/command-menu) | Component: `CommandDialog` (title, description and `resultCount` required; it draws `Command` itself), `CommandInput`, `CommandList`, `CommandEmpty`, `CommandGroup`, `CommandItem`, `CommandShortcut` (a `Kbd`). Find goes to places and runs no command, so there is no page stack. |
|
|
943
|
+
| [Context Card](https://vercel.com/geist/context-card) | Component: `HoverCard`, `HoverCardTrigger`, `HoverCardContent` and `HoverCardSummary` (name, one identifying line, two to four label and value facts, at most one link that takes the product's router link through `render`). Opens above after 150 ms. |
|
|
928
944
|
| [Context Menu](https://vercel.com/geist/context-menu) | Component: `ActionContextMenu`, the same `RecordMenu` as the row's `ActionMenu`, over the `ContextMenu` family. |
|
|
929
|
-
| [Copy Button](https://vercel.com/geist/copy-button) |
|
|
930
|
-
| [Description](https://vercel.com/geist/description) | Component: `ObjectPage`'s `facts`, `ObjectFacts`, `SettingsFactsSection`, `TableValue`. |
|
|
931
|
-
| [Destructive Action Modal](https://vercel.com/geist/destructive-action-modal) | Component
|
|
945
|
+
| [Copy Button](https://vercel.com/geist/copy-button) | `CopyButton` owns Button + existing clipboard behavior, pending state and an announced result. `TextWithCopyButton` binds a shown value to it. |
|
|
946
|
+
| [Description](https://vercel.com/geist/description) | Component: `ObjectPage`'s `facts`, `ObjectFacts` (a fact takes `tooltip`, `ellipsis` and `right`), `SettingsFactsSection`, `TableValue`. |
|
|
947
|
+
| [Destructive Action Modal](https://vercel.com/geist/destructive-action-modal) | Component: `ConfirmDialog`, with `verify` for the typed-name gate and `irreversible` for the band. |
|
|
932
948
|
| [Dots Menu](https://vercel.com/geist/dots-menu) | Component: `ActionMenu` for a record, `PageActions`' `menu` for a page. |
|
|
933
|
-
| [Drawer](https://vercel.com/geist/drawer) | Component: `
|
|
934
|
-
| [Empty State](https://vercel.com/geist/empty-state) | Component: [EmptyState](../ui/src/components/empty-state.tsx)
|
|
935
|
-
| [Entity](https://vercel.com/geist/entity) | Component: `RecordList` for records
|
|
936
|
-
| [Error](https://vercel.com/geist/error) | Component: `FieldError
|
|
937
|
-
| [Error Card](https://vercel.com/geist/error-card) |
|
|
949
|
+
| [Drawer](https://vercel.com/geist/drawer) | Component: `Drawer`, the bottom sheet for a short job on a phone, with `height` for the case where the default clips the action and `unsaved` to hold back a swipe, Escape or the back gesture while input is typed ([Menus and commands](#menus-and-commands)). `CatalogDrawer` and `FormDrawer` are Geist's Sheet in shape and are listed on the Sheet row. |
|
|
950
|
+
| [Empty State](https://vercel.com/geist/empty-state) | Component: [EmptyState](../ui/src/components/empty-state.tsx) with the kinds `firstUse`, `nothingYet`, `noResults`, `cleared`, `denied` and `failed`, following the [absence contract](#elevation--depth). |
|
|
951
|
+
| [Entity](https://vercel.com/geist/entity) | Component: `RecordList` for records (72 px entity rows, an optional `select` column); `Item`, `ItemGroup` and `ItemSelect` for a descriptive list; `CatalogEntry` in `LibraryShelf` and `CatalogDrawer`; `AgentListRow`. |
|
|
952
|
+
| [Error](https://vercel.com/geist/error) | Component: `FieldError` (a field), `MessageNotice` (a control or section), `EmptyState kind="failed"` with its reference (a block). |
|
|
953
|
+
| [Error Card](https://vercel.com/geist/error-card) | `EmptyState kind="failed" scope="card"`; no ErrorCard export. |
|
|
938
954
|
| [Feedback](https://vercel.com/geist/feedback) | Composition: `Popover`, `Field`, `Textarea`, `RadioGroup`, optional `Select`, and `Button`. The app supplies the submission destination and result; no collection backend is implied. |
|
|
939
|
-
| [Fieldset](https://vercel.com/geist/fieldset) | Component: `SettingsSection` with
|
|
955
|
+
| [Fieldset](https://vercel.com/geist/fieldset) | Component: `SettingsSection` with `save`, `tone`, `lockedReason` and `unlock`; `SettingsField`; `FieldSet`/`FieldLegend` for semantic subgroups. Required: the title, the description and the footer's left line (`footerHint`, `save.hint` or `lockedReason`); only a card of title and line has no footer. Tone error or warning: a 1px border in the hue and a footer tinted in it with its line in the hue, the body and the buttons neutral. Its DisabledWall is `lockedReason`. |
|
|
940
956
|
| [File Tree](https://vercel.com/geist/file-tree) | Composition: `SidebarMenu` + `Collapsible` + `FileTypeIcon` can follow sidebar-11 for nested files. Full tree-widget selection and roving arrow-key navigation require additional behavior. |
|
|
941
|
-
| [Gauge](https://vercel.com/geist/gauge) |
|
|
957
|
+
| [Gauge](https://vercel.com/geist/gauge) | Component: `Gauge` in `gauge.tsx`, one ratio out of 100 on Base UI `Meter`, `xs`/`sm`/`md`/`lg` (16, 32, 64 and 128 px), the number or an icon in the centre, our `Progress` tones. Not adopted: `indeterminate` (the waiting line), the two-arc `equal` ratio and the `colors` map (the tone is the product's threshold). |
|
|
942
958
|
| [Grid](https://vercel.com/geist/grid) | Composition: layout grid, `CardRow`, website `nc-page`; no ruled `Grid` API. |
|
|
943
|
-
| [Input](https://vercel.com/geist/input) | Component: `Input`, `InputGroup
|
|
959
|
+
| [Input](https://vercel.com/geist/input) | Component: `Input` (sizes `sm` 32, default 36, `lg` 40; props `label` (with `id`), `error`, `prefix` and `suffix` as filled cells, `look="plain"` for marks on the box fill, `rounded` for a pill), `InputGroup` for a button inside the box, a block addon, a textarea toolbar or a read-only server-given value with its copy button, `SettingsField`/`Field` for the card around it. Geist's `prefixContainer` and `suffixContainer` are compositions of `InputGroup`. |
|
|
944
960
|
| [JSON View](https://vercel.com/geist/json-view) | Composition for static JSON: code display with exact serialized text. `Collapsible` supports grouped disclosure; Geist-style keyboard tree navigation, search highlighting and depth controls remain an enhanced capability gap. |
|
|
945
|
-
| [Keyboard Input](https://vercel.com/geist/keyboard-input) | Component: `Kbd`, `
|
|
946
|
-
| [Label](https://vercel.com/geist/label) | Component: `Label`, `FieldLabel`, `FieldLegend
|
|
947
|
-
| [Load More Button](https://vercel.com/geist/load-more-button) | Component: `ActivityFeed`'s `older
|
|
948
|
-
| [Loading Dots](https://vercel.com/geist/loading-dots) | Personalization: `
|
|
949
|
-
| [Menu](https://vercel.com/geist/menu) | Component: `ActionMenu`, `ActionContextMenu`, `PageActions`' `menu` and `AccountMenu`, which draw their rows with `DropdownMenuCommand
|
|
950
|
-
| [MiddleTruncate](https://vercel.com/geist/middle-truncate) |
|
|
951
|
-
| [Modal](https://vercel.com/geist/modal) | Component: `Dialog` family, `FormDialog` for short forms, and `ConfirmDialog` for consequences. |
|
|
952
|
-
| [Multi Select](https://vercel.com/geist/multi-select) |
|
|
953
|
-
| [Note](https://vercel.com/geist/note) | Component: `
|
|
954
|
-
| [Pagination](https://vercel.com/geist/pagination) |
|
|
961
|
+
| [Keyboard Input](https://vercel.com/geist/keyboard-input) | Component: `Kbd`, which takes `meta`, `shift`, `alt` and `ctrl` flags, draws the person's platform (⌘ ⇧ ⌥ ⌃ on Apple systems, Ctrl Shift Alt elsewhere) and has two sizes, `default` (24 px) and `sm` (20 px) in a menu row, a command item or a table cell; `CommandShortcut` draws the same `Kbd`. There is no `KbdGroup`: several modifiers are one key. |
|
|
962
|
+
| [Label](https://vercel.com/geist/label) | Component: `Label`, `FieldLabel`, `FieldLegend`, at regular weight. Geist's `value`, `withInput` and `bypassCasing` are not needed: the label is children, the `Field` spaces it 8 px above the box at 13 px regular, and casing is never transformed. `htmlFor` ties it to the control's id. |
|
|
963
|
+
| [Load More Button](https://vercel.com/geist/load-more-button) | Component: `LoadMoreButton`, the full-width outline button under a list that grows in place; `ActivityFeed`'s `older` is one, or a `ButtonLink` when it navigates. It sits one `{spacing.md}` step below its list, and `noGap` removes the step for a list inside a card. |
|
|
964
|
+
| [Loading Dots](https://vercel.com/geist/loading-dots) | Personalization: `Button`'s `loading` and `WaitingLine`; no LoadingDots. |
|
|
965
|
+
| [Menu](https://vercel.com/geist/menu) | Component: `ActionMenu`, `ActionContextMenu`, `PageActions`' `menu` and `AccountMenu`, which draw their rows with `DropdownMenuCommand` (a command can be `disabled` with a reason, or `locked` with the reason it is locked); the `DropdownMenu` family directly only for a choice menu such as a sort, with `DropdownMenuLink` for a destination row. Every row, of any kind, is 36 px (44 on touch) with `{rounded.sm}` corners. |
|
|
966
|
+
| [MiddleTruncate](https://vercel.com/geist/middle-truncate) | `MiddleTruncate`: a path, URL, ID, hash or branch cut in the middle with one ellipsis glyph, the last third (at most 16 characters) kept whole, the full value in the page and, while cut, on the clipboard. Prose still ends in an end ellipsis. |
|
|
967
|
+
| [Modal](https://vercel.com/geist/modal) | Component: `Dialog` family (a bottom sheet on a phone), `FormDialog` for short forms with the `unsaved` guard, and `ConfirmDialog` for consequences. |
|
|
968
|
+
| [Multi Select](https://vercel.com/geist/multi-select) | Component: `MultiSelect` (checkbox menu, count in the trigger; a row is a checkbox square plus a button holding the name, whose word is Select all on a chosen row while some rows are unchosen and Select only otherwise); `Combobox multiple` when typing to find matters more; `CollectionFilters` for query facets, where a suggested value waits as a dashed, muted chip led by a +, never looking like a filter in force. |
|
|
969
|
+
| [Note](https://vercel.com/geist/note) | Component: `MessageNotice placement="section"` (the framed note, one action and at most a second after it); `Alert` is its primitive. No success, violet or cyan tone: our tones are neutral, info, warning and destructive. |
|
|
970
|
+
| [Pagination](https://vercel.com/geist/pagination) | Not built until a page needs it: the pages of a table of records are `DataTable`'s own Previous and Next under its card, and `RecordList`'s footer paging. |
|
|
955
971
|
| [Phone](https://vercel.com/geist/phone) | Optional composition: `AspectRatio` + decorative frame and captured content. No dedicated device-frame export. |
|
|
956
|
-
| [Pill](https://vercel.com/geist/badge#pill) |
|
|
957
|
-
| [Progress](https://vercel.com/geist/progress) | Component: `Progress
|
|
958
|
-
| [Project Banner](https://vercel.com/geist/project-banner) |
|
|
959
|
-
| [Radio](https://vercel.com/geist/radio) | Component: `RadioGroup`, `RadioGroupItem` with FieldSet/legend. |
|
|
960
|
-
| [Relative Time Card](https://vercel.com/geist/relative-time-card) | Component: `RecordTime`: the time in its verb's sentence or the clock time, the exact moment in UTC and the local zone in its hover card. |
|
|
961
|
-
| [Scroller](https://vercel.com/geist/scroller) | Component: `ScrollArea
|
|
962
|
-
| [Search Input](https://vercel.com/geist/search-input) | Component: `CollectionSearch` in `CollectionToolbar
|
|
963
|
-
| [Select](https://vercel.com/geist/select) | Component: `Select` family, `NativeSelect`
|
|
964
|
-
| [Separator](https://vercel.com/geist/separator) | Component: `Separator
|
|
965
|
-
| [Sheet](https://vercel.com/geist/sheet) | Component: `RecordSheet` for one record looked at from a list,
|
|
966
|
-
| [Show more](https://vercel.com/geist/show-more) |
|
|
967
|
-
| [Skeleton](https://vercel.com/geist/skeleton) | Component: `Skeleton
|
|
968
|
-
| [Slider](https://vercel.com/geist/slider) | Component: `Slider
|
|
969
|
-
| [Snippet](https://vercel.com/geist/snippet) |
|
|
970
|
-
| [Spinner](https://vercel.com/geist/spinner) | Personalization: `
|
|
971
|
-
| [Split Button](https://vercel.com/geist/split-button) |
|
|
972
|
-
| [Status Dot](https://vercel.com/geist/status-dot) | Component: [StatusDot](../ui/src/components/status-dot.tsx) and `StatusBadge`. |
|
|
973
|
-
| [Switch](https://vercel.com/geist/switch) |
|
|
974
|
-
| [Table](https://vercel.com/geist/table) | Component: `
|
|
975
|
-
| [Tabs](https://vercel.com/geist/tabs) | Component: `Tabs`, `TabsList
|
|
976
|
-
| [Text With Copy Button](https://vercel.com/geist/text-with-copy-button) |
|
|
977
|
-
| [Textarea](https://vercel.com/geist/textarea) | Component: `Textarea` + Field/SettingsField. |
|
|
978
|
-
| [Theme Switcher](https://vercel.com/geist/theme-switcher) | Component: `ThemeModeSwitcher
|
|
979
|
-
| [Toast](https://vercel.com/geist/toast) | Component: `Toaster
|
|
980
|
-
| [Toggle](https://vercel.com/geist/toggle) | Component: our `Switch` for boolean setting;
|
|
981
|
-
| [Tooltip](https://vercel.com/geist/tooltip) | Component: `TooltipProvider`, `Tooltip`, `TooltipTrigger`, `TooltipContent`. |
|
|
972
|
+
| [Pill](https://vercel.com/geist/badge#pill) | `Badge variant="pill"` with `render={<a href=... />}` for a link-like badge; static category: `Tag`; filters: `CollectionFilters`; buttons keep their semantics. |
|
|
973
|
+
| [Progress](https://vercel.com/geist/progress) | Component: `Progress` (tones, `stops`; the track is 4 px), `ProgressTrack`, `ProgressIndicator`, `ProgressLabel`, `ProgressValue`; `UsageMeter`. aria-valuenow follows the reading at most once a second. |
|
|
974
|
+
| [Project Banner](https://vercel.com/geist/project-banner) | Component: `NoticeBanner` (label, icon, one action as a command, no close, one at a time). |
|
|
975
|
+
| [Radio](https://vercel.com/geist/radio) | Component: `RadioGroup`, `RadioGroupItem` with FieldSet/legend. Rows are 24 px apart. The chosen radio keeps an empty circle with an ink edge and an 8 px ink dot; each option is named like a checkbox. |
|
|
976
|
+
| [Relative Time Card](https://vercel.com/geist/relative-time-card) | Component: `RecordTime`: the time in its verb's sentence or the clock time, the exact moment in UTC and the local zone in its hover card (above, after 150 ms); `children` carries a state no time describes (Pending, Queued). The product's words stay: Intl relative words inside the phrase, not Geist's 2m / 5h short form. |
|
|
977
|
+
| [Scroller](https://vercel.com/geist/scroller) | Component: `ScrollArea` (`overflow` y, x or both; an edge fade on each clipped edge; `buttonLabels` for two round buttons that scroll to the next direct child) and `ScrollBar`. `Carousel` stays a separate component until its fold into `ScrollArea` is done. |
|
|
978
|
+
| [Search Input](https://vercel.com/geist/search-input) | Component: `CollectionSearch` in `CollectionToolbar`: search mark or custom `prefix`, clear button and Escape, `loading` (busy plus the waiting line after a second), optional `shortcut` keys that become Esc. |
|
|
979
|
+
| [Select](https://vercel.com/geist/select) | Component: `Select` family and `NativeSelect` family, sizes `sm`/default/`lg`, optional `prefix` and `suffix` (a suffix takes the chevron's place); `label` and `error` as props on `SelectTrigger` and `NativeSelect`. A list of two or three static options is `RadioGroup`, as Geist says. |
|
|
980
|
+
| [Separator](https://vercel.com/geist/separator) | Component: `Separator` (hidden from assistive technology by default; `inset` keeps 1 px clear at each end where a divider meets a frame painted over the content); `FieldSeparator` and menu/group separators for scoped roles. |
|
|
981
|
+
| [Sheet](https://vercel.com/geist/sheet) | Component: `Sheet`, not modal by default (`modal` dims the page, `noOverlay` drops the scrim), with `RecordSheet` for one record looked at from a list, and `FormDrawer`/`CatalogDrawer` as its modal catalogue and steps forms. |
|
|
982
|
+
| [Show more](https://vercel.com/geist/show-more) | Not built until a page needs it: a list that grows from the server takes `LoadMoreButton`. `Disclosure` and `Collapsible` stay for optional sections. |
|
|
983
|
+
| [Skeleton](https://vercel.com/geist/skeleton) | Component: `Skeleton` (still; with a size it shows a bar until its content arrives, unsized it wraps a control and `show` covers it) and `SkeletonRegion` (the aria-busy region). Geist's shimmer and `animated` option are not taken. |
|
|
984
|
+
| [Slider](https://vercel.com/geist/slider) | Component: `Slider` takes a label and the real `min`, `max` and `step`, draws its live value and, on request, start and end boxes (`Input` `sm`); values are arrays and a range has two thumbs named by the label and their position. The track is 8 px, the filled part is blue and turns grey when disabled, and the thumb is a 6 by 14 px bar that grows by a fifth while dragged or focused. |
|
|
985
|
+
| [Snippet](https://vercel.com/geist/snippet) | `Snippet`: one command (or a few lines) after a prompt the component draws and never copies, with `CopyButton`, `placeholder` for the empty state, `copyText` for a highlighted element, `copied` and `onCopy`. No `dark`, `type` or `width`: colour and size are ours. Longer scripts are a `CodeBlock`. |
|
|
986
|
+
| [Spinner](https://vercel.com/geist/spinner) | Personalization: `Button`'s `loading` and `WaitingLine`, no Spinner export. |
|
|
987
|
+
| [Split Button](https://vercel.com/geist/split-button) | Not built until a page needs it. |
|
|
988
|
+
| [Status Dot](https://vercel.com/geist/status-dot) | Component: [StatusDot](../ui/src/components/status-dot.tsx) and `StatusBadge`. Kept ours: the dot is still, has four generic tones and no deployment states; the word beside it is its name. |
|
|
989
|
+
| [Switch](https://vercel.com/geist/switch) | Component: `SegmentedControl` for two or three exclusive views of one surface (radio semantics, option heights `sm` 24, `default` 28, `lg` 32 inside a 4 px inset, so the control is 32, 36 or 40 px high); `Tabs` for panels; `ToggleGroup` for pressed buttons that can be several or none; the theme stays `ThemeModeSwitcher`. |
|
|
990
|
+
| [Table](https://vercel.com/geist/table) | Component: `Table` with `TableColgroup`/`TableCol` and a `TableBody` that takes `striped`, `bordered` and `interactive`; `DataTable` for records with sizes and sortable headings; `RecordList` for rows that name themselves; `TableCard` and `TableValue`. Virtualization remains a separate capability. |
|
|
991
|
+
| [Tabs](https://vercel.com/geist/tabs) | Component: `Tabs`, `TabsList` (`variant` default or line), `TabsTrigger` (`disabledReason` with `disabled`), `TabsContent`; URL views use `TabsNav`/`TabsLink`. |
|
|
992
|
+
| [Text With Copy Button](https://vercel.com/geist/text-with-copy-button) | `TextWithCopyButton`: the value in the mono label type plus `CopyButton` (32 px); `ellipsis` cuts it in the middle and the whole value still copies. The Portal uses it for identifiers and checksums. |
|
|
993
|
+
| [Textarea](https://vercel.com/geist/textarea) | Component: `Textarea` (100 px minimum, grows with its content, `lg` for 16 px type, `label` with `id` and `error` as props) + Field/SettingsField. Its height is its content with a 100 px floor; `rows` is not a size. The save of `FormDialog`, `FormDrawer`, `RowEditForm` and `SettingsSection` trims its ends. |
|
|
994
|
+
| [Theme Switcher](https://vercel.com/geist/theme-switcher) | Component: `ThemeModeSwitcher` (three named tiles with their icons, System, Light, Dark, the one order every theme choice keeps) on the settings page, `ThemeModeMenu` in the account menu, `ThemeModeSegments` in the corner of a page. |
|
|
995
|
+
| [Toast](https://vercel.com/geist/toast) | Component: `Toaster` (6 s); `showMessageToast` from `@nadicodeai/ui/components/toast`. Gaps held in `toast.ts`: `preserve`, a literal Undo, a neutral tone. |
|
|
996
|
+
| [Toggle](https://vercel.com/geist/toggle) | Component: our `Switch` for a boolean setting; a bare `Switch` is the 28 by 14 px track, on is blue and a disabled one is grey. It sits in a card's body with its state word, or at the end of a row of a multi-row card. Our `Toggle` is a pressed button. |
|
|
997
|
+
| [Tooltip](https://vercel.com/geist/tooltip) | Component: `TooltipProvider`, `Tooltip`, `TooltipTrigger`, `TooltipContent`. Opens after 150 ms (`delay` on the trigger or provider; `delay={0}` for none); `arrow={false}` is Geist's `tip={false}` and `centerText={false}` its `center={false}`. Geist's coloured `type` is not provided. |
|
|
982
998
|
| [Video](https://vercel.com/geist/video) | Composition: `AspectRatio` + native video, controls, poster and caption tracks. A richer player needs a concrete media requirement; no shared Video export is needed for native playback. |
|
|
983
999
|
|
|
984
1000
|
### Additional shared building blocks
|
|
@@ -987,16 +1003,13 @@ These shared components also follow the same foundations, although Geist does no
|
|
|
987
1003
|
|
|
988
1004
|
| Owner | Use and composition contract |
|
|
989
1005
|
| --- | --- |
|
|
990
|
-
| `Sidebar`, `SidebarSections`, `UpdateCard`, `AccountMenu`, `
|
|
991
|
-
| `NavigationMenu` | A site's grouped navigation links, with genuine destinations and usable keyboard paths. Product object views use shared tabs; commands use a menu. |
|
|
992
|
-
| `Menubar` | A persistent application command bar with related menus. Use only when the workspace has that command model; do not substitute it for website navigation or a row's actions. |
|
|
1006
|
+
| `Sidebar`, `SidebarSections`, `UpdateCard`, `AccountMenu`, `DesktopShell`; the Portal's `PortalShellFrame` | Persistent product navigation and workspace chrome ("Product shells"). The product owns destinations and active state; the shell owns compact behavior, landmarks and layout. `SidebarSections` is the sidebar's swap into an object's sections or an area's sub-menu, `UpdateCard` the offer to update above the account. Never add a competing sidebar to a page. |
|
|
993
1007
|
| `Popover` | A bounded contextual control such as filters or a scope chooser. Name its trigger, keep essential meaning visible outside hover, and restore focus when it closes. Which form surface a job takes is decided in [Menus and commands](#menus-and-commands). |
|
|
994
1008
|
| `InputOTP` and its group/slot parts | A fixed-length verification code. Keep one logical input with paste and keyboard behavior, a visible label, invalid/retry state and a real resend policy. The product owns length, expiry and submission. |
|
|
995
1009
|
| `Carousel` | A finite horizontal rail where adjacent media or items have a meaningful sequence. Give previous/next controls clear names and boundaries; preserve keyboard access and reduced motion. A sortable record collection uses a table or entity list. |
|
|
996
1010
|
| `ResizablePanelGroup`, `ResizablePanel`, `ResizableHandle` | A workspace with genuinely adjustable panes. Keep keyboard resizing, meaningful minimum sizes, readable content and a compact alternative. The product owns persistence of pane sizes. |
|
|
997
1011
|
| `AspectRatio` | Stable layout for real media while it loads. Supply a meaningful ratio and correct media alternative; the wrapper creates neither playback controls nor a device-frame component. |
|
|
998
|
-
|
|
|
999
|
-
| `DirectionProvider` | Direction context when the product supports right-to-left content. Keep reading and focus order meaningful; direction does not translate strings or change locale by itself. |
|
|
1012
|
+
| Field parts and form adapters | Connect actual validation to controls, help and errors. Use the field owner that matches the product's form engine; preserve values through recoverable failure. Do not change the form engine during visual styling. |
|
|
1000
1013
|
| `PairingCode` | A short code two screens show at once so a person can tell they are talking to each other, such as the four digits Nadia and Alveare Server both show while a Nadia asks to join. Each digit stands in its own cell at `{typography.heading-lg}` with tabular figures, large enough to compare from across a desk, and assistive technology reads the label, then the digits one by one. It only shows a code: a code a person types is `InputOTP`. |
|
|
1001
1014
|
| `QrCode` | A real scannable value with a readable fallback and an alternative action when scanning is unavailable. Keep secrets out of accessible labels and show expiry or invalidity from actual state. |
|
|
1002
1015
|
| `FileDiff` | Existing code-change comparison, with file identity and additions/removals explained. A diff is not a general code editor or JSON viewer. Preserve exact source and the established conversation/tool owner. |
|
|
@@ -1012,49 +1025,59 @@ Choose the owner for the whole task. Keep its slots and state handling together
|
|
|
1012
1025
|
| Read-only facts | `ObjectPage`'s `facts`, `SettingsFactsSection` or `ObjectFacts`, with `TableValue` for missing facts. | Label/value pairs, actual timestamps, identifier format, links and permission-aware actions. Unknown remains distinct from zero. |
|
|
1013
1026
|
| Entity collection | `CollectionPage` on `RecordList`: the title's actions, the line tabs, search, filters and sort, then rows that identify themselves (`RecordIdentity` with its `IdentityMark` and `detail`, a status only for the exception, `RecordTime`), the row's command or menu, an action's failure inside its row, the edit inside its row (`RowEditForm`), and its loading, empty and no-match states. | The records, what each one says, its commands as data, its catalogue message when an action fails, and the edit form. Never its own toolbar, table, rows or menus. |
|
|
1014
1027
|
| A list inside another page | `RecordList` with its `heading`: an overview's exceptions, an object's "Needs attention". | The same as a collection's rows, and the heading's title. |
|
|
1015
|
-
| Comparable collection | `DataTable` within `TableCard`, under `PageActions` and `CollectionToolbar`. | Stable record IDs, columns, visible headings, search/filter/sort, URL state, row commands, pagination and `empty`. Numeric columns align at the trailing edge; totals and paging use their own footer zone. |
|
|
1028
|
+
| Comparable collection | `DataTable` within `TableCard`, under `PageActions` and `CollectionToolbar`. | Stable record IDs, columns, visible headings, search/filter/sort, URL state, row commands, pagination and `empty`. Numeric columns align at the trailing edge; the first and last columns stand in from the card's edges by the card's spacing, so the first lines up with the title; totals and paging use their own footer zone. On a phone the toolbar's search takes the first line and its filters and sort one scrolling line under it. |
|
|
1016
1029
|
| Overview | `OverviewPage` with its `KpiCard` figures, its `ChartCard`s and its exceptions. | Measurement, unit, comparison period, truthful delta and stable categorical assignment; the reading time and the way to each figure's owner. Status colour and series colour retain different meanings. |
|
|
1017
1030
|
| Object | `ObjectPage` with `ObjectSection`, `ObjectFacts`, a `RecordList` with its heading, a `SettingsSection` or an `ActivityFeed` as its sections. | The object, its mark, its facts, its one secondary action and its menu, and its sections. An Agent's Profile keeps `AgentProfileCard`. |
|
|
1018
|
-
| A reusable thing to add | `LibraryShelf` with `
|
|
1031
|
+
| A reusable thing to add | `LibraryShelf` with `AgentCard`s for a gallery of templates; `CollectionPage` for a catalog a person finds, opens and adds from (the Portal's Skills and Plugins); `CatalogDrawer` with `CatalogEntry`s where the choice opens from a page. | The cards or the rows, one line each, the add and its state. |
|
|
1019
1032
|
| What happened | `ActivityFeed`; one run's steps are `RunTimeline` ("Activity"). | The events, each with its time, actor, sentence, the exception and a detail line, grouped by day. |
|
|
1020
1033
|
| Getting something set up | `NumberedSteps` for the steps on a page; `FormDrawer job="steps"` for a setup with a wait. | The steps, the current one where the sequence tracks real progress, and each step's own action. |
|
|
1021
1034
|
| Short form: a new record, or one or two values from a command | `FormDialog` with Field parts; Portal binds it through `ActionDialogForm`. A record in a list edits inside its row (Entity collection); a catalog uses `CatalogDrawer` and a setup in steps `FormDrawer` ([Menus and commands](#menus-and-commands)). | Submit operation, labels, validation, dirty state, retained input, permissions and dismissal policy. Use the owned scroll body and fixed footer; do not nest another overlay. |
|
|
1022
1035
|
| One record looked at from a list | `RecordSheet`. | The record's name, one line, its facts, an optional payload and the way to its owner. |
|
|
1023
|
-
| Destructive confirmation | `ConfirmDialog`; the app's confirm-action adapter. | A title naming the record as a statement, the real consequence, a confirm repeating the verb and the noun, pending state, failure and operation.
|
|
1036
|
+
| Destructive confirmation | `ConfirmDialog`; the app's confirm-action adapter. | A title naming the record as a statement, the real consequence, a confirm repeating the verb and the noun, pending state, failure and operation. `verify` asks for the record's name before the confirm enables, for a high-stakes action (delete, rotate, revoke, disconnect, downgrade, a protection switched off), even a reversible one; `irreversible` names what cannot be undone and is left out when the action can be reversed. A routine confirmation (discard a draft) takes neither. |
|
|
1024
1037
|
| Global commands or record actions | `CommandDialog` for Find; `ActionMenu` and `ActionContextMenu` for one record; `PageActions` for a page. | Real commands as data, the record they act on, permissions, disabled reasons and keyboard shortcuts. The destructive command stays last. |
|
|
1025
|
-
| Absence or failed read | `EmptyState`, through the composition's `empty`, `noMatch` and `failed` or `DataTable.empty`; `MessageNotice` for persistent conditions. | First use with its section's picture, nothing yet, no matches or failed read, with the real recovery action. Empty state belongs outside the semantic table body. |
|
|
1026
|
-
| Rich choices | `
|
|
1027
|
-
|
|
|
1028
|
-
|
|
|
1029
|
-
| Plain code or static JSON | `CodeBlock` owns the read-only InputGroup composition and CopyButton. | Exact `code`, accessible `label`, optional filename/language and copy labels. Serialize static JSON in the adapter; use FileDiff for an actual before/after comparison. |
|
|
1038
|
+
| Absence or failed read | `EmptyState`, through the composition's `empty`, `noMatch` and `failed` or `DataTable.empty`; `MessageNotice` for persistent conditions. | First use with its section's picture, nothing yet, no matches, finished work, a denial or a failed read, with the real recovery action. Empty state belongs outside the semantic table body, inside the composition's persisting polite wrapper. |
|
|
1039
|
+
| Rich choices | `ChoiceboxGroup` with `ChoiceboxGroupItem`, in the group's own `FieldSet` and legend. | Known options (no more than six), selection model, labels, a description for every tile, disabled reasons. The whole tile selects, its corner always shows the dot or the check, a selected tile is blue (border, tint behind its row, words and corner mark) unless it is unavailable, and only the tile draws the focus ring; a tile's content is for reading, never a link or a button. |
|
|
1040
|
+
| Copyable identifier or command | `TextWithCopyButton` for a value, `Snippet` for a command; the prompt is the component's and is never copied. | Exact `value` or `text`, translated `copyLabel`, `copiedLabel`, `copyFailedLabel`. The shown text is the copied text; a long one takes `ellipsis`. |
|
|
1041
|
+
| Plain code or static JSON | `CodeBlock`. | Exact `code`, accessible `label`, `filename` only when the code has a place to be pasted into, copy labels. Serialize static JSON in the adapter; use FileDiff for a before/after comparison. |
|
|
1030
1042
|
| A record's time | `RecordTime`: the time in its verb's sentence, or the clock time in a feed, with UTC and the local zone in its hover card. | The machine-readable timestamp, the phrase, the locale and the product's refresh policy. |
|
|
1031
1043
|
| Expandable file navigation | `SidebarMenu` and `Collapsible`, following shadcn sidebar-11, with file icons and real file links or commands. | Hierarchy, stable identity, current file, labels and actions. Preserve semantic nested lists; a full tree widget needs a separately verified keyboard contract. |
|
|
1032
1044
|
| Feedback collection | `Popover` with Field, Textarea, optional RadioGroup/Select and Button; inline rendering uses the same form parts. | Prompt, topic choices, permitted context, destination, pending/result state and retained input on failure. |
|
|
1033
1045
|
| Native media playback | `AspectRatio` around a native video with its controls, poster and caption tracks. | Media source, captions, transcript where needed, aspect ratio, playback policy and unavailable-media recovery. |
|
|
1034
1046
|
|
|
1035
|
-
Use `CopyButton` and `CodeBlock` for their complete compositions. Feedback and expandable file navigation combine existing parts with product adapters.
|
|
1047
|
+
Use `CopyButton`, `TextWithCopyButton`, `Snippet` and `CodeBlock` for their complete compositions. Feedback and expandable file navigation combine existing parts with product adapters. Syntax colour and full JSON/tree-widget navigation remain specific behavior gaps; do not invent undocumented props or copy a local implementation into every caller. [shadcn Button Group](https://ui.shadcn.com/docs/components/base/button-group), [Field](https://ui.shadcn.com/docs/components/base/field) and [Data Table](https://ui.shadcn.com/docs/components/base/data-table) provide the underlying composition patterns; our public wrappers and this document own their product use.
|
|
1036
1048
|
|
|
1037
1049
|
### Personalization boundaries
|
|
1038
1050
|
|
|
1039
|
-
|
|
1051
|
+
The owner's line: follow Geist for everything that makes components and compositions coherent (the spacing scale, paddings and gaps, control, row and icon sizes, the type scale and hierarchy, layout, density, alignment, corner radii, how components are built and composed, and their behaviour and rules), and keep nadicode's colour, glass and material (surfaces, depth, shadows, blur), Agent orbs, genuine provider marks, categorical Library colours and sentence-case product words. Every part, option and rule comes from Geist's page or is already ours; nothing is invented. These differences are tokenized or owned by a typed component variant. Business status, permissions, transaction boundaries and product copy remain the product's truth; a visual reference cannot change them.
|
|
1052
|
+
|
|
1053
|
+
The owner's decisions where Geist and ours differ:
|
|
1054
|
+
|
|
1055
|
+
- Words stay in sentence case, never Geist's Title Case: tab titles, collapse headings, reasons and a date range's presets ("Past 7 days") included.
|
|
1056
|
+
- Our component names stay; a Geist part we lack is added under a name that says what it is.
|
|
1057
|
+
- A settings toggle, the theme included, is a draft that its section's Save applies, where Geist applies a toggle on change. The exception is a switch in a card's header: it applies at once, and that card has no Save, only its footer line.
|
|
1058
|
+
- Find goes to places only: it runs no command and has no page stack.
|
|
1059
|
+
- A wait stays still, with no spinner, loading dots or shimmer; a `Button` takes Geist's `loading` behaviour with its pending word in place of the spinner.
|
|
1060
|
+
- `Gauge` is a control for one ratio, never a chart.
|
|
1061
|
+
- `ChoiceboxGroup`, `ClearableInput`, `Snippet` and `LoadMoreButton` are components, never recipes a page assembles.
|
|
1062
|
+
- The three-dot trigger stays 36 px, ruled by the owner on 14 October 2026.
|
|
1040
1063
|
|
|
1041
1064
|
### Controls
|
|
1042
1065
|
|
|
1043
|
-
- **Buttons.**
|
|
1044
|
-
- **Dialog footers.** A dialog's
|
|
1045
|
-
- **Tabs** switch between sibling collections or views of one scope, such as a company's Members, Invitations and Teams, or Billing's Subscriptions, Approvals and Stripe events. One shows at a time; the choice lives in the URL, as a route or `?tab=` with the first tab left out, so it survives a reload, Back and a shared link; and switching never changes whose things you are looking at. A tab never introduces a new scope: another company or Agent is another place, reached from the sidebar or a scope selector, and a choice of whose things are listed is a filter in the toolbar. A tab title is a noun with no icon and no count; the count belongs to the list's footer. A page's collections take the line tabs (`Tabs` with `TabsList variant="line"`), under the title row and above the toolbar: the current tab in ink on a 2 px ink underline, the rest muted until hover. The page's actions stay on its title row whichever tab is shown, the toolbar belongs to the tab shown and switching clears its search and page, and two lists are never stacked with a tab row between them. A section's views take `TabsNav` and `TabsLink` in the band under the top bar, the current link on the selection fill, scrolling sideways on a phone. A set of different things, such as Nadia's company sections, is pages in the sidebar, never tabs.
|
|
1066
|
+
- **Buttons.** A button is 24, 32, 36 or 40 px high (`{spacing.control-height-xs}`, `{spacing.control-height-sm}`, `{spacing.control-height}`, `{spacing.control-height-lg}`) with `{rounded.sm}` corners, `{rounded.md}` at 40 px and `{rounded.xs-plus}` on the 24 px icon button. The label is `{typography.button}` at 32 and 36 px, `{typography.button-lg}` at 40 px and `{typography.button-xs}` at 24 px, and the inline padding is `{spacing.button-padding-inline-sm}` at 32 px, `{spacing.button-padding-inline}` at 36 px and `{spacing.button-padding-inline-lg}` at 40 px ("Layout" says where the smaller sizes may go). An icon leads or trails the label as the button's `prefix` or `suffix`; an icon-only button is named by its `aria-label`. A working button is `loading`: it says the label's -ing form in the label's place, ignores a second press, keeps focus and shows no spinner. A disabled filled button drops to the muted fill, the muted text and the hairline at full opacity; `ghost` and `link` dim instead. A link drawn as a button is a `ButtonLink`. `default` is the action (ink, white label; `{colors.dark-action}` with a `{colors.dark-action-foreground}` label in dark); `outline` and `secondary` are the quieter steps, edged with the `{colors.line}` hairline; `ghost` has no edge and serves a tertiary text action or an icon-only command (the three dots, close, collapse); `destructive` is the error pair; `link` is inline. On a colour or black ground a control takes a variant whose label clears AA there: `brandSolid` (white, ink label) or `brandGhost` (white label, no fill) on cobalto, rosso and black, and the default ink button on verde, arancio and giallo.
|
|
1067
|
+
- **Dialog footers.** A dialog's Cancel sits at the footer's leading edge and its primary at the trailing edge; a dialog with one button fills the footer with it. A step back (Previous) is grouped with Cancel in one wrapper at the leading edge, so the footer keeps two ends. A choice to stop being asked is a checkbox at the end of the body, remembered by whichever action is taken, never a third button. On a phone the dialog and the confirmation are bottom sheets whose footer keeps its one row, Cancel leading and the primary trailing.
|
|
1068
|
+
- **Tabs** switch between sibling collections or views of one scope, such as a company's Members, Invitations and Teams, or Billing's Subscriptions, Approvals and Stripe events. One shows at a time; the choice lives in the URL, as a route or `?tab=` with the first tab left out, so it survives a reload, Back and a shared link; and switching never changes whose things you are looking at. A tab never introduces a new scope: another company or Agent is another place, reached from the sidebar or a scope selector, and a choice of whose things are listed is a filter in the toolbar. A tab title is a noun with no icon and no count; the count belongs to the list's footer. A page's collections take the line tabs (`Tabs` with `TabsList variant="line"`), under the title row and above the toolbar: the current tab in ink on a 2 px ink underline, the rest muted until hover. The page's actions stay on its title row whichever tab is shown, the toolbar belongs to the tab shown and switching clears its search and page, and two lists are never stacked with a tab row between them. A section's views take `TabsNav` and `TabsLink` in the band under the top bar, the current link on the selection fill, scrolling sideways on a phone and fading out over 32 px at each end where more links stand beyond it. A set of different things, such as Nadia's company sections, is pages in the sidebar, never tabs. A pill tab (`TabsList`, `TabsNav`) is 32 px high with 12 px sides, `{typography.label-sm}` at 400 and no gap between tabs. A line tab (`variant="line"`) is 50 px high with 2 px sides, `{typography.body-sm}` at 400, 24 px between tabs and a 1 px rule under a full-width row. A row of line tabs holds at most 7 tabs on a desktop and 4 on a phone; a `TabsNav` band, which scrolls sideways on a phone, holds at most 7 at every width, as an Agent's six views do. One tab is disabled only for a permission or an empty state and says why with `disabledReason`. Label the row with `aria-label` or `aria-labelledby` and keep keyboard navigation. A choice that changes a value rather than a view uses radio or toggle semantics instead.
|
|
1046
1069
|
- **Links** read as text. A link inside a sentence, or offered alone as a section's way on, is `{colors.link}` and underlined at rest; a link that is itself the value, such as a record's name or a fact, keeps the text's colour and underlines on hover; a secondary way out beside the content, such as a card header's "see everything", uses the same blue link treatment. Breadcrumb and back navigation retain their quieter navigation treatment. The underline sits 4 px under the text.
|
|
1047
|
-
- **Fields**
|
|
1070
|
+
- **Fields** draw their edge as a 1 px ring outside the box in `{colors.input}`, darker on hover and full strength with a 4 px halo on focus, `{rounded.sm}` (`{rounded.md}` at 40 px; `rounded` makes a pill), in three heights that Input, Textarea, Select, NativeSelect, Combobox, MultiSelect and InputGroup share: `{spacing.control-height-sm}`, `{spacing.control-height}` and `{spacing.control-height-lg}`. Inline padding is `{spacing.control-padding-inline}`. A prefix or suffix is a filled cell with a divider, or `plain` on the box fill, with a 14 px mark; an icon button inside a field fills the row flush to its edge, is muted until hovered and never fills. Every field has a name: a visible label of 13 px in the secondary text colour, 8 px above the box, tied by id (or `aria-label` where the name is drawn elsewhere). Colour sits in one place: an error turns the ring red, fills the halo (also while the box has focus) and colours the 13 px message under it (8 px below, with an alert mark; 16 px beside a 40 px field), and a Combobox colours its typed text; the label, fill, text, placeholder and marks stay neutral. A disabled box, and the label of a disabled control, step down in fill and text, never in opacity, and ignore hover. A field fills its container. Help is the one-line description of the card that holds the field, one setting to a card, never a line under each field; the error takes its place while it shows. A field that may stay empty says so in its label, never in its placeholder. A field validates when it loses focus, stays focusable while it saves, and the save of a `FormDialog`, `FormDrawer`, `RowEditForm` or `SettingsSection` trims the ends of its text.
|
|
1048
1071
|
- **Focus** is drawn once, by the base layer, on every `:focus-visible` element. A component never repaints it; it may move it to a proxy that stands for the focused element, as a field group does for its input.
|
|
1049
|
-
- Enabled buttons show a pointer; a disabled control advertises nothing. On coarse or non-hover input every target is at least `{spacing.touch-target}`, while a checkbox or radio mark stays compact and its label supplies the target. An unchecked checkbox or radio mark is its `{colors.input}` edge with no fill of its own, so it shows the surface it sits on
|
|
1072
|
+
- Enabled buttons show a pointer; a disabled control advertises nothing. On coarse or non-hover input every target is at least `{spacing.touch-target}`, while a checkbox or radio mark stays compact and its label supplies the target. An unchecked checkbox or radio mark is its `{colors.input}` edge with no fill of its own, so it shows the surface it sits on, and greys on hover unless disabled. A checked checkbox fills with the action pair; a checked radio stays an empty circle with an ink edge and an 8 px ink dot; a mixed checkbox stays unfilled with a grey dash.
|
|
1050
1073
|
|
|
1051
1074
|
### Cards and sections
|
|
1052
1075
|
|
|
1053
|
-
`Card` is the product's container, at the resting height by default ("Elevation & Depth"). A row of cards is a `CardRow`: siblings share one height, and the row collapses to one column below its breakpoint. A card or settings section is composed around a real task, collection or form; its header names the content and may explain scope or consequence, and it is never a card holding only an introduction. A card's or a section's title carries no icon, unless the card stands for one external system, whose mark it then carries. A settings section owns its heading, a one-line description of what the setting changes, its fields and its local save. On a settings page the shape follows the data, and when it saves follows whether a half-done edit makes sense. A reversible choice (a switch, a theme, a language, a pick from a short list) applies at once, with no Save, and the product's toast confirms it; a change that fails says so in the toast and the control shows the stored value again. A typed value (a name, a URL, a server, a port, a key) gets its own card, which saves its fields through its own `save`, with its own Save in its footer: always visible and off until something in that card differs from what is saved; while saving, its pending word; a save that succeeds
|
|
1076
|
+
`Card` is the product's container, at the resting height by default ("Elevation & Depth"). A row of cards is a `CardRow`: siblings share one height, and the row collapses to one column below its breakpoint. A card or settings section is composed around a real task, collection or form; its header names the content and may explain scope or consequence, and it is never a card holding only an introduction. Its one header action, a single button, badge or three dots, stays at the title's right at every width, as Vercel keeps a card's Add on its title row on a phone; only an action of several controls moves under the description in a header narrower than 28rem. A card's or a section's title carries no icon, unless the card stands for one external system, whose mark it then carries. A settings section owns its heading, a one-line description of what the setting changes, its fields and its local save. On a settings page the shape follows the data, and when it saves follows whether a half-done edit makes sense. A reversible choice (a switch, a theme, a language, a pick from a short list) applies at once, with no Save, and the product's toast confirms it; a change that fails says so in the toast and the control shows the stored value again. A typed value (a name, a URL, a server, a port, a key) gets its own card, which saves its fields through its own `save`, with its own Save in its footer: always visible and off until something in that card differs from what is saved; while saving, its pending word; a save that succeeds calls `save.saved`, and the product announces it through its own toast, a catalogue message: "Completion toasts follow `{Noun} {past-participle}`: `Blob deleted`, `Domain added`, `Environment variable saved`. Never include `successfully`; the action name implies it." (https://vercel.com/geist/toast), and Save returns to disabled with no saved state in the footer; a failure keeps every value and shows under the field it is about. A collection is a table whose Add opens a form and whose every row carries **⋯**, and a destructive action there confirms first. A status is a read-only card with the one action that fixes it. A section that reports a condition of its own (a failed payment, a trial ending) takes `tone="error"` or `tone="warning"`: a 1px border in the hue and a footer tinted in it with its line in the hue, while the title, description, fields and buttons stay neutral, and says the condition in words in the footer line. A button takes the hue of its command, not of the card: red for a permanent loss (Delete), amber for a disruptive command that can be undone (Pause, Archive). A section the person may not change takes `lockedReason`: its fields stay in view, their text muted and out of reach under a not-allowed cursor, the title and description unchanged; the footer line says why, and `unlock` is the way to get access when there is one; a locked section has no Save or header action. An object's section that edits in place swaps to the same section with Cancel before Save. Its footer is a strip one tone off the card body inside the card's edge, the `recessed` role behind a `{colors.line}` seam: `{colors.canvas-soft}` below the white card in light, and `{colors.dark-canvas}` below the resting body in dark: an optional hint on the left, only where it says something specific to that card (a limit such as "Please use 32 characters at maximum.", what a value is for, the plan a feature needs or a link to learn more) and never one sentence every card repeats, and the section's action on the right; a facts section shows labelled facts as plain pairs, the label above its value, in two equal columns, stacked on compact screens, with every label kept in place when a value is missing; a fact never gets a box of its own inside the card. A KPI card is one figure: label, value, the change as a badge in the top right, and a footer with the comparison; its label is words alone, with no icon. A figure that carries its own values over the period, as on Analytics' Activity, reads as Vercel Observability's overview tile: the label across the tile, the value with the change badge at its right, a thin line across the tile's width under them, and the comparison under the line on up to two lines that every tile of the row reserves, with no footer, so nothing in a row of five is cut. A row of five figures sits in one row from 1280 px, three over two below that, two by two with the fifth across on a tablet, and one column on a phone; it never leaves one figure alone beside a hole.
|
|
1054
1077
|
|
|
1055
1078
|
### Menus and commands
|
|
1056
1079
|
|
|
1057
|
-
A record's primary destination is its visible name or a labelled link. Navigation is never hidden in its action menu. Keep the main task visible: Edit opens the record inside its row, as in Vercel Domains; Connect belongs beside an available connection. Additional mutations use an end-aligned `ActionMenu`, the same commands on a right-click through `ActionContextMenu`; a menu is not required when the row has no secondary mutations. Commands reach a person only through `PageActions` (a page), `ActionMenu` and `ActionContextMenu` (a record) and `AccountMenu` (the account), each taking its commands as data (`menu-owner`). The three-dot trigger is a `{spacing.control-height}` ghost icon button named for its record, "More for pec@acme.it", and comes last, after any button. A record's or a page's menu opens under its trigger at the floating height and draws, top to bottom: its first line naming the record it acts on, in muted type; the commands, each with its icon leading the label, as Geist and Vercel draw them; then, after a divider, the destructive command last, in the error colour. A disabled command stays in place with its reason under its label. A destructive command never becomes the loudest repeated action: it is never a button on every row. Ruled by the owner on 14 October 2026. The account menu is the one exception, drawn as Vercel's below: its icons trail their labels and Sign out is in the body colour.
|
|
1080
|
+
A record's primary destination is its visible name or a labelled link. Navigation is never hidden in its action menu. Keep the main task visible: Edit opens the record inside its row, as in Vercel Domains; Connect belongs beside an available connection. Additional mutations use an end-aligned `ActionMenu`, the same commands on a right-click through `ActionContextMenu`; a menu is not required when the row has no secondary mutations. Commands reach a person only through `PageActions` (a page), `ActionMenu` and `ActionContextMenu` (a record) and `AccountMenu` (the account), each taking its commands as data (`menu-owner`). The three-dot trigger is a `{spacing.control-height}` ghost icon button named for its record, "More for pec@acme.it", and comes last, after any button. A record's or a page's menu opens under its trigger at the floating height and draws, top to bottom: its first line naming the record it acts on, in muted type; the commands, each with its icon leading the label, as Geist and Vercel draw them; then, after a divider, the destructive command last, in the error colour. A command that cannot run now is disabled and stays in place with its reason under its label; a command the person may not run is locked: it stays in place, inert, with a lock at its end and the reason under its label, which is required. A menu holds about ten commands at most, and one level of submenu at most, never for a destructive command. A destructive command never becomes the loudest repeated action: it is never a button on every row. The lists of a Select, a Combobox and a MultiSelect share this geometry: a 12 px corner, a 6 px inset (8 px for MultiSelect), rows 36 px (28 px for MultiSelect) with no gap, opened 8 px from their trigger; they keep glass, and a row that cannot be chosen turns its text muted, never dimmed. Ruled by the owner on 14 October 2026. The account menu is the one exception, drawn as Vercel's below: its icons trail their labels and Sign out is in the body colour.
|
|
1058
1081
|
|
|
1059
1082
|
Choose the surface by where the thing being changed is shown and how big the job is, never by the page that happens to need it: the same job takes the same surface in every product. Adding a skill is the catalogue drawer in the Portal and in Nadia, and editing a task or an MCP server opens its row in both. Each surface has one owner:
|
|
1060
1083
|
|
|
@@ -1063,33 +1086,34 @@ Choose the surface by where the thing being changed is shown and how big the job
|
|
|
1063
1086
|
| Change a record shown in a list | Its row opens into the form, with Cancel and Save in the form's footer, Save off until something changes; the other rows stay where they are | `RowEditForm` in `CollectionPage`'s `editor` | Vercel Domains › Edit; a task, a mailbox, an MCP server, a channel |
|
|
1064
1087
|
| Change a fact on a record's own page or card | In place: a pencil turns the fact into its field, saved by the card's Save | `AgentProfileCard`; an `ObjectSection` that swaps to its `SettingsSection` | An Agent's name and description |
|
|
1065
1088
|
| Add a record through a few fields, or change one or two values from a command | A centred dialog | `FormDialog`; the Portal's `ActionDialogForm` | New task, add a mailbox, add an MCP server |
|
|
1066
|
-
| Choose from a catalogue | A
|
|
1067
|
-
| Set up in several steps with a wait | The same
|
|
1068
|
-
| Look at one record from a list, then go back to the list | A sheet from the right, its title naming the record, its facts and its payload; Close
|
|
1089
|
+
| Choose from a catalogue | A modal sheet at the right edge: the search, then the entries, each with its Add | `CatalogDrawer` | Add a skill, in both products; Vercel Domains › Add |
|
|
1090
|
+
| Set up in several steps with a wait | The same sheet, its progress, "Step 2 of 3", in mono over the title, which stays the job's name | `FormDrawer job="steps"` | Connect a messaging channel; Telegram's QR setup |
|
|
1091
|
+
| Look at one record from a list, then go back to the list | A sheet from the right that leaves the page usable, its title naming the record, its facts and its payload; a press outside does not close it, Close and Escape do and give focus back to the row | `RecordSheet` | One Stripe event in Billing |
|
|
1069
1092
|
| Do a workflow a person could link to | Its own page | The page's composition | Vercel Add New › Project; New Agent |
|
|
1070
1093
|
| Confirm a consequence | A confirmation | `ConfirmDialog` | Remove, Disconnect |
|
|
1071
1094
|
|
|
1072
|
-
A record already on screen is never edited in a dialog or a
|
|
1095
|
+
A record already on screen is never edited in a dialog or a sheet, and a sheet is never chosen because an action takes input: a catalogue is `CatalogDrawer`, a setup in steps is `FormDrawer` with `job="steps"`, and a sheet owns its one width, 512 px from 1024 px and the window less its margins below it, which no caller sets. A `Drawer` is only the phone's bottom sheet for a short job, never a desktop surface and never a confirmation. A confirmation's title names the record as a statement, never a question: "Delete Bandi di Bergamo"; its body says what happens, and its button repeats the verb and the noun, "Delete task". A settings page is the Settings composition. These choices follow the live Vercel Domains, Projects and settings pages and the [Geist Modal](https://vercel.com/geist/modal), [Sheet](https://vercel.com/geist/sheet) and [Fieldset](https://vercel.com/geist/fieldset) patterns.
|
|
1073
1096
|
|
|
1074
1097
|
Collection search and filters stay immediately above their rows. The title row holds the collection's primary action, unless an inline form already exposes that task. Scope selectors preserve the authorized organization or account. Filters do not compete with primary actions. The account menu identifies the signed-in person and exposes their account settings, theme and language, drawn as Vercel's: 288 px wide, opening 6 px above its trigger; a header of the name and the lines under it with the gear at its end, and no picture; then one divider and the rows, 36 px high, each its label leading and its icon or its control trailing in muted ink, Theme and Language as a small round pill of choices, a product's own reading before its icon, and Sign out last in the body colour, since signing out destroys nothing. Ruled by the owner on 16 October 2026.
|
|
1075
1098
|
|
|
1076
1099
|
|
|
1077
1100
|
### Tables and missing values
|
|
1078
1101
|
|
|
1079
|
-
A table is native table structure: 40 px rows for comparable facts,
|
|
1102
|
+
A table is native table structure: a head row of 36 px labels over 12 px of room and then its rule, so the first body row starts at the rule like every other, 40 px body rows for comparable facts (a cell that holds a control, such as the three dots, is padded just enough to keep the row at 40), every cell padded 8 px sideways (10 px above and below in the body), headings at 14 px / 20 px and weight 500, visible because people compare and sort by them. Numeric columns align to the trailing edge with tabular figures. A sortable heading is a button inside its header cell: the arrow is decorative, the cell carries `aria-sort`, and the button names the next sort. `striped`, `bordered` and `interactive` belong to the table body; an interactive, striped or bordered row rounds the outer corners of its first and last cell to 6 px.
|
|
1080
1103
|
|
|
1081
|
-
A record row is one line per record, drawn by `RecordList`, which `CollectionPage` renders, and nothing else draws one (`page-composition` refuses a `DataTable` without column headings): a
|
|
1104
|
+
A record row is one line per record, drawn by `RecordList`, which `CollectionPage` renders, and nothing else draws one (`page-composition` refuses a `DataTable` without column headings): a 72 px entity row, with 16 px above and below, whose columns stand left to right at the widths the list declares, so a person reads every list the same way:
|
|
1082
1105
|
|
|
1083
|
-
| Slot |
|
|
1106
|
+
| Slot | Width | Holds |
|
|
1084
1107
|
| --- | --- | --- |
|
|
1085
|
-
|
|
|
1086
|
-
|
|
|
1087
|
-
|
|
|
1088
|
-
|
|
|
1089
|
-
| The
|
|
1090
|
-
|
|
|
1108
|
+
| Selection | 40 px, only when the list is picked from | A box named "Select {name}" |
|
|
1109
|
+
| Identity | The rest: the one column without a size | The record's 32 px identity mark ("Identity marks"), then its name (600) over one muted 14 px line saying what it is or where it comes from, each on one line ending in an ellipsis (`RecordIdentity`'s `detail`: "Company skill · every Agent has it") |
|
|
1110
|
+
| Facts | Each fact's `size` | A few facts on one line, ending in an ellipsis |
|
|
1111
|
+
| Status | `status.size` | Only the exception, the status that tells this row apart from the others; empty for the usual record |
|
|
1112
|
+
| Time | `time.size`, tabular | The time in its verb's sentence (`RecordTime`: "Updated 3 hours ago", the date after a week, the exact moment on hover) |
|
|
1113
|
+
| Checklist | 52 px, only when the record has steps to be ready | Its `ProgressChecklist` ring ("Status") |
|
|
1114
|
+
| The row's command and the three dots | `commandsSize`; left out, 64 px for the three dots alone, or as wide as the widest lone menu command drawn as a button, never cutting its label | One command that is not destructive, as an `outline` button, then the row's `ActionMenu`; or a muted chevron when the row only opens |
|
|
1091
1115
|
|
|
1092
|
-
Never the three dots before the button, a decorative icon for the record's mark, a status on every row, or a destructive button on every row. An action that failed or was refused shows as its catalogue message inside its own row, with its next step, never a notice under the row, and an edit opens inside its row. A screen gives `RecordList` the records and what each one says, never its own toolbar, table, rows or menus, and anything more than a few facts lives on the record's page. A
|
|
1116
|
+
A status column stands only while a record in the list shows its exception, the commands column only while a record has a command, a menu or a message or the rows open, and the commands column widens for a failed action's next steps only while a row shows one, so the name and its line keep the room the row leaves. Never the three dots before the button, a decorative icon for the record's mark, a status on every row, or a destructive button on every row. An action that failed or was refused shows as its catalogue message inside its own row, with its next step, never a notice under the row, and an edit opens inside its row. A screen gives `RecordList` the records and what each one says, never its own toolbar, table, rows or menus, and anything more than a few facts lives on the record's page. A descriptive list uses `ItemGroup` and `Item` instead of table semantics: 16 px padding, a 600 title over one 20 px description with no gap, a row of 72 px, and at most two trailing controls (`size="sm"`, 32 px), the rest in the three dots. A list a person picks from starts each row with `ItemSelect`, whose box is named "Select {name}". The table inherits its enclosing surface, whose Card owns the outer edge; a visible header and every record except the last end with a quiet 1 px `border` divider. An interactive body row takes the full `accent` fill on hover, on keyboard focus within it and while its menu is open; a passive table does not imply an action on hover; a selected row takes `muted`; headers and footers never highlight. A collection fits its container without sideways scrolling: each column is as wide as its definition's `size` in pixels, the one column without a size takes what is left, and a card narrower than the sized columns plus 160 px for the unsized one keeps the identity and the actions in their columns and takes every other column out of the row, as Vercel's lists read on a phone: each joins one muted line under the name, joined by a middle dot and ending in an ellipsis, with no labels on screen, or is dropped when its column says `compact: "dropped"`, for a fact the record's page holds and the phone can spare; a status keeps its own mark. A row on a phone is the name over that one line, never a stack of labelled values: in a record row the facts join the identity's own line after a middle dot, so the record stays one 72 px row, the name over one line. A table whose every column must stay, a settings matrix, names them all in `primaryColumns` and lays out by its content on a narrow card, so its names wrap beside the columns. A titled table card carries its toolbar on the title's row, title left and controls right, as Vercel heads a card's list; under 576 px the toolbar takes its own line under the title. A value too long for its column holds one line and ends in an ellipsis, whole in its title, as a long name does. A document's table, such as a legal page's, is read whole instead: its columns take the `wraps` option, so their words wrap and the row grows, and it shows its header row. In the compact layout every cell but the identity wraps between words. Text anywhere in the product breaks between words, and inside a word only when that word alone cannot fit a line; a machine string such as a hash or a key breaks at any character in a row of wrapped text, or is cut in the middle with `MiddleTruncate` on one line. One categorical fact in a row, such as an installation or a partner, is a `Tag`: a 24 px pill with its mark, dashed when the fact states an absence. An app in a row is its brand mark, its identity mark at 32 px.
|
|
1093
1117
|
|
|
1094
1118
|
An unknown or not-applicable value in a table, a comparison list or a set of facts is a muted `—` with screen-reader text, in the same slot as a present value; zero stays zero. An absent report is not `None`: `None` is only for a complete report that found nothing. A stale value keeps its last reading with a short `Stale` qualifier. Loading, failure, missing permission and actionable setup each keep their own visible state and never turn into a dash. Essential reasons and actions never live only in a hover tooltip.
|
|
1095
1119
|
|
|
@@ -1107,6 +1131,8 @@ A status is one `StatusBadge`: a mark and a word in one of five tones, so it rea
|
|
|
1107
1131
|
|
|
1108
1132
|
The Portal, Nadia and Alveare draw every status with the one `StatusBadge` in `@nadicodeai/ui`, which owns the tones and their marks; each app keeps only its value-to-tone map in one module, and nothing else chooses a status colour. A status never moves.
|
|
1109
1133
|
|
|
1134
|
+
How far a record is through the steps that make it ready is a `ProgressChecklist`, as Vercel ends a project's row with its Production Checklist: a 24 px blue `Gauge`, its track and its arc the share of steps done, a whole ring when all are, with the double check inside in ink, on a 36 px ghost button before the row's commands whose tooltip names the checklist and how far it is ("Customer setup 3/4"), that opens the steps in a sheet at the right: the ring, the title, one line, then a card per step with its icon on a tile of its hue, its title, one line and the outline button that leads where it is done; every step is the same hairline card, and a done step differs only by the blue Done chip after its title and by having no button, so the steps still to do lead the eye. A step is done because the thing it asks for exists, so the checklist remembers nothing and has no Skip. The step's hue says which kind of step it is, never whether it is done.
|
|
1135
|
+
|
|
1110
1136
|
In a list or a feed a status shows only for the exception: the record or the event that differs from the others, such as a failure, a revocation or a wait for a person's decision. The usual state shows nothing, so a status never stands on every row. An object's own status sits beside its name in the path ("Product shells").
|
|
1111
1137
|
|
|
1112
1138
|
### Activity
|
|
@@ -1127,16 +1153,16 @@ Who does the work decides how it looks. An Agent's work is that Agent's orb in i
|
|
|
1127
1153
|
|
|
1128
1154
|
| The wait | What shows |
|
|
1129
1155
|
| --- | --- |
|
|
1130
|
-
| Under about a second | The control's own label changes to its pending word
|
|
1156
|
+
| Under about a second | The control's own label changes to its pending word, a button's through its `loading` and `loadingLabel`; its place, size and icon stay. |
|
|
1131
1157
|
| Past a second | One 2 px waiting line of ink beside the work, a 32% segment crossing it on `wait`, and nothing else moves. |
|
|
1132
|
-
| Measurable | A progress line with a written count, "Step 2 of 3" or "12 of 40 MB". Never a percentage. |
|
|
1133
|
-
| A page load | Still skeleton placeholders in the shape of the content, never pulsing and never paired with a waiting line. |
|
|
1158
|
+
| Measurable | A progress line with a written count, "Step 2 of 3" or "12 of 40 MB". Never a percentage. A ratio of a fixed maximum is a `Gauge`, which prints the bare number and leaves the unit to its label. |
|
|
1159
|
+
| A page load | Still skeleton placeholders in the shape of the content, inside one `SkeletonRegion`, never pulsing and never paired with a waiting line. |
|
|
1134
1160
|
|
|
1135
1161
|
One wait gets one indicator. A request waiting for a person is not a wait: queued, paused, blocked, failed and done take the status or feedback treatment. A wait is ink; info blue never marks one. Under reduced motion the waiting line breathes in opacity instead of travelling.
|
|
1136
1162
|
|
|
1137
1163
|
### Failure surfaces
|
|
1138
1164
|
|
|
1139
|
-
A page that cannot show what was asked for opens with a picture, the way a Portal email does: one whole cut-out in art direction's editorial register, centred above the words, whose idea says what happened. The picture carries a label, the way a museum labels a work: its title says what the figure is doing, which is the page's one joke, and a mono line gives its materials and year.
|
|
1165
|
+
A page that cannot show what was asked for opens with a picture, the way a Portal email does: one whole cut-out in art direction's editorial register, centred above the words, whose idea says what happened. The picture carries a label, the way a museum labels a work: its title says what the figure is doing, which is the page's one joke, and a mono line gives its materials and year. The label stands centred under the picture at every width. Below the label, on the same centre line, stand a mono eyebrow naming the situation, the page's one heading, one plain sentence, and the recovery action, which leads. The cut-out's transparent ground takes the page's own, so one file serves light and dark, and it stays whole at every width: it scales down with the column and is never cropped by the viewport. No orb turns on a failure page.
|
|
1140
1166
|
|
|
1141
1167
|
A Portal email, whether the Portal or Knock sends it, follows the same order under its picture, in one structure: the picture, the eyebrow and a short heading keep the centre line; one sentence of consequence, a list between hairlines when the email is about several things (each a semibold heading over its one sentence), a table of its facts between hairlines when it has facts, one to-do sentence, the fallback link and the footer stand flush left; the button stays centred.
|
|
1142
1168
|
|
|
@@ -1157,13 +1183,13 @@ An Agent is its orb, in every product; there is no other Agent picture. An orb i
|
|
|
1157
1183
|
- **In Nadia's list.** Each Agent's row (`AgentListRow`) is 52 px high: her orb at 32 px in her real state, her name, and one state line in words, "Working", "Idle" or "Needs you". Only "Needs you" takes a 6 px status dot before its words; the orb shows working by itself. In the list's narrow column (from 640 to 899 px) each orb stands at 40 px in a 48 px square, named with its state line in a tooltip. Only an orb moves in the list.
|
|
1158
1184
|
- **Status and ambient.** An orb that stands for an Agent shows its real state. An orb in decorative artwork, such as a sign-in picture, takes ambient motion: its form moves at its own pace with no state pose or cue, and it claims no activity.
|
|
1159
1185
|
- **Reduced motion.** Movement stops; a thinking or working orb breathes between full ink and 0.45 opacity so busy still reads as busy, and an ambient orb holds still.
|
|
1160
|
-
- **In a conversation.** Her states are the conversation's own: the orb in its header follows them, and every mark of her activity in the thread is her own orb in her real state, never another Agent's figure, a spinner, a ticker or a pulse. Her steps and tool calls hold still and say in words what they do or did, with a tool's kind as a decorative icon beside the words and no state of its own; the outcome of a step or a request is the `StatusBadge`, and a failed turn is the `MessageNotice`. A conversation has two actors, her and the person, and every wait in it belongs to one of them. Everything she does, including what follows the person's approval or answer, is her orb in its state: working once Run is pressed, thinking once a question is answered, waiting while an approval or a question waits for the person, blocked when a turn fails, done once when she finishes. The person's own action in progress shows on what they made: a file stays veiled on its own chip until it is uploaded, and fills only where its upload reports progress; the microphone shows it records. A pressed control keeps its place and changes only its word
|
|
1186
|
+
- **In a conversation.** Her states are the conversation's own: the orb in its header follows them, and every mark of her activity in the thread is her own orb in her real state, never another Agent's figure, a spinner, a ticker or a pulse. Her steps and tool calls hold still and say in words what they do or did, with a tool's kind as a decorative icon beside the words and no state of its own; the outcome of a step or a request is the `StatusBadge`, and a failed turn is the `MessageNotice`. A conversation has two actors, her and the person, and every wait in it belongs to one of them. Everything she does, including what follows the person's approval or answer, is her orb in its state: working once Run is pressed, thinking once a question is answered, waiting while an approval or a question waits for the person, blocked when a turn fails, done once when she finishes. The person's own action in progress shows on what they made: a file stays veiled on its own chip until it is uploaded, and fills only where its upload reports progress; the microphone shows it records. A pressed control keeps its place and changes only its word, a button through its `loading`. The waiting line is for the window's own loading, outside the conversation. Ruled by the owner on 11 October 2026: the Agent's states are the chat's default states, not random icons; and on 13 October 2026: the person never meets "the app" in a conversation, only the Agent.
|
|
1161
1187
|
|
|
1162
1188
|
Text sits beside an orb, never on it.
|
|
1163
1189
|
|
|
1164
1190
|
### Agent card
|
|
1165
1191
|
|
|
1166
|
-
An Agent is shown as one card shape wherever it appears as an object, in the Portal's Library and Nadia's gallery alike
|
|
1192
|
+
An Agent is shown as one card shape wherever it appears as an object, in the Portal's Library and Nadia's gallery alike, as Vercel's Templates gallery draws a template: the name over the job, cut after two lines, the small meta and a status row under them, the one action at the name's right, and under them the preview tile, inset 32 px from the leading edge and running off the trailing and bottom edges, her orb at 96 px in its middle on the recessed ground. On an Agent's own page the name is the page heading.
|
|
1167
1193
|
|
|
1168
1194
|
### Company card
|
|
1169
1195
|
|
|
@@ -1177,9 +1203,9 @@ An identity mark says which thing a record is, and `IdentityMark` is its one own
|
|
|
1177
1203
|
| --- | --- |
|
|
1178
1204
|
| An Agent | Her real orb from the orb engine, at its largest size not above the mark's, with no tile and no ring; never a painted circle ("Agent orbs") |
|
|
1179
1205
|
| An app | Its own logo in the tile |
|
|
1180
|
-
| A company | Its two initials in a ringed tile on the card ground |
|
|
1206
|
+
| A company | Its logo: the one white ink Sofia keeps from its site, on a black tile (`{colors.identity-ink}`) in both themes, as its card stamps it, or a square SVG icon in its own colours filling the tile, as Vercel shows a project's favicon; its two initials in a ringed tile on the card ground until a logo is found |
|
|
1181
1207
|
| A person | Their picture, or their initials, round |
|
|
1182
|
-
| A record of a kind | The kind's own icon in a ringed tile on the card ground, the same icon its section has in the navigation: Mail for a mailbox, a server for an MCP server, a key for a password. A Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is |
|
|
1208
|
+
| A record of a kind | The kind's own icon in a ringed tile on the card ground, the same icon its section has in the navigation: Mail for a mailbox, a server for an MCP server, a key for a password. A Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is; an entry that has its own object picture draws it on that ground in the icon's place |
|
|
1183
1209
|
|
|
1184
1210
|
Initials stand only for a company or a person. The mark is 32 px in a record's row, 64 px at the head of an object's page, 40 px on a Library entry, 24 px in a feed and on a sidebar's identity line, and 28 px for the company at the top of Nadia's list; a tile takes 6 px corners, 8 px at 40 and 64.
|
|
1185
1211
|
|
|
@@ -1191,7 +1217,7 @@ Website product views follow "Product views on the website" in [Elevation & Dept
|
|
|
1191
1217
|
|
|
1192
1218
|
### CSS components
|
|
1193
1219
|
|
|
1194
|
-
These
|
|
1220
|
+
These three ship as framework-neutral CSS; `@nadicodeai/ui` wraps the last two for React.
|
|
1195
1221
|
|
|
1196
1222
|
**`dotted-field`** — the ground of a canvas where a person or an Agent places and arranges objects: a diagram of an Agent's work, a board of its outputs. The dots say that things here can be moved, so the field never sits behind a dashboard, a list, settings or a website section, and it never stands in for elevation.
|
|
1197
1223
|
|
|
@@ -1199,15 +1225,13 @@ These four ship as framework-neutral CSS; `@nadicodeai/ui` wraps the last three
|
|
|
1199
1225
|
|
|
1200
1226
|
**`run-timeline`** — the vertical thread of an Agent's run, a handoff or a workflow, one step per row.
|
|
1201
1227
|
|
|
1202
|
-
**`memory-item`** — one fact an Agent remembers about the company or its work.
|
|
1203
|
-
|
|
1204
1228
|
## Iconography
|
|
1205
1229
|
|
|
1206
1230
|
Every product draws Lucide's shapes, unedited, in the house render: a 1.5 px line (`{spacing.icon-stroke}`) measured on screen at every size and 1.25 px (`{spacing.icon-stroke-sm}`) at 12 px, round caps and joins, no fill, and the text colour by default. Semantic icons may use their status or category tone with an adjacent readable label; navigation icons stay neutral. Sizes are 12, 16, 20 and 24 px, 16 by default, and inside a stock component the registry's own icon size stands; persistent navigation uses 20 so its entries read before the content beside them, and a collapsed rail keeps 16. A surface draws a small, disciplined set, never the whole library.
|
|
1207
1231
|
|
|
1208
1232
|
Three icons are the house's own, drawn on Lucide's grid in the same render: `arch` for the company and its doors, `approvals`, the arch with a check, for work waiting on a person, and `agent`, the orb seen face-on with the Agent as the dot on its path. They name those three things wherever an icon does, and no Lucide glyph stands in for them. An icon beside text is decorative; an icon-only control carries an accessible name.
|
|
1209
1233
|
|
|
1210
|
-
An icon belongs to a control or a menu row, never to a title. A card's, a section's or a label's title and a KPI's label carry no icon (`no-decorative-icon`): an icon there repeats the words beside it and competes with the marks that matter. A menu row
|
|
1234
|
+
An icon belongs to a control or a menu row, never to a title. A card's, a section's or a label's title and a KPI's label carry no icon (`no-decorative-icon`): an icon there repeats the words beside it and competes with the marks that matter. A menu row takes one icon, leading its label; a button takes one, leading or trailing it (`prefix` or `suffix`). A mark goes where it says which thing you are looking at; a picture marks a moment. Where each goes:
|
|
1211
1235
|
|
|
1212
1236
|
| Place | Identity mark | Icon | Picture |
|
|
1213
1237
|
| --- | --- | --- | --- |
|
|
@@ -1217,8 +1241,9 @@ An icon belongs to a control or a menu row, never to a title. A card's, a sectio
|
|
|
1217
1241
|
| A KPI card | No | Only the trend in the change badge | No |
|
|
1218
1242
|
| A first-use empty state | No | No | Yes, the section's picture, 240 × 176 on a page |
|
|
1219
1243
|
| Nothing yet, no results | No | No | No |
|
|
1244
|
+
| Finished work, a denial | No | The success mark; the lock mark | No |
|
|
1220
1245
|
| A failed read | No | The warning mark | No |
|
|
1221
|
-
| A menu row, a button | No | One, leading | No |
|
|
1246
|
+
| A menu row, a button | No | One, leading; a button's may trail | No |
|
|
1222
1247
|
| Entry, a failure page, Downloads, a first run | The Agent's orb where she is the subject | No | Yes, one, whole |
|
|
1223
1248
|
|
|
1224
1249
|
A benefit of nadicode, and each piece of office work Nadia arrives ready for, is drawn on the website by its object: one transparent object of the art direction, something old from Italy with one piece of today in it, in two identity hues, in the family of the Portal's email pictures (the key ring with its security key). The objects are a library (`brand/visual-design/images/website-objects/`, briefed in `brand/refs/briefs/website-benefits.json`), and the same object stands for the same benefit wherever the brand names it: the website, the docs, a deck, a post. On a page they stand at one size, above their title, and never move. Lucide glyphs stay the products' own icons and never stand for a benefit on the website.
|
|
@@ -1256,10 +1281,10 @@ The clear space is one stroke width of the rendered logo on every side. The mini
|
|
|
1256
1281
|
|
|
1257
1282
|
- Do keep the brand still: only Agents, the product at work and the website's shader objects move. Don't animate sections, pictures or scrolling, apart from the bounded homepage figure response and a first use's one arrival in Motion.
|
|
1258
1283
|
- Do use the identity hues at full strength in the places "Colour as stage" lists, with the text pole that clears AA. Don't tint them, grade them, or paint a control, chrome or a status with them.
|
|
1259
|
-
- Do choose a surface's height by its physical role, and let its
|
|
1284
|
+
- Do choose a surface's height by its physical role, and let its recipe show it: shadows in light, a top highlight and an outer hairline on black in dark. Don't add a border, ring or second shadow to an elevated surface.
|
|
1260
1285
|
- Do put glass on floating chrome over content that scrolls or moves under it. Don't make content glass, or put glass over a plain ground.
|
|
1261
1286
|
- Do show authentic captures or real-component scenes as "Product views on the website" specifies, with provenance recorded in the repository. Don't use device frames or invented interfaces.
|
|
1262
|
-
- Do give each thing the corner its role takes on the scale ("Shapes"). Don't
|
|
1287
|
+
- Do give each thing the corner its role takes on the scale ("Shapes"). Don't choose a corner at the call site: a raised card, like any medium or large surface, takes the larger corner with its material.
|
|
1263
1288
|
- Do give every line one owner, and draw focus only with the focus outline.
|
|
1264
1289
|
- Do say a status with a `StatusBadge` tone, a mark and a word. Don't use colour alone or a bare dot.
|
|
1265
1290
|
- Do open a failure page with one whole cut-out whose idea says what happened, labelled like a work in a museum, above the words on one centre line, with the recovery action leading and the diagnostic code only for a request that stopped. Don't apologise, don't crop the picture, don't joke about lost work, and don't put an orb on a failure page.
|
|
@@ -1293,37 +1318,6 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1293
1318
|
"value": 20,
|
|
1294
1319
|
"unit": "px"
|
|
1295
1320
|
}
|
|
1296
|
-
},
|
|
1297
|
-
"glass-highlight": {
|
|
1298
|
-
"$type": "shadow",
|
|
1299
|
-
"$value": {
|
|
1300
|
-
"offsetX": {
|
|
1301
|
-
"value": 0,
|
|
1302
|
-
"unit": "px"
|
|
1303
|
-
},
|
|
1304
|
-
"offsetY": {
|
|
1305
|
-
"value": 1,
|
|
1306
|
-
"unit": "px"
|
|
1307
|
-
},
|
|
1308
|
-
"blur": {
|
|
1309
|
-
"value": 0,
|
|
1310
|
-
"unit": "px"
|
|
1311
|
-
},
|
|
1312
|
-
"spread": {
|
|
1313
|
-
"value": 0,
|
|
1314
|
-
"unit": "px"
|
|
1315
|
-
},
|
|
1316
|
-
"color": {
|
|
1317
|
-
"colorSpace": "srgb",
|
|
1318
|
-
"components": [
|
|
1319
|
-
1,
|
|
1320
|
-
1,
|
|
1321
|
-
1
|
|
1322
|
-
],
|
|
1323
|
-
"alpha": 0.18
|
|
1324
|
-
},
|
|
1325
|
-
"inset": true
|
|
1326
|
-
}
|
|
1327
1321
|
}
|
|
1328
1322
|
},
|
|
1329
1323
|
"elevation": {
|
|
@@ -1364,7 +1358,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1364
1358
|
"unit": "px"
|
|
1365
1359
|
},
|
|
1366
1360
|
"offsetY": {
|
|
1367
|
-
"value":
|
|
1361
|
+
"value": 1,
|
|
1368
1362
|
"unit": "px"
|
|
1369
1363
|
},
|
|
1370
1364
|
"blur": {
|
|
@@ -1382,7 +1376,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1382
1376
|
0,
|
|
1383
1377
|
0
|
|
1384
1378
|
],
|
|
1385
|
-
"alpha": 0.
|
|
1379
|
+
"alpha": 0.05
|
|
1386
1380
|
}
|
|
1387
1381
|
},
|
|
1388
1382
|
{
|
|
@@ -1391,25 +1385,25 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1391
1385
|
"unit": "px"
|
|
1392
1386
|
},
|
|
1393
1387
|
"offsetY": {
|
|
1394
|
-
"value":
|
|
1388
|
+
"value": 2,
|
|
1395
1389
|
"unit": "px"
|
|
1396
1390
|
},
|
|
1397
1391
|
"blur": {
|
|
1398
|
-
"value":
|
|
1392
|
+
"value": 8,
|
|
1399
1393
|
"unit": "px"
|
|
1400
1394
|
},
|
|
1401
1395
|
"spread": {
|
|
1402
|
-
"value":
|
|
1396
|
+
"value": -2,
|
|
1403
1397
|
"unit": "px"
|
|
1404
1398
|
},
|
|
1405
1399
|
"color": {
|
|
1406
1400
|
"colorSpace": "srgb",
|
|
1407
1401
|
"components": [
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1402
|
+
0,
|
|
1403
|
+
0,
|
|
1404
|
+
0
|
|
1411
1405
|
],
|
|
1412
|
-
"alpha":
|
|
1406
|
+
"alpha": 0.06
|
|
1413
1407
|
}
|
|
1414
1408
|
}
|
|
1415
1409
|
]
|
|
@@ -1449,7 +1443,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1449
1443
|
"unit": "px"
|
|
1450
1444
|
},
|
|
1451
1445
|
"offsetY": {
|
|
1452
|
-
"value":
|
|
1446
|
+
"value": 1,
|
|
1453
1447
|
"unit": "px"
|
|
1454
1448
|
},
|
|
1455
1449
|
"blur": {
|
|
@@ -1467,7 +1461,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1467
1461
|
0,
|
|
1468
1462
|
0
|
|
1469
1463
|
],
|
|
1470
|
-
"alpha": 0.
|
|
1464
|
+
"alpha": 0.06
|
|
1471
1465
|
}
|
|
1472
1466
|
},
|
|
1473
1467
|
{
|
|
@@ -1476,15 +1470,15 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1476
1470
|
"unit": "px"
|
|
1477
1471
|
},
|
|
1478
1472
|
"offsetY": {
|
|
1479
|
-
"value":
|
|
1473
|
+
"value": 6,
|
|
1480
1474
|
"unit": "px"
|
|
1481
1475
|
},
|
|
1482
1476
|
"blur": {
|
|
1483
|
-
"value":
|
|
1477
|
+
"value": 12,
|
|
1484
1478
|
"unit": "px"
|
|
1485
1479
|
},
|
|
1486
1480
|
"spread": {
|
|
1487
|
-
"value": -
|
|
1481
|
+
"value": -4,
|
|
1488
1482
|
"unit": "px"
|
|
1489
1483
|
},
|
|
1490
1484
|
"color": {
|
|
@@ -1494,7 +1488,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1494
1488
|
0,
|
|
1495
1489
|
0
|
|
1496
1490
|
],
|
|
1497
|
-
"alpha": 0.
|
|
1491
|
+
"alpha": 0.08
|
|
1498
1492
|
}
|
|
1499
1493
|
},
|
|
1500
1494
|
{
|
|
@@ -1503,25 +1497,25 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1503
1497
|
"unit": "px"
|
|
1504
1498
|
},
|
|
1505
1499
|
"offsetY": {
|
|
1506
|
-
"value":
|
|
1500
|
+
"value": 16,
|
|
1507
1501
|
"unit": "px"
|
|
1508
1502
|
},
|
|
1509
1503
|
"blur": {
|
|
1510
|
-
"value":
|
|
1504
|
+
"value": 32,
|
|
1511
1505
|
"unit": "px"
|
|
1512
1506
|
},
|
|
1513
1507
|
"spread": {
|
|
1514
|
-
"value":
|
|
1508
|
+
"value": -8,
|
|
1515
1509
|
"unit": "px"
|
|
1516
1510
|
},
|
|
1517
1511
|
"color": {
|
|
1518
1512
|
"colorSpace": "srgb",
|
|
1519
1513
|
"components": [
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1514
|
+
0,
|
|
1515
|
+
0,
|
|
1516
|
+
0
|
|
1523
1517
|
],
|
|
1524
|
-
"alpha": 1
|
|
1518
|
+
"alpha": 0.1
|
|
1525
1519
|
}
|
|
1526
1520
|
}
|
|
1527
1521
|
]
|
|
@@ -1561,11 +1555,11 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1561
1555
|
"unit": "px"
|
|
1562
1556
|
},
|
|
1563
1557
|
"offsetY": {
|
|
1564
|
-
"value":
|
|
1558
|
+
"value": 2,
|
|
1565
1559
|
"unit": "px"
|
|
1566
1560
|
},
|
|
1567
1561
|
"blur": {
|
|
1568
|
-
"value":
|
|
1562
|
+
"value": 4,
|
|
1569
1563
|
"unit": "px"
|
|
1570
1564
|
},
|
|
1571
1565
|
"spread": {
|
|
@@ -1579,7 +1573,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1579
1573
|
0,
|
|
1580
1574
|
0
|
|
1581
1575
|
],
|
|
1582
|
-
"alpha": 0.
|
|
1576
|
+
"alpha": 0.06
|
|
1583
1577
|
}
|
|
1584
1578
|
},
|
|
1585
1579
|
{
|
|
@@ -1588,15 +1582,15 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1588
1582
|
"unit": "px"
|
|
1589
1583
|
},
|
|
1590
1584
|
"offsetY": {
|
|
1591
|
-
"value":
|
|
1585
|
+
"value": 12,
|
|
1592
1586
|
"unit": "px"
|
|
1593
1587
|
},
|
|
1594
1588
|
"blur": {
|
|
1595
|
-
"value":
|
|
1589
|
+
"value": 24,
|
|
1596
1590
|
"unit": "px"
|
|
1597
1591
|
},
|
|
1598
1592
|
"spread": {
|
|
1599
|
-
"value": -
|
|
1593
|
+
"value": -6,
|
|
1600
1594
|
"unit": "px"
|
|
1601
1595
|
},
|
|
1602
1596
|
"color": {
|
|
@@ -1606,7 +1600,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1606
1600
|
0,
|
|
1607
1601
|
0
|
|
1608
1602
|
],
|
|
1609
|
-
"alpha": 0.
|
|
1603
|
+
"alpha": 0.12
|
|
1610
1604
|
}
|
|
1611
1605
|
},
|
|
1612
1606
|
{
|
|
@@ -1615,15 +1609,15 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1615
1609
|
"unit": "px"
|
|
1616
1610
|
},
|
|
1617
1611
|
"offsetY": {
|
|
1618
|
-
"value":
|
|
1612
|
+
"value": 32,
|
|
1619
1613
|
"unit": "px"
|
|
1620
1614
|
},
|
|
1621
1615
|
"blur": {
|
|
1622
|
-
"value":
|
|
1616
|
+
"value": 64,
|
|
1623
1617
|
"unit": "px"
|
|
1624
1618
|
},
|
|
1625
1619
|
"spread": {
|
|
1626
|
-
"value": -
|
|
1620
|
+
"value": -16,
|
|
1627
1621
|
"unit": "px"
|
|
1628
1622
|
},
|
|
1629
1623
|
"color": {
|
|
@@ -1633,9 +1627,13 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1633
1627
|
0,
|
|
1634
1628
|
0
|
|
1635
1629
|
],
|
|
1636
|
-
"alpha": 0.
|
|
1630
|
+
"alpha": 0.16
|
|
1637
1631
|
}
|
|
1638
|
-
}
|
|
1632
|
+
}
|
|
1633
|
+
]
|
|
1634
|
+
},
|
|
1635
|
+
"modal": {
|
|
1636
|
+
"$value": [
|
|
1639
1637
|
{
|
|
1640
1638
|
"offsetX": {
|
|
1641
1639
|
"value": 0,
|
|
@@ -1656,32 +1654,28 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1656
1654
|
"color": {
|
|
1657
1655
|
"colorSpace": "srgb",
|
|
1658
1656
|
"components": [
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1657
|
+
0,
|
|
1658
|
+
0,
|
|
1659
|
+
0
|
|
1662
1660
|
],
|
|
1663
|
-
"alpha":
|
|
1661
|
+
"alpha": 0.08
|
|
1664
1662
|
}
|
|
1665
|
-
}
|
|
1666
|
-
]
|
|
1667
|
-
},
|
|
1668
|
-
"modal": {
|
|
1669
|
-
"$value": [
|
|
1663
|
+
},
|
|
1670
1664
|
{
|
|
1671
1665
|
"offsetX": {
|
|
1672
1666
|
"value": 0,
|
|
1673
1667
|
"unit": "px"
|
|
1674
1668
|
},
|
|
1675
1669
|
"offsetY": {
|
|
1676
|
-
"value":
|
|
1670
|
+
"value": 2,
|
|
1677
1671
|
"unit": "px"
|
|
1678
1672
|
},
|
|
1679
1673
|
"blur": {
|
|
1680
|
-
"value":
|
|
1674
|
+
"value": 4,
|
|
1681
1675
|
"unit": "px"
|
|
1682
1676
|
},
|
|
1683
1677
|
"spread": {
|
|
1684
|
-
"value":
|
|
1678
|
+
"value": 0,
|
|
1685
1679
|
"unit": "px"
|
|
1686
1680
|
},
|
|
1687
1681
|
"color": {
|
|
@@ -1691,7 +1685,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1691
1685
|
0,
|
|
1692
1686
|
0
|
|
1693
1687
|
],
|
|
1694
|
-
"alpha": 0.
|
|
1688
|
+
"alpha": 0.06
|
|
1695
1689
|
}
|
|
1696
1690
|
},
|
|
1697
1691
|
{
|
|
@@ -1700,15 +1694,15 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1700
1694
|
"unit": "px"
|
|
1701
1695
|
},
|
|
1702
1696
|
"offsetY": {
|
|
1703
|
-
"value":
|
|
1697
|
+
"value": 24,
|
|
1704
1698
|
"unit": "px"
|
|
1705
1699
|
},
|
|
1706
1700
|
"blur": {
|
|
1707
|
-
"value":
|
|
1701
|
+
"value": 48,
|
|
1708
1702
|
"unit": "px"
|
|
1709
1703
|
},
|
|
1710
1704
|
"spread": {
|
|
1711
|
-
"value":
|
|
1705
|
+
"value": -12,
|
|
1712
1706
|
"unit": "px"
|
|
1713
1707
|
},
|
|
1714
1708
|
"color": {
|
|
@@ -1718,7 +1712,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1718
1712
|
0,
|
|
1719
1713
|
0
|
|
1720
1714
|
],
|
|
1721
|
-
"alpha": 0.
|
|
1715
|
+
"alpha": 0.18
|
|
1722
1716
|
}
|
|
1723
1717
|
},
|
|
1724
1718
|
{
|
|
@@ -1727,15 +1721,15 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1727
1721
|
"unit": "px"
|
|
1728
1722
|
},
|
|
1729
1723
|
"offsetY": {
|
|
1730
|
-
"value":
|
|
1724
|
+
"value": 64,
|
|
1731
1725
|
"unit": "px"
|
|
1732
1726
|
},
|
|
1733
1727
|
"blur": {
|
|
1734
|
-
"value":
|
|
1728
|
+
"value": 128,
|
|
1735
1729
|
"unit": "px"
|
|
1736
1730
|
},
|
|
1737
1731
|
"spread": {
|
|
1738
|
-
"value": -
|
|
1732
|
+
"value": -32,
|
|
1739
1733
|
"unit": "px"
|
|
1740
1734
|
},
|
|
1741
1735
|
"color": {
|
|
@@ -1745,35 +1739,40 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1745
1739
|
0,
|
|
1746
1740
|
0
|
|
1747
1741
|
],
|
|
1748
|
-
"alpha": 0.
|
|
1742
|
+
"alpha": 0.26
|
|
1749
1743
|
}
|
|
1750
|
-
}
|
|
1744
|
+
}
|
|
1745
|
+
]
|
|
1746
|
+
},
|
|
1747
|
+
"glass": {
|
|
1748
|
+
"$value": [
|
|
1751
1749
|
{
|
|
1752
1750
|
"offsetX": {
|
|
1753
1751
|
"value": 0,
|
|
1754
1752
|
"unit": "px"
|
|
1755
1753
|
},
|
|
1756
1754
|
"offsetY": {
|
|
1757
|
-
"value":
|
|
1755
|
+
"value": 1,
|
|
1758
1756
|
"unit": "px"
|
|
1759
1757
|
},
|
|
1760
1758
|
"blur": {
|
|
1761
|
-
"value":
|
|
1759
|
+
"value": 0,
|
|
1762
1760
|
"unit": "px"
|
|
1763
1761
|
},
|
|
1764
1762
|
"spread": {
|
|
1765
|
-
"value":
|
|
1763
|
+
"value": 0,
|
|
1766
1764
|
"unit": "px"
|
|
1767
1765
|
},
|
|
1768
1766
|
"color": {
|
|
1769
1767
|
"colorSpace": "srgb",
|
|
1770
1768
|
"components": [
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1769
|
+
1,
|
|
1770
|
+
1,
|
|
1771
|
+
1
|
|
1774
1772
|
],
|
|
1775
|
-
"alpha": 0.
|
|
1776
|
-
}
|
|
1773
|
+
"alpha": 0.75
|
|
1774
|
+
},
|
|
1775
|
+
"inset": true
|
|
1777
1776
|
},
|
|
1778
1777
|
{
|
|
1779
1778
|
"offsetX": {
|
|
@@ -1799,15 +1798,10 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1799
1798
|
1,
|
|
1800
1799
|
1
|
|
1801
1800
|
],
|
|
1802
|
-
"alpha":
|
|
1803
|
-
}
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
}
|
|
1807
|
-
},
|
|
1808
|
-
"dark": {
|
|
1809
|
-
"resting": {
|
|
1810
|
-
"$value": [
|
|
1801
|
+
"alpha": 0.35
|
|
1802
|
+
},
|
|
1803
|
+
"inset": true
|
|
1804
|
+
},
|
|
1811
1805
|
{
|
|
1812
1806
|
"offsetX": {
|
|
1813
1807
|
"value": 0,
|
|
@@ -1828,11 +1822,11 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1828
1822
|
"color": {
|
|
1829
1823
|
"colorSpace": "srgb",
|
|
1830
1824
|
"components": [
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1825
|
+
0,
|
|
1826
|
+
0,
|
|
1827
|
+
0
|
|
1834
1828
|
],
|
|
1835
|
-
"alpha": 0.
|
|
1829
|
+
"alpha": 0.07
|
|
1836
1830
|
}
|
|
1837
1831
|
},
|
|
1838
1832
|
{
|
|
@@ -1841,11 +1835,11 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1841
1835
|
"unit": "px"
|
|
1842
1836
|
},
|
|
1843
1837
|
"offsetY": {
|
|
1844
|
-
"value":
|
|
1838
|
+
"value": 2,
|
|
1845
1839
|
"unit": "px"
|
|
1846
1840
|
},
|
|
1847
1841
|
"blur": {
|
|
1848
|
-
"value":
|
|
1842
|
+
"value": 4,
|
|
1849
1843
|
"unit": "px"
|
|
1850
1844
|
},
|
|
1851
1845
|
"spread": {
|
|
@@ -1859,7 +1853,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1859
1853
|
0,
|
|
1860
1854
|
0
|
|
1861
1855
|
],
|
|
1862
|
-
"alpha": 0.
|
|
1856
|
+
"alpha": 0.06
|
|
1863
1857
|
}
|
|
1864
1858
|
},
|
|
1865
1859
|
{
|
|
@@ -1868,15 +1862,42 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1868
1862
|
"unit": "px"
|
|
1869
1863
|
},
|
|
1870
1864
|
"offsetY": {
|
|
1871
|
-
"value":
|
|
1865
|
+
"value": 12,
|
|
1872
1866
|
"unit": "px"
|
|
1873
1867
|
},
|
|
1874
1868
|
"blur": {
|
|
1869
|
+
"value": 24,
|
|
1870
|
+
"unit": "px"
|
|
1871
|
+
},
|
|
1872
|
+
"spread": {
|
|
1873
|
+
"value": -6,
|
|
1874
|
+
"unit": "px"
|
|
1875
|
+
},
|
|
1876
|
+
"color": {
|
|
1877
|
+
"colorSpace": "srgb",
|
|
1878
|
+
"components": [
|
|
1879
|
+
0,
|
|
1880
|
+
0,
|
|
1881
|
+
0
|
|
1882
|
+
],
|
|
1883
|
+
"alpha": 0.12
|
|
1884
|
+
}
|
|
1885
|
+
},
|
|
1886
|
+
{
|
|
1887
|
+
"offsetX": {
|
|
1875
1888
|
"value": 0,
|
|
1876
1889
|
"unit": "px"
|
|
1877
1890
|
},
|
|
1891
|
+
"offsetY": {
|
|
1892
|
+
"value": 32,
|
|
1893
|
+
"unit": "px"
|
|
1894
|
+
},
|
|
1895
|
+
"blur": {
|
|
1896
|
+
"value": 64,
|
|
1897
|
+
"unit": "px"
|
|
1898
|
+
},
|
|
1878
1899
|
"spread": {
|
|
1879
|
-
"value":
|
|
1900
|
+
"value": -16,
|
|
1880
1901
|
"unit": "px"
|
|
1881
1902
|
},
|
|
1882
1903
|
"color": {
|
|
@@ -1886,13 +1907,43 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1886
1907
|
0,
|
|
1887
1908
|
0
|
|
1888
1909
|
],
|
|
1889
|
-
"alpha":
|
|
1910
|
+
"alpha": 0.16
|
|
1890
1911
|
}
|
|
1891
1912
|
}
|
|
1892
1913
|
]
|
|
1893
|
-
}
|
|
1894
|
-
|
|
1914
|
+
}
|
|
1915
|
+
},
|
|
1916
|
+
"dark": {
|
|
1917
|
+
"resting": {
|
|
1895
1918
|
"$value": [
|
|
1919
|
+
{
|
|
1920
|
+
"offsetX": {
|
|
1921
|
+
"value": 0,
|
|
1922
|
+
"unit": "px"
|
|
1923
|
+
},
|
|
1924
|
+
"offsetY": {
|
|
1925
|
+
"value": 1,
|
|
1926
|
+
"unit": "px"
|
|
1927
|
+
},
|
|
1928
|
+
"blur": {
|
|
1929
|
+
"value": 0,
|
|
1930
|
+
"unit": "px"
|
|
1931
|
+
},
|
|
1932
|
+
"spread": {
|
|
1933
|
+
"value": 0,
|
|
1934
|
+
"unit": "px"
|
|
1935
|
+
},
|
|
1936
|
+
"color": {
|
|
1937
|
+
"colorSpace": "srgb",
|
|
1938
|
+
"components": [
|
|
1939
|
+
1,
|
|
1940
|
+
1,
|
|
1941
|
+
1
|
|
1942
|
+
],
|
|
1943
|
+
"alpha": 0.05
|
|
1944
|
+
},
|
|
1945
|
+
"inset": true
|
|
1946
|
+
},
|
|
1896
1947
|
{
|
|
1897
1948
|
"offsetX": {
|
|
1898
1949
|
"value": 0,
|
|
@@ -1917,7 +1968,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1917
1968
|
1,
|
|
1918
1969
|
1
|
|
1919
1970
|
],
|
|
1920
|
-
"alpha": 0.
|
|
1971
|
+
"alpha": 0.08
|
|
1921
1972
|
}
|
|
1922
1973
|
},
|
|
1923
1974
|
{
|
|
@@ -1926,7 +1977,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1926
1977
|
"unit": "px"
|
|
1927
1978
|
},
|
|
1928
1979
|
"offsetY": {
|
|
1929
|
-
"value":
|
|
1980
|
+
"value": 1,
|
|
1930
1981
|
"unit": "px"
|
|
1931
1982
|
},
|
|
1932
1983
|
"blur": {
|
|
@@ -1944,35 +1995,40 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1944
1995
|
0,
|
|
1945
1996
|
0
|
|
1946
1997
|
],
|
|
1947
|
-
"alpha": 0.
|
|
1998
|
+
"alpha": 0.6
|
|
1948
1999
|
}
|
|
1949
|
-
}
|
|
2000
|
+
}
|
|
2001
|
+
]
|
|
2002
|
+
},
|
|
2003
|
+
"raised": {
|
|
2004
|
+
"$value": [
|
|
1950
2005
|
{
|
|
1951
2006
|
"offsetX": {
|
|
1952
2007
|
"value": 0,
|
|
1953
2008
|
"unit": "px"
|
|
1954
2009
|
},
|
|
1955
2010
|
"offsetY": {
|
|
1956
|
-
"value":
|
|
2011
|
+
"value": 1,
|
|
1957
2012
|
"unit": "px"
|
|
1958
2013
|
},
|
|
1959
2014
|
"blur": {
|
|
1960
|
-
"value":
|
|
2015
|
+
"value": 0,
|
|
1961
2016
|
"unit": "px"
|
|
1962
2017
|
},
|
|
1963
2018
|
"spread": {
|
|
1964
|
-
"value":
|
|
2019
|
+
"value": 0,
|
|
1965
2020
|
"unit": "px"
|
|
1966
2021
|
},
|
|
1967
2022
|
"color": {
|
|
1968
2023
|
"colorSpace": "srgb",
|
|
1969
2024
|
"components": [
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
2025
|
+
1,
|
|
2026
|
+
1,
|
|
2027
|
+
1
|
|
1973
2028
|
],
|
|
1974
|
-
"alpha": 0.
|
|
1975
|
-
}
|
|
2029
|
+
"alpha": 0.07
|
|
2030
|
+
},
|
|
2031
|
+
"inset": true
|
|
1976
2032
|
},
|
|
1977
2033
|
{
|
|
1978
2034
|
"offsetX": {
|
|
@@ -1991,6 +2047,33 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1991
2047
|
"value": 1,
|
|
1992
2048
|
"unit": "px"
|
|
1993
2049
|
},
|
|
2050
|
+
"color": {
|
|
2051
|
+
"colorSpace": "srgb",
|
|
2052
|
+
"components": [
|
|
2053
|
+
1,
|
|
2054
|
+
1,
|
|
2055
|
+
1
|
|
2056
|
+
],
|
|
2057
|
+
"alpha": 0.1
|
|
2058
|
+
}
|
|
2059
|
+
},
|
|
2060
|
+
{
|
|
2061
|
+
"offsetX": {
|
|
2062
|
+
"value": 0,
|
|
2063
|
+
"unit": "px"
|
|
2064
|
+
},
|
|
2065
|
+
"offsetY": {
|
|
2066
|
+
"value": 16,
|
|
2067
|
+
"unit": "px"
|
|
2068
|
+
},
|
|
2069
|
+
"blur": {
|
|
2070
|
+
"value": 32,
|
|
2071
|
+
"unit": "px"
|
|
2072
|
+
},
|
|
2073
|
+
"spread": {
|
|
2074
|
+
"value": -8,
|
|
2075
|
+
"unit": "px"
|
|
2076
|
+
},
|
|
1994
2077
|
"color": {
|
|
1995
2078
|
"colorSpace": "srgb",
|
|
1996
2079
|
"components": [
|
|
@@ -1998,7 +2081,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
1998
2081
|
0,
|
|
1999
2082
|
0
|
|
2000
2083
|
],
|
|
2001
|
-
"alpha":
|
|
2084
|
+
"alpha": 0.6
|
|
2002
2085
|
}
|
|
2003
2086
|
}
|
|
2004
2087
|
]
|
|
@@ -2011,7 +2094,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2011
2094
|
"unit": "px"
|
|
2012
2095
|
},
|
|
2013
2096
|
"offsetY": {
|
|
2014
|
-
"value":
|
|
2097
|
+
"value": 1,
|
|
2015
2098
|
"unit": "px"
|
|
2016
2099
|
},
|
|
2017
2100
|
"blur": {
|
|
@@ -2019,7 +2102,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2019
2102
|
"unit": "px"
|
|
2020
2103
|
},
|
|
2021
2104
|
"spread": {
|
|
2022
|
-
"value":
|
|
2105
|
+
"value": 0,
|
|
2023
2106
|
"unit": "px"
|
|
2024
2107
|
},
|
|
2025
2108
|
"color": {
|
|
@@ -2029,8 +2112,9 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2029
2112
|
1,
|
|
2030
2113
|
1
|
|
2031
2114
|
],
|
|
2032
|
-
"alpha": 0.
|
|
2033
|
-
}
|
|
2115
|
+
"alpha": 0.09
|
|
2116
|
+
},
|
|
2117
|
+
"inset": true
|
|
2034
2118
|
},
|
|
2035
2119
|
{
|
|
2036
2120
|
"offsetX": {
|
|
@@ -2038,25 +2122,25 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2038
2122
|
"unit": "px"
|
|
2039
2123
|
},
|
|
2040
2124
|
"offsetY": {
|
|
2041
|
-
"value":
|
|
2125
|
+
"value": 0,
|
|
2042
2126
|
"unit": "px"
|
|
2043
2127
|
},
|
|
2044
2128
|
"blur": {
|
|
2045
|
-
"value":
|
|
2129
|
+
"value": 0,
|
|
2046
2130
|
"unit": "px"
|
|
2047
2131
|
},
|
|
2048
2132
|
"spread": {
|
|
2049
|
-
"value":
|
|
2133
|
+
"value": 1,
|
|
2050
2134
|
"unit": "px"
|
|
2051
2135
|
},
|
|
2052
2136
|
"color": {
|
|
2053
2137
|
"colorSpace": "srgb",
|
|
2054
2138
|
"components": [
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2139
|
+
1,
|
|
2140
|
+
1,
|
|
2141
|
+
1
|
|
2058
2142
|
],
|
|
2059
|
-
"alpha": 0.
|
|
2143
|
+
"alpha": 0.12
|
|
2060
2144
|
}
|
|
2061
2145
|
},
|
|
2062
2146
|
{
|
|
@@ -2065,15 +2149,15 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2065
2149
|
"unit": "px"
|
|
2066
2150
|
},
|
|
2067
2151
|
"offsetY": {
|
|
2068
|
-
"value":
|
|
2152
|
+
"value": 32,
|
|
2069
2153
|
"unit": "px"
|
|
2070
2154
|
},
|
|
2071
2155
|
"blur": {
|
|
2072
|
-
"value":
|
|
2156
|
+
"value": 64,
|
|
2073
2157
|
"unit": "px"
|
|
2074
2158
|
},
|
|
2075
2159
|
"spread": {
|
|
2076
|
-
"value": -
|
|
2160
|
+
"value": -16,
|
|
2077
2161
|
"unit": "px"
|
|
2078
2162
|
},
|
|
2079
2163
|
"color": {
|
|
@@ -2083,16 +2167,20 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2083
2167
|
0,
|
|
2084
2168
|
0
|
|
2085
2169
|
],
|
|
2086
|
-
"alpha": 0.
|
|
2170
|
+
"alpha": 0.7
|
|
2087
2171
|
}
|
|
2088
|
-
}
|
|
2172
|
+
}
|
|
2173
|
+
]
|
|
2174
|
+
},
|
|
2175
|
+
"modal": {
|
|
2176
|
+
"$value": [
|
|
2089
2177
|
{
|
|
2090
2178
|
"offsetX": {
|
|
2091
2179
|
"value": 0,
|
|
2092
2180
|
"unit": "px"
|
|
2093
2181
|
},
|
|
2094
2182
|
"offsetY": {
|
|
2095
|
-
"value":
|
|
2183
|
+
"value": 1,
|
|
2096
2184
|
"unit": "px"
|
|
2097
2185
|
},
|
|
2098
2186
|
"blur": {
|
|
@@ -2100,23 +2188,20 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2100
2188
|
"unit": "px"
|
|
2101
2189
|
},
|
|
2102
2190
|
"spread": {
|
|
2103
|
-
"value":
|
|
2191
|
+
"value": 0,
|
|
2104
2192
|
"unit": "px"
|
|
2105
2193
|
},
|
|
2106
2194
|
"color": {
|
|
2107
2195
|
"colorSpace": "srgb",
|
|
2108
2196
|
"components": [
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2197
|
+
1,
|
|
2198
|
+
1,
|
|
2199
|
+
1
|
|
2112
2200
|
],
|
|
2113
|
-
"alpha":
|
|
2114
|
-
}
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
},
|
|
2118
|
-
"modal": {
|
|
2119
|
-
"$value": [
|
|
2201
|
+
"alpha": 0.11
|
|
2202
|
+
},
|
|
2203
|
+
"inset": true
|
|
2204
|
+
},
|
|
2120
2205
|
{
|
|
2121
2206
|
"offsetX": {
|
|
2122
2207
|
"value": 0,
|
|
@@ -2141,7 +2226,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2141
2226
|
1,
|
|
2142
2227
|
1
|
|
2143
2228
|
],
|
|
2144
|
-
"alpha": 0.
|
|
2229
|
+
"alpha": 0.14
|
|
2145
2230
|
}
|
|
2146
2231
|
},
|
|
2147
2232
|
{
|
|
@@ -2150,15 +2235,15 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2150
2235
|
"unit": "px"
|
|
2151
2236
|
},
|
|
2152
2237
|
"offsetY": {
|
|
2153
|
-
"value":
|
|
2238
|
+
"value": 64,
|
|
2154
2239
|
"unit": "px"
|
|
2155
2240
|
},
|
|
2156
2241
|
"blur": {
|
|
2157
|
-
"value":
|
|
2242
|
+
"value": 128,
|
|
2158
2243
|
"unit": "px"
|
|
2159
2244
|
},
|
|
2160
2245
|
"spread": {
|
|
2161
|
-
"value": -
|
|
2246
|
+
"value": -32,
|
|
2162
2247
|
"unit": "px"
|
|
2163
2248
|
},
|
|
2164
2249
|
"color": {
|
|
@@ -2168,35 +2253,40 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2168
2253
|
0,
|
|
2169
2254
|
0
|
|
2170
2255
|
],
|
|
2171
|
-
"alpha": 0.
|
|
2256
|
+
"alpha": 0.8
|
|
2172
2257
|
}
|
|
2173
|
-
}
|
|
2258
|
+
}
|
|
2259
|
+
]
|
|
2260
|
+
},
|
|
2261
|
+
"glass": {
|
|
2262
|
+
"$value": [
|
|
2174
2263
|
{
|
|
2175
2264
|
"offsetX": {
|
|
2176
2265
|
"value": 0,
|
|
2177
2266
|
"unit": "px"
|
|
2178
2267
|
},
|
|
2179
2268
|
"offsetY": {
|
|
2180
|
-
"value":
|
|
2269
|
+
"value": 1,
|
|
2181
2270
|
"unit": "px"
|
|
2182
2271
|
},
|
|
2183
2272
|
"blur": {
|
|
2184
|
-
"value":
|
|
2273
|
+
"value": 0,
|
|
2185
2274
|
"unit": "px"
|
|
2186
2275
|
},
|
|
2187
2276
|
"spread": {
|
|
2188
|
-
"value":
|
|
2277
|
+
"value": 0,
|
|
2189
2278
|
"unit": "px"
|
|
2190
2279
|
},
|
|
2191
2280
|
"color": {
|
|
2192
2281
|
"colorSpace": "srgb",
|
|
2193
2282
|
"components": [
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2283
|
+
1,
|
|
2284
|
+
1,
|
|
2285
|
+
1
|
|
2197
2286
|
],
|
|
2198
|
-
"alpha": 0.
|
|
2199
|
-
}
|
|
2287
|
+
"alpha": 0.12
|
|
2288
|
+
},
|
|
2289
|
+
"inset": true
|
|
2200
2290
|
},
|
|
2201
2291
|
{
|
|
2202
2292
|
"offsetX": {
|
|
@@ -2215,6 +2305,33 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2215
2305
|
"value": 1,
|
|
2216
2306
|
"unit": "px"
|
|
2217
2307
|
},
|
|
2308
|
+
"color": {
|
|
2309
|
+
"colorSpace": "srgb",
|
|
2310
|
+
"components": [
|
|
2311
|
+
1,
|
|
2312
|
+
1,
|
|
2313
|
+
1
|
|
2314
|
+
],
|
|
2315
|
+
"alpha": 0.12
|
|
2316
|
+
}
|
|
2317
|
+
},
|
|
2318
|
+
{
|
|
2319
|
+
"offsetX": {
|
|
2320
|
+
"value": 0,
|
|
2321
|
+
"unit": "px"
|
|
2322
|
+
},
|
|
2323
|
+
"offsetY": {
|
|
2324
|
+
"value": 32,
|
|
2325
|
+
"unit": "px"
|
|
2326
|
+
},
|
|
2327
|
+
"blur": {
|
|
2328
|
+
"value": 64,
|
|
2329
|
+
"unit": "px"
|
|
2330
|
+
},
|
|
2331
|
+
"spread": {
|
|
2332
|
+
"value": -16,
|
|
2333
|
+
"unit": "px"
|
|
2334
|
+
},
|
|
2218
2335
|
"color": {
|
|
2219
2336
|
"colorSpace": "srgb",
|
|
2220
2337
|
"components": [
|
|
@@ -2222,7 +2339,7 @@ The YAML front matter holds the four groups the DESIGN.md format defines: colors
|
|
|
2222
2339
|
0,
|
|
2223
2340
|
0
|
|
2224
2341
|
],
|
|
2225
|
-
"alpha":
|
|
2342
|
+
"alpha": 0.7
|
|
2226
2343
|
}
|
|
2227
2344
|
}
|
|
2228
2345
|
]
|