@synopackageland/ui 0.23.5 → 0.23.7

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.
@@ -14,11 +14,12 @@ App. Each line links to its details below.
14
14
  | One compact top bar | One 44px row: Back, the menu button or the App icon, the title, at most two icons and one "…". No brand row, no second header row. |
15
15
  | No tab heading on tab pages | A page of the tab bar draws no title, icon or brand in the bar (`phone-bar-title="none"`) and no heading of its own: the tab bar says where the user is. A sub-page keeps Back and its title. |
16
16
  | Title on a tab page is opt-in | Showing a title on a tab page is the App's explicit choice: `phone-bar-title="auto"` on `AppLayout`, and the SDK AppShell's own opt-in (`phoneTitle`). |
17
- | Hide on scroll | By `transform` only; the scroller keeps its size, position and padding and nothing writes `scrollTop`, so a momentum fling keeps going. Slow scrolls use distance hysteresis, flicks decide at once. See [Hide on scroll](#native-phone-shell) and [Gesture velocity](#gesture-velocity). |
18
- | No horizontal pan | The page never pans sideways: the phone layout's content area and page scroller clip `overflow-x`, and `check:phone-layout` asserts `scrollWidth == clientWidth` for the document and the page's scrollers at 320, 360, 390 and 430px. An inner horizontal scroller (a table, a tab strip) still scrolls. |
17
+ | Hide on scroll | By `transform` only; the scroller keeps its size, position and padding and nothing writes `scrollTop`, so a momentum fling keeps going. Slow scrolls use distance hysteresis, flicks decide at once. While the page has scrolled less than the room above its content (the bar's row, a toolbar row, a host header's room), the bars show, a bounce past the top included; a scroll back into that zone shows them before the room shows empty, so the first content never sits below an empty band. See [Hide on scroll](#native-phone-shell) and [Gesture velocity](#gesture-velocity). |
18
+ | Commit footers never hide on scroll | A `SettingsPage` commit footer (Reset / Apply) is out of sight while the form is clean, slides in when it becomes dirty, invalid or saving, and stays in one place through every scroll and fling; Apply, Reset or the form becoming clean slides it out. On a phone it is a compact bar (8px padding, 32px buttons with 14px text and a 44px hit area: 48px plus its divider and the real safe-area inset), the tab bar stays directly under it, and the page's end space includes it so the last field scrolls fully above it. See [Settings footer](#native-phone-shell). |
19
+ | No horizontal pan | The page never pans sideways: the phone layout's content area and page scroller clip `overflow-x`, a `PageHeader`'s last action keeps its tap box inside the header, and `check:phone-layout` asserts `scrollWidth == clientWidth` for the document and the page's scrollers at 320, 360, 390 and 430px and in landscape (825x360, 753x279), also when the scroller is an App's own element in a fill page. An inner horizontal scroller (a table, a tab strip) still scrolls. |
19
20
  | Bottom accessory | `#accessory` docks above the tab bar, lifts the FAB and toasts, and slides into the tab bar's place with the bars. |
20
- | Sticky offsets | `--ui-sticky-top-offset` counts the covered padding, a sticky `PageHeader`, the tabs strip and every `data-ui-sticky` row, so scrolling to an element lands below them. A row in an App's own nested scroller (a side pane) sticks at that scroller's top and counts only there. |
21
- | 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. |
21
+ | Sticky offsets | `--ui-sticky-top-offset` counts the covered padding, a sticky `PageHeader`, the tabs strip and every `data-ui-sticky` row, so scrolling to an element lands below them. A row in an App's own nested scroller (a side pane, a record pane) sticks below the sticky `PageHeader` and tabs strip in that scroller and counts only there. |
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. |
22
23
  | Gesture velocity | One estimator and one set of thresholds for every gesture decision the UI makes. See [Gesture velocity](#gesture-velocity). |
23
24
 
24
25
  ## Width containment and the release gate
@@ -219,6 +220,19 @@ its 44px over the gutter and loses only what would lie outside the page. The
219
220
  body's width and `max-width` allow for the bleed; an App that sizes the body
220
221
  itself (`width: 100%`) is overridden by the body's inline width.
221
222
 
223
+ A fill page's scroller can be an element of the App's own, with the
224
+ `PageHeader` inside it (a record pane). No PageContent clip sits between the
225
+ header and that scroller's edge, so a "…" IconButton at the end of the
226
+ header reached 13px past it in a landscape phone window. A `PageHeader`'s
227
+ last action therefore sets `--ui-hit-end-room` to the header's own end
228
+ padding (`--ui-page-padding-x`, 0 inside a PageContent): its tap box stops
229
+ at the header's edge and grows towards its start side, still the full 44px,
230
+ wherever the header is. The scroller itself is not clipped: an App's
231
+ scroller that also scrolls a wide table sideways keeps doing so. For the
232
+ same reason no UI component's box reaches past its own edges: an
233
+ Accordion's pressed wash reaches 4px past each side by `box-shadow` (ink,
234
+ never scrollable overflow), not by a wider trigger.
235
+
222
236
  A control at the end edge of its own component is the component's job, not
223
237
  the page's: a dismissible Callout is often full width in an App's own
224
238
  scroller with no `PageContent` around it. Such a control sets
@@ -703,14 +717,20 @@ scrolls natively; the decision reads the shared velocity estimator (see
703
717
  [Gesture velocity](#gesture-velocity)) and the distance travelled one way:
704
718
 
705
719
  - a slow scroll down of `hideDistance` (48px) slides the bar, the tab bar,
706
- the FAB and a clean settings footer out (`data-ui-bars-hidden`); a slow
720
+ and the FAB out (`data-ui-bars-hidden`); a slow
707
721
  scroll up of `showDistance` (24px) brings them back, so a slow or wobbly
708
722
  drag never flickers them;
709
723
  - a flick at `flick` (1000 px/s) or faster hides them, or shows them, at
710
724
  once, and they move in 60% of `--ui-motion-bars` (never under 120ms;
711
725
  `--ui-bars-motion` on the layout), else in `--ui-motion-bars` (200ms; at
712
726
  once with reduced motion);
713
- - the top of the page and a scroll that stops at its end bring them back.
727
+ - while the page has scrolled less than the room above its content (the
728
+ top of the content area measured from the layout's column: the bar's row,
729
+ a toolbar row, a DSM portal header's room), they show whatever the
730
+ direction or speed, a bounce past the top included; they hide only once
731
+ content lies under them, and a scroll back into that zone shows them
732
+ before the room above the content can show empty;
733
+ - a scroll that stops at the page's end brings them back.
714
734
 
715
735
  The bars move by `transform` only. When the page scrolls in an area under
716
736
  the bar (a fill layout, or an App shell whose `main` does not let the
@@ -733,14 +753,20 @@ page that scrolls less than the bars' room never hides them.
733
753
 
734
754
  - Opt out for the App: `<AppLayout :hide-on-scroll="false">`; for one page:
735
755
  `<PageContent :hide-on-scroll="false">`. Both keep the settings footer too.
736
- - **Settings footer.** A `SettingsPage` footer hides with the bars only while
737
- the form is clean: never while it is dirty, invalid or saving, so Apply is
738
- in reach after every edit. Set `dirty`, `invalid` and `saving` on the
756
+ - **Settings footer.** On a phone a `SettingsPage` footer is a commit bar
757
+ and never takes part in hide on scroll. It is out of sight while the form
758
+ is clean and slides in when the form is dirty, invalid or saving; it then
759
+ stays in one place through every scroll and fling, and slides out after
760
+ Apply, Reset or the form becoming clean. While it shows, the tab bar stays
761
+ directly under it (one bottom edge), and the page's end space includes it,
762
+ so the last field scrolls fully above it. It moves by `transform` only;
763
+ the scroller is never resized. Set `dirty`, `invalid` and `saving` on the
739
764
  SettingsPage, or let it read them: clean while the footer's primary button
740
765
  (every button, without a primary) is disabled, invalid while a field has
741
- `aria-invalid="true"`, saving while a footer button is loading. A clean
742
- footer stays at rest: it slides away only with the bars, so Reset / Apply
743
- never appear or vanish under the finger while the user edits.
766
+ `aria-invalid="true"`, saving while a footer button is loading. The phone
767
+ footer is compact: 8px above and below 32px buttons (14px text, 12px side
768
+ padding), 48px plus its divider and only the real safe-area inset; each button keeps a 44px
769
+ hit area inside the footer. A DSM window and a desktop are unchanged.
744
770
 
745
771
  **Bottom accessory.** `AppLayout`'s `#accessory` slot is a bar across the
746
772
  bottom of the page for something the App is running (a recording bar, a mini
@@ -820,8 +846,15 @@ An App sets no `top` of its own and measures nothing.
820
846
  rows (`top` 0 for the first), never counts in the page's offset, and the
821
847
  container gets its own `--ui-sticky-top-offset` (its top padding plus its
822
848
  rows), so what scrolls in the pane stops below the pane's rows and not
823
- below the page's header. Before 0.23.5 such a row was stuck the page's
824
- header height down inside its pane.
849
+ below the page's header.
850
+ - A sticky `PageHeader` (and a sticky tabs strip) inside such a container
851
+ covers that container's top, not the page's: the container's rows stick
852
+ below it (`--ui-sticky-row-top` starts at the header's height), the
853
+ container's `--ui-sticky-top-offset` is its top padding plus the header,
854
+ the strip and its rows, and the container gets its own
855
+ `--ui-page-sticky-top` (its header's height) for a strip in it. Such a
856
+ header is left out of the page's `--ui-page-sticky-top` and offset. A
857
+ container with a sticky header and no rows gets the header as its offset.
825
858
  - A nested scroller without rows still inherits the page's offset as its
826
859
  content's scroll margin. Mark it `data-ui-sticky-scope` and what scrolls in
827
860
  it takes no page offset. A fill page's own list scroller
@@ -839,7 +872,14 @@ the room for the bars is the separate `--ui-bars-room` spacer, and a fill
839
872
  page whose own scroller has the FAB's room gets no end space below that
840
873
  scroller, so no blank band sits under a list. An App shell that pads its
841
874
  page end reads it:
842
- `padding-bottom: var(--ui-page-end-space, var(--ui-space-6, 24px))`.
875
+ `padding-bottom: var(--ui-page-end-space, var(--ui-space-6, 24px))`. Under
876
+ docked bars its value is a `calc()` expression, not a plain length: code
877
+ that needs it in pixels reads a resolved length (PageContent reads the
878
+ computed margin of a hidden probe whose `margin-top` is the variable), never
879
+ `parseFloat` of the property's text. PageContent subtracts it when it looks
880
+ for a fill page's scroller, so an App that puts the end space on a wrapper
881
+ around its own scroller (rather than on the scroller) still has that
882
+ scroller found.
843
883
 
844
884
  **Scroll helpers.** A phone page scrolls in a different element than a
845
885
  desktop or DSM window. `nearestScroller(el)` returns the element that
@@ -8,7 +8,7 @@ checks through the optional build-isolation wrapper.
8
8
 
9
9
  | Entry point | Default | Explicit full |
10
10
  | --- | --- | --- |
11
- | `npm run gates`, `scripts/gates.mjs` | Internal-content checks, build, lint, typecheck, unit tests, notices, isolated pack and tarball content audit | Adds Chromium installation, responsive/adaptive/date-picker/JSON/host/switch/layout/InfoTip/motion/short-viewport/phone-layout/focus-restore browser checks, Histoire build, exact-tarball registry consumer smoke |
11
+ | `npm run gates`, `scripts/gates.mjs` | Internal-content checks, build, lint, typecheck, unit tests, notices, isolated pack and tarball content audit | Adds Chromium and WebKit installation, responsive/adaptive/date-picker/JSON/host/switch/layout/InfoTip/motion/short-viewport/phone-layout/phone-bars (Chromium and WebKit)/focus-restore browser checks, Histoire build, exact-tarball registry consumer smoke |
12
12
  | `pnpm check`, `check:fast` | Basic, with optional Docker host build isolation | `SPL_FULL_GATE=1` selects the same full plan |
13
13
  | `fast-ci.yml`, composite verify action | Basic | No automatic extended checks |
14
14
  | Disabled CI/release workflow templates | Basic, version/tag/ancestry checks, stage, pack and actual archive audit | No implicit browser or registry consumer smoke |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synopackageland/ui",
3
- "version": "0.23.5",
3
+ "version": "0.23.7",
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,34 +79,6 @@
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
- },
110
82
  "engines": {
111
83
  "node": ">=20"
112
84
  },
@@ -117,62 +89,5 @@
117
89
  "reka-ui": "2.11.0"
118
90
  }
119
91
  },
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:text-zoom": "node scripts/check-text-zoom.mjs",
156
- "check:focus-restore": "node scripts/check-focus-restore.mjs",
157
- "check:detail-surface": "node scripts/check-detail-surface.mjs",
158
- "check:internal": "node --test scripts/check-internal-content.test.mjs scripts/check-npm-metadata.test.mjs && node scripts/check-internal-content.mjs --repo .",
159
- "check:npm-metadata": "node scripts/check-npm-metadata.mjs",
160
- "check:package": "node scripts/check-package-content.mjs",
161
- "check:public-api-consumer": "node scripts/check-public-api-consumer.mjs",
162
- "notices:update": "node scripts/third-party-notices.mjs --write",
163
- "notices:check": "node scripts/third-party-notices.mjs --check",
164
- "check": "bash scripts/docker-check.sh \"npm run gates\"",
165
- "check:fast": "bash scripts/docker-check.sh \"npm run gates\"",
166
- "check:local-browser": "node scripts/app-local-browser.mjs",
167
- "check:infotip": "node scripts/check-infotip.mjs",
168
- "release:stage": "node scripts/stage-release.mjs",
169
- "check:polish": "bash scripts/docker-check.sh --build --out .polish-shots 'node scripts/check-polish.mjs'",
170
- "check:acceptance": "node scripts/check-acceptance.mjs",
171
- "check:palette": "node scripts/check-palette.mjs",
172
- "gates": "node scripts/gates.mjs",
173
- "gates:full": "node scripts/gates.mjs --full",
174
- "check:layout": "node scripts/check-layout.mjs",
175
- "release:smoke": "node scripts/release-smoke.mjs",
176
- "check:browser-install": "playwright install chromium"
177
- }
178
- }
92
+ "homepage": "https://www.varvis.me/docs/"
93
+ }