@synopackageland/ui 0.23.8 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/callout.md CHANGED
@@ -103,9 +103,9 @@ halfway across. A Callout drops it: it stays on the page, where DSM draws its
103
103
  notes with no decoration.
104
104
 
105
105
  The title reads in the text colour at 600, and the message under it in the
106
- secondary text colour. Corners are 12px (`--ui-callout-radius`), rounder than
107
- a card on purpose: a Callout floats above the settings rather than being one
108
- of them. Buttons in `#actions` and a toast's action are capsules. A Callout
106
+ secondary text colour. Corners follow `--ui-radius-callout` (10px in a DSM window, 12px on a full
107
+ page and mobile; `--ui-callout-radius` overrides it), rounder than a card on
108
+ purpose: a Callout floats above the settings rather than being one of them. Buttons in `#actions` and a toast's action are capsules. A Callout
109
109
  fades in and rises 6px when it appears, and a toast slides in; with reduced
110
110
  motion both appear at once.
111
111
 
@@ -22,6 +22,37 @@ App. Each line links to its details below.
22
22
  | No end space under docked bars | The room under the last row is constant (`--ui-page-end-space`, plus `--ui-bars-room` under docked bars); a fill page's list runs under the FAB and bars to the screen's bottom with no blank band, also when that list is an App's own element nested in the page. |
23
23
  | Gesture velocity | One estimator and one set of thresholds for every gesture decision the UI makes. See [Gesture velocity](#gesture-velocity). |
24
24
 
25
+ ## Phone look
26
+
27
+ Since 0.25 a touch phone (narrow and a coarse pointer, the phone tokens'
28
+ gate) draws softer than a DSM window: a pale page with white cards on it and
29
+ no frames, round corners, more air and bigger text. It is all in
30
+ `src/theme/phone.css`, inside `@media (pointer: coarse)` and scoped to the
31
+ phone presentation; a desktop, a DSM window (also one narrowed with a mouse)
32
+ and a touch tablet are unchanged. Tap boxes, bar heights, hide on scroll and
33
+ the commit footer behave as before.
34
+
35
+ | Token or part | Before (phone) | Phone look |
36
+ | --- | --- | --- |
37
+ | Page under cards (`--ui-page-canvas`) | `#fafbf9` | `#f1f3f0` (dark: the dark page, `#121513`) |
38
+ | Card | white, 1px frame, card shadow, 6px corner | white, no frame, 1px soft shadow (none in dark), `--ui-radius-card` 20px |
39
+ | Section list (SectionTabs' phone list) | framed group, 6px corner, 44px rows, full-width rules | inset grouped list: white group, 20px corner, 52px rows, hairlines inset 16px, on the mist |
40
+ | A list of ListItems on the page (`role="list"`, `ul`, `ol`, outside a card, sheet or dialog) | full-bleed rows, full-width rules | the same inset grouped list: one white group per list, rows inset 16px, hairlines from the text's edge, the heading just above it inset to the text |
41
+ | Page background | the mist only on a page of cards | the mist on every page (not a data-grid page or `surface="none"`); a sticky row and `--ui-app-web-surface` follow it |
42
+ | `--ui-radius-md` / `-lg` (and the 0.23.9 roles on them) | 4 / 6 | 12 / 14: md rounds the control, container and popover roles (fields, tool buttons, inset blocks, menus), lg the panel and nav roles |
43
+ | `--ui-radius-dialog` / `-window` / `-sheet` | 8 / 8 / 12 | 24 |
44
+ | Primary, danger and secondary buttons | capsule (action) or 4px (tool) | capsule; a primary's fill is accent step 10 (`#0075db`, 4.6:1 with white) |
45
+ | Segmented control | accent pill on a framed track, equal columns | ink pill (`--ui-phone-ink`, `#1f2421`; dark `#e3e8e4`) on a frameless mist track; 6px sides; up to three segments stay equal columns but one whose label is wider than its share grows to it, so a label is not cut (four ellipsize as before) (`check:phone-layout` checks it) |
46
+ | Phone bar | white with a hairline | the page's colour, no hairline, 17px bold title, round pressed tint |
47
+ | Tab bar | full-width white row with a top rule | a floating white pill inset 16px, 8px above the bottom (`--ui-tab-bar-float`); the current tab is ink on a round pad |
48
+ | `--ui-text-muted` | 40% grey (2:1) | 80% (4.8:1 on the mist; dark 62%) |
49
+ | Separators | `--ui-border-subtle` | `--ui-phone-separator` |
50
+
51
+ An App that sets `--ui-mobile-bar-bg`, `--ui-mobile-bar-border` or
52
+ `--ui-tab-bar-bg` keeps its colour. The tab bar's box keeps the full width and
53
+ adds the float gap below the pill, so the room AppLayout measures for the
54
+ bottom bars, the FAB's offset and the end space follow it.
55
+
25
56
  ## Width containment and the release gate
26
57
 
27
58
  Typography tables scroll horizontally within their parent, including a flex
@@ -75,12 +106,12 @@ control and grid sizes; it does not change the 16px field rule.
75
106
 
76
107
  | Token | Desktop | Touch tablet | Phone | Used for |
77
108
  |---|---|---|---|---|
78
- | `--ui-font-size` | 13 | 13 | **14** | primary text: list and record titles, field values, body copy, menu items |
79
- | `--ui-font-size-sm` | 12 | 12 | **12** | secondary text: labels, meta, captions, helper text, badges |
109
+ | `--ui-font-size` | 13 | 13 | **15** | primary text: list and record titles, field values, body copy, menu items |
110
+ | `--ui-font-size-sm` | 12 | 12 | **13** | secondary text: labels, meta, captions, helper text, badges |
80
111
  | `--ui-font-size-xs` (new) | 12 | 12 | 12 | the smallest text anywhere |
81
- | `--ui-line-height` | 20 | 20 | **20** | body line |
82
- | `--ui-font-size-lg` | 14 | 14 | **15** | card and section titles |
83
- | `--ui-font-size-title` | 16 | 16 | **16** | header and dialog titles |
112
+ | `--ui-line-height` | 20 | 20 | **22** | body line |
113
+ | `--ui-font-size-lg` | 14 | 14 | **17** | card and section titles |
114
+ | `--ui-font-size-title` | 16 | 16 | **17** | header and dialog titles |
84
115
  | `--ui-grid-font-size` (new) | 13 | 13 | **14** | grid cell text (not yet read by the canvas grid; see below) |
85
116
  | `--ui-font-size-field` (new) | 16 | 16 | 16 | every field on a coarse pointer, to stop iOS focus zoom |
86
117
  | `--ui-control-md` | 28 | **44** | **44** | fields, selects, form and sheet buttons |
@@ -91,15 +122,15 @@ control and grid sizes; it does not change the 16px field rule.
91
122
  | `--ui-grid-row-height` / `-header-height` | 28 | **36** | **32** | canvas grid rows (docs/ux-grid.md) |
92
123
  | `--ui-list-row-height` | 32 | **44** | **44** | list rows, a DisclosureRow |
93
124
  | `--ui-menu-row-height` | 32 | **44** | **44** | menu, select and sheet list rows |
94
- | `--ui-page-padding-x` / `-y` | 16 (narrow layout 12) | 16 | **12** | page gutter |
95
- | `--ui-section-gap` | 12 | 12 | **12** | space between sections |
96
- | `--ui-card-padding` | 20 (Card default) | 20 | **12** | card inset |
125
+ | `--ui-page-padding-x` / `-y` | 16 (narrow layout 12) | 16 | **16 / 12** | page gutter |
126
+ | `--ui-section-gap` | 12 | 12 | **16** | space between sections |
127
+ | `--ui-card-padding` | 20 (Card default) | 20 | **16** | card inset |
97
128
  | `--ui-chrome-height` | 44 (web 48, narrow layout 44) | – | **44** | the phone bar (plus its 1px rule) |
98
129
  | `--ui-tab-bar-height` | – | – | **48** | the tab bar's row, above `--ui-safe-bottom` |
99
130
  | `--ui-section-tab-height` | 44 | 44 | **40** | the drawn height of a phone's tabs strip (its tap box stays 44) |
100
131
  | `--ui-sticky-top-offset` | 0 | 0 | measured | what sticks at the top of a PageContent (see below) |
101
132
  | `--ui-page-end-space` | 24 | 24 | 24 (constant: hiding the bars never changes it) | room after a page's last row |
102
- | `--ui-radius-sheet` (new) | 12 | 12 | 12 | top corners of a bottom sheet |
133
+ | `--ui-radius-sheet` (new) | 12 | 12 | **24** | top corners of a bottom sheet |
103
134
  | `--ui-safe-top/right/bottom/left` (new) | `env(safe-area-inset-*, 0px)` | same | same | notch and home indicator; non-zero only once the viewport meta has `viewport-fit=cover` |
104
135
  | `--ui-pressed` (new) | 8% of the text colour | same | same | the pressed tint |
105
136
 
@@ -182,7 +182,7 @@ before the token existed. Set them on the app root or any ancestor.
182
182
  | `--ui-mobile-bar-fg` | the phone bar's text, menu button and brand | `var(--ui-text-secondary)` (text), `var(--ui-text)` (button, brand) |
183
183
  | `--ui-mobile-bar-border` | the phone bar's bottom rule | `var(--ui-border-subtle)` |
184
184
  | `--ui-callout-max-width` | caps how wide a `Callout` grows; it spans its container by default | none |
185
- | `--ui-callout-radius` | a `Callout`'s and a `Toast`'s corners | 12px |
185
+ | `--ui-callout-radius` | a `Callout`'s and a `Toast`'s corners | `--ui-radius-callout` (window 10px, web and mobile 12px) |
186
186
  | `--ui-callout-glow` | how strong the tone's glow is behind a `Callout`'s or `Toast`'s icon; a dark theme raises it (workbench: 14%) | 9% |
187
187
  | `--ui-callout-shadow` | the shadow under a `Callout` and a `Toast` (workbench dark: `0 10px 28px -12px rgba(0, 0, 0, 0.6)`) | `0 8px 24px -12px rgba(15, 23, 42, 0.18)` |
188
188
 
@@ -190,10 +190,70 @@ The colour, radius, spacing and web tokens are listed in the
190
190
  [README](../README.md#theme-override), [colour system](color-system.md) and
191
191
  [adaptive layout](adaptive-layout.md#safe-overrides).
192
192
 
193
+ ## Corner radius
194
+
195
+ Components round their corners with a role, not a step, so a theme can round
196
+ one kind of surface without the others. Since 0.25 a DSM window rounds a step
197
+ softer than DSM's own 3-5px and a full page softer still; the mobile
198
+ presentation keeps the steps (a phone rounds them itself, `phone.css`):
199
+
200
+ | Token | Rounds | Window | Web | Mobile | Touch phone |
201
+ | --- | --- | --- | --- | --- | --- |
202
+ | `--ui-radius-inner` | a part inside a control or a popover: a menu row, a tag, a tooltip, a checkbox box, a small hit area | 4px | 6px | `sm` (3px) | 3px |
203
+ | `--ui-radius-control` | a button, a field, a select, a segment | 6px | 8px | `md` (4px) | 12px |
204
+ | `--ui-radius-container` | a flat block: a card's surface, an inset area, a thumbnail frame | 8px | 10px | `md` (4px) | 12px |
205
+ | `--ui-radius-popover` | a menu, a select or combobox list, a popover, a picker | 8px | 10px | `md` (4px) | 12px |
206
+ | `--ui-radius-panel` | a raised block: a choice card, a framed region, a drop zone, a side drawer, a grid card | 8px | 12px | `lg` (6px) | 14px |
207
+ | `--ui-radius-nav` | a navigation row in the sidebar or the top bar | 6px | 8px | `lg` (6px) | 14px |
208
+ | `--ui-radius-window` | a dialog with a title bar | 10px | 14px | 8px | 24px |
209
+ | `--ui-radius-dialog` | a message box | 10px | 14px | 8px | 24px |
210
+ | `--ui-radius-callout` | a `Callout` and a `Toast` (`--ui-callout-radius` still wins) | 10px | 12px | 12px | 12px |
211
+
212
+ A part inside a popover stays concentric with it: a menu row (`inner`, 4px) sits
213
+ 4px inside its menu (`popover`, 8px). What floats highest rounds most.
214
+
215
+ The steps `--ui-radius-sm`, `-md` and `-lg` stay public at DSM's 3, 4 and 5px
216
+ for an App's own parts. On the mobile presentation the roles follow the steps
217
+ (declared again on its root in `adaptive.css`), so a step overridden there
218
+ moves them. On a touch phone (docs/mobile-native.md, "Phone look") the phone
219
+ scope sets the steps `--ui-radius-md` to 12px and `-lg` to 14px, so the roles
220
+ follow them there; a card on a page of cards and a grouped list take
221
+ `--ui-radius-card` (20px), and a sheet `--ui-radius-sheet` (24px).
222
+
223
+ Override a role to change only that kind of surface:
224
+
225
+ ```css
226
+ :root {
227
+ --ui-radius-panel: 8px; /* choice cards and framed regions only */
228
+ --ui-radius-popover: 6px; /* menus and popovers only */
229
+ }
230
+ ```
231
+
232
+ To keep the pre-0.25 corners in a DSM window, set the roles back to the steps:
233
+ `inner` 3px, `control`, `container` and `popover` 4px, `panel` and `nav` 5px,
234
+ `window` 3px, `dialog` 6px, `callout` 12px.
235
+
236
+ ## Focus, hover and the scrim
237
+
238
+ | Token | What | Value |
239
+ | --- | --- | --- |
240
+ | `--ui-focus-ring` | the keyboard focus colour | the accent (`--ui-accent-9`), solid |
241
+ | `--ui-shadow-focus` | keyboard focus on a control: a 2px gap in the surface colour, then a 2px ring | `0 0 0 2px surface, 0 0 0 4px ring` |
242
+ | `--ui-shadow-focus-inset` | keyboard focus inside a row, a cell or a tab strip | `inset 0 0 0 2px ring` |
243
+ | `--ui-shadow-focus-field` | a focused field, whose own border turns primary: a soft halo | `0 0 0 3px` `--ui-focus-halo` (`--ui-accent-a4`) |
244
+ | `--ui-state-hover` | the pointer on a ghost button or a menu row | 6% of the text colour |
245
+ | `--ui-state-pressed` | pressed (a ghost button, a touch control while the finger is down) | 8% of the text colour; `--ui-pressed` is a deprecated alias |
246
+ | `--ui-surface-hover` | the pointer on a list or table row (DSM's pale blue) | `--ui-accent-a2` |
247
+ | `--ui-overlay` | the scrim behind a modal | window: white 55%; web: `--ui-overlay-page`; mobile: `--ui-overlay-dim` (black 40%, as before) |
248
+ | `--ui-overlay-page` | the scrim on a full page | `rgba(15, 23, 32, 0.32)`; dark `rgba(0, 0, 0, 0.5)` |
249
+
250
+ A component never writes a ring out (`shadow-[0_0_0_3px_…]`); it uses one of
251
+ the focus tokens (`tests/css/focus-ring.test.ts`).
252
+
193
253
  ## Motion
194
254
 
195
255
  The components move a little by default: dialogs and their masks fade in and
196
- settle from 97 %, menus, popovers and select lists drop 4px from their trigger,
256
+ settle from 97 %, menus, popovers and select lists drop 6px from their trigger (settling from 96 %),
197
257
  a notification slides 8px in, expandable bodies (`Card`, `SettingsSection`,
198
258
  `ExpandableItem`, `Callout` details, `TimelineRow`, `FacetPanel`, `Accordion`,
199
259
  `Fieldset`) open their height, a row the user just added fades in, and a tab
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synopackageland/ui",
3
- "version": "0.23.8",
3
+ "version": "0.25.0",
4
4
  "description": "Shared Vue 3 UI component library with a DSM 7 inspired application theme",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -79,6 +79,34 @@
79
79
  "@tiptap/vue-3": "3.32.1",
80
80
  "zod": "^4.6.5"
81
81
  },
82
+ "devDependencies": {
83
+ "@eslint/js": "10.0.1",
84
+ "@histoire/plugin-vue": "1.0.0-beta.1",
85
+ "@tailwindcss/vite": "4.3.3",
86
+ "@tanstack/vue-virtual": "3.13.39",
87
+ "@vitejs/plugin-vue": "6.0.9",
88
+ "@vue/test-utils": "2.5.1",
89
+ "@vueuse/core": "14.4.0",
90
+ "eslint": "10.11.0",
91
+ "eslint-plugin-vue": "10.11.1",
92
+ "flexsearch": "0.8.212",
93
+ "globals": "17.12.0",
94
+ "histoire": "1.0.0-beta.1",
95
+ "jsdom": "30.1.1",
96
+ "playwright": "1.58.2",
97
+ "reka-ui": "2.11.0",
98
+ "tailwindcss": "4.3.3",
99
+ "typescript": "5.9.3",
100
+ "typescript-eslint": "8.71.0",
101
+ "vite": "7.3.6",
102
+ "vite-plugin-dts": "5.1.1",
103
+ "vitest": "5.0.2",
104
+ "vscode-oniguruma": "2.0.1",
105
+ "vscode-textmate": "9.3.2",
106
+ "vue": "3.5.43",
107
+ "vue-eslint-parser": "10.4.1",
108
+ "vue-tsc": "3.3.11"
109
+ },
82
110
  "engines": {
83
111
  "node": ">=20"
84
112
  },
@@ -89,5 +117,63 @@
89
117
  "reka-ui": "2.11.0"
90
118
  }
91
119
  },
92
- "homepage": "https://www.varvis.me/docs/"
93
- }
120
+ "homepage": "https://www.varvis.me/docs/",
121
+ "scripts": {
122
+ "check:docs": "node --test scripts/check-doc-versions.test.mjs && node scripts/check-doc-versions.mjs",
123
+ "dev": "vite build --watch",
124
+ "build": "vite build && vite build --mode json && vite build --mode rich-text && vite build --mode grid && vite build --mode cli && vite build --mode preview && vite build --mode embedded && node scripts/postbuild.mjs",
125
+ "lint": "eslint .",
126
+ "typecheck": "vue-tsc --noEmit -p tsconfig.json",
127
+ "test": "vitest run",
128
+ "test:watch": "vitest",
129
+ "test:changed": "echo \"test:changed skips the tests the changes since ${SYNOPKGLAND_GATE_BASE:-origin/master} do not reach (vitest --changed); pnpm check runs them all\" && vitest run --changed ${SYNOPKGLAND_GATE_BASE:-origin/master}",
130
+ "story": "histoire dev",
131
+ "story:build": "histoire build",
132
+ "check:host": "node scripts/dsm-host-shots.mjs",
133
+ "check:switch": "node scripts/check-switch.mjs",
134
+ "check:tabs": "node scripts/check-tabs.mjs",
135
+ "check:mobile": "node scripts/check-mobile-overflow.mjs",
136
+ "check:ui-patch": "node scripts/check-ui-patch.mjs",
137
+ "check:narrow": "node scripts/check-narrow-controls.mjs",
138
+ "check:drawer-form": "node scripts/check-drawer-form.mjs",
139
+ "check:responsive": "node scripts/check-responsive.mjs",
140
+ "check:adaptive": "node scripts/check-adaptive.mjs",
141
+ "check:sidebar-focus": "node scripts/check-sidebar-focus.mjs",
142
+ "check:json-render": "node scripts/check-json-render.mjs",
143
+ "check:motion": "node scripts/check-motion.mjs",
144
+ "check:topology": "node scripts/check-topology.mjs",
145
+ "check:wizard": "node scripts/check-wizard.mjs",
146
+ "check:edges": "node scripts/check-edges.mjs",
147
+ "check:data-grid": "node scripts/check-data-grid.mjs",
148
+ "check:truncation": "node scripts/check-truncation.mjs",
149
+ "check:link": "node scripts/check-link.mjs",
150
+ "check:text-select": "node scripts/check-text-select.mjs",
151
+ "check:date-picker": "node scripts/check-date-picker.mjs",
152
+ "check:full-page": "node scripts/check-full-page.mjs",
153
+ "check:short-viewport": "node scripts/check-short-viewport.mjs",
154
+ "check:phone-layout": "node scripts/check-phone-layout.mjs",
155
+ "check:phone-bars": "node scripts/check-phone-bars.mjs",
156
+ "check:text-zoom": "node scripts/check-text-zoom.mjs",
157
+ "check:focus-restore": "node scripts/check-focus-restore.mjs",
158
+ "check:detail-surface": "node scripts/check-detail-surface.mjs",
159
+ "check:internal": "node --test scripts/check-internal-content.test.mjs scripts/check-npm-metadata.test.mjs && node scripts/check-internal-content.mjs --repo .",
160
+ "check:npm-metadata": "node scripts/check-npm-metadata.mjs",
161
+ "check:package": "node scripts/check-package-content.mjs",
162
+ "check:public-api-consumer": "node scripts/check-public-api-consumer.mjs",
163
+ "notices:update": "node scripts/third-party-notices.mjs --write",
164
+ "notices:check": "node scripts/third-party-notices.mjs --check",
165
+ "check": "bash scripts/docker-check.sh \"npm run gates\"",
166
+ "check:fast": "bash scripts/docker-check.sh \"npm run gates\"",
167
+ "check:local-browser": "node scripts/app-local-browser.mjs",
168
+ "check:infotip": "node scripts/check-infotip.mjs",
169
+ "release:stage": "node scripts/stage-release.mjs",
170
+ "check:polish": "bash scripts/docker-check.sh --build --out .polish-shots 'node scripts/check-polish.mjs'",
171
+ "check:acceptance": "node scripts/check-acceptance.mjs",
172
+ "check:palette": "node scripts/check-palette.mjs",
173
+ "gates": "node scripts/gates.mjs",
174
+ "gates:full": "node scripts/gates.mjs --full",
175
+ "check:layout": "node scripts/check-layout.mjs",
176
+ "release:smoke": "node scripts/release-smoke.mjs",
177
+ "check:browser-install": "playwright install chromium webkit"
178
+ }
179
+ }