vintage-frames 0.5.4 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10756,7 +10756,7 @@
10756
10756
  "declarations": [
10757
10757
  {
10758
10758
  "kind": "class",
10759
- "description": "`<vf-scroll-area>` — a container whose scrollbars look like System 7.\n\nWhite box with a 1px black frame, an inner scrolling viewport, and scroll\nrails the kit draws itself as shadow DOM (the shared `vfScrollRail` recipe):\nboxed arrow buttons at each end, a loose 1-bit dot-dither trough, and the\nclassic fixed 16px thumb. The native scrollbar is hidden, never the native\nscrolling — wheel, trackpad momentum, keyboard, touch and assistive-tech\nscrolling stay the platform's, and ScrollRailController keeps the\nrail in sync while driving the classic interactions (thumb drag, trough\npaging, arrow stepping with auto-repeat). Every engine renders the same\nrail — there is no Firefox fallback skin anymore.\n\nEach reserved scroll rail is a permanent placeholder: arrow buttons on an\nempty white channel sit in the gutter even when the content fits, the\ndither and thumb filling in only once that axis overflows (System 7 drew\nan active window's no-overflow bar as arrows on a bare channel; driven\nby ScrollStateController). Which rails are reserved is set by\naxis; when both are reserved the bottom-right corner joins them.\n\nSize the host (width/height) from the outside; the viewport fills it.",
10759
+ "description": "`<vf-scroll-area>` — a container whose scrollbars look like System 7.\n\nWhite box with a 1px black frame, an inner scrolling viewport, and scroll\nrails the kit draws itself as shadow DOM (the shared `vfScrollRail` recipe):\nboxed arrow buttons at each end, a loose 1-bit dot-dither trough, and the\nclassic fixed 16px thumb. The native scrollbar is hidden, never the native\nscrolling — wheel, trackpad momentum, keyboard, touch and assistive-tech\nscrolling stay the platform's, and ScrollRailController keeps the\nrail in sync while driving the classic interactions (thumb drag, trough\npaging, arrow stepping with auto-repeat). Every engine renders the same\nrail — there is no Firefox fallback skin anymore.\n\nEach reserved scroll rail is a permanent placeholder: arrow buttons on an\nempty white channel sit in the gutter even when the content fits, the\ndither and thumb filling in only once that axis overflows (System 7 drew\nan active window's no-overflow bar as arrows on a bare channel; driven\nby ScrollStateController). Which rails are reserved is set by\naxis; when both are reserved the bottom-right corner joins them,\nand corner reserves that cell on a single-axis rail too — the\nrail stops 15px short of the frame, for a grow box to land in.\n\nSize the host (width/height) from the outside; the viewport fills it. The\nviewport insets its content 8px; flush drops that inset so content\nruns to the frame and the rails.",
10760
10760
  "name": "VfScrollArea",
10761
10761
  "cssProperties": [
10762
10762
  {
@@ -10807,6 +10807,28 @@
10807
10807
  "attribute": "axis",
10808
10808
  "reflects": true
10809
10809
  },
10810
+ {
10811
+ "kind": "field",
10812
+ "name": "flush",
10813
+ "type": {
10814
+ "text": "boolean"
10815
+ },
10816
+ "default": "false",
10817
+ "description": "Drop the viewport's 8px inset: slotted content and the (0,0) of placed\nchildren sit at the frame's inner edge, one system px from the frame\nbox (the border-floor compensation stays — see the viewport rule).\n`vf-window[scrollbars]` forwards its own `flush` here.",
10818
+ "attribute": "flush",
10819
+ "reflects": true
10820
+ },
10821
+ {
10822
+ "kind": "field",
10823
+ "name": "corner",
10824
+ "type": {
10825
+ "text": "boolean"
10826
+ },
10827
+ "default": "false",
10828
+ "description": "Reserve the bottom-right corner cell on a single-axis rail: the rail\nstops 15px short of the frame and the viewport spans the rest, leaving\nthe 15×15 cell — with the two dividers a `both` rail's corner carries —\nfor a grow box to land in. A `both` rail always has the cell, so the\nflag changes nothing there. `vf-window[scrollbars resizable]` sets it.",
10829
+ "attribute": "corner",
10830
+ "reflects": true
10831
+ },
10810
10832
  {
10811
10833
  "kind": "field",
10812
10834
  "name": "label",
@@ -10915,6 +10937,24 @@
10915
10937
  "description": "Which scroll rails to reserve as permanent placeholders: `vertical`\n(default), `horizontal`, or `both`. Each reserved rail shows an empty white\nchannel until its axis overflows; the unreserved axis still scrolls\nnatively (wheel, keyboard) but draws no rail.",
10916
10938
  "fieldName": "axis"
10917
10939
  },
10940
+ {
10941
+ "name": "flush",
10942
+ "type": {
10943
+ "text": "boolean"
10944
+ },
10945
+ "default": "false",
10946
+ "description": "Drop the viewport's 8px inset: slotted content and the (0,0) of placed\nchildren sit at the frame's inner edge, one system px from the frame\nbox (the border-floor compensation stays — see the viewport rule).\n`vf-window[scrollbars]` forwards its own `flush` here.",
10947
+ "fieldName": "flush"
10948
+ },
10949
+ {
10950
+ "name": "corner",
10951
+ "type": {
10952
+ "text": "boolean"
10953
+ },
10954
+ "default": "false",
10955
+ "description": "Reserve the bottom-right corner cell on a single-axis rail: the rail\nstops 15px short of the frame and the viewport spans the rest, leaving\nthe 15×15 cell — with the two dividers a `both` rail's corner carries —\nfor a grow box to land in. A `both` rail always has the cell, so the\nflag changes nothing there. `vf-window[scrollbars resizable]` sets it.",
10956
+ "fieldName": "corner"
10957
+ },
10918
10958
  {
10919
10959
  "name": "label",
10920
10960
  "type": {
@@ -17256,7 +17296,7 @@
17256
17296
  "text": "boolean"
17257
17297
  },
17258
17298
  "default": "false",
17259
- "description": "Remove the default 12px body padding.",
17299
+ "description": "Remove the default 12px body padding. Under `scrollbars` the body has\nnone to remove, so the flag reaches the built-in scroll area instead\nand drops its viewport's 8px inset: content runs to the frame and the\nrails, and the (0,0) of placed children is the content region's corner.",
17260
17300
  "attribute": "flush",
17261
17301
  "reflects": true
17262
17302
  },
@@ -17266,7 +17306,7 @@
17266
17306
  "type": {
17267
17307
  "text": "'vertical' | 'horizontal' | 'both' | undefined"
17268
17308
  },
17269
- "description": "Put System 7 scroll rails on the window edge — the classic document\nwindow. The body slot renders inside a built-in `vf-scroll-area` pulled\none system pixel under the frame on every side, so the rails repaint the\nborder lines and a `resizable` window's grow box lands in the corner\ncell. Values mirror `vf-scroll-area`'s `axis`; the `heading` names the\nscroll region; the viewport part is re-exported. Implies `flush` (the\nviewport carries its own padding). The slotted composition (SPEC §5\nvf-scroll-area) still works for windows that want an inset well instead.",
17309
+ "description": "Put System 7 scroll rails on the window edge — the classic document\nwindow. The body slot renders inside a built-in `vf-scroll-area` pulled\none system pixel under the frame on every side, so the rails repaint the\nborder lines and a `resizable` window's grow box lands in the corner\ncell — reserved on a single-axis rail too (the area's `corner`), unless\na populated status strip holds the grow box, when the rail runs edge to\nedge onto the strip's rule. Values mirror `vf-scroll-area`'s `axis`; the\n`heading` names the scroll region; the viewport part is re-exported.\nThe body's own padding goes; the viewport keeps its 8px inset unless\n`flush`, which passes through. The slotted composition (SPEC §5\nvf-scroll-area) still works for windows that want an inset well instead.",
17270
17310
  "attribute": "scrollbars",
17271
17311
  "reflects": true
17272
17312
  },
@@ -17636,7 +17676,7 @@
17636
17676
  "text": "boolean"
17637
17677
  },
17638
17678
  "default": "false",
17639
- "description": "Remove the default 12px body padding.",
17679
+ "description": "Remove the default 12px body padding. Under `scrollbars` the body has\nnone to remove, so the flag reaches the built-in scroll area instead\nand drops its viewport's 8px inset: content runs to the frame and the\nrails, and the (0,0) of placed children is the content region's corner.",
17640
17680
  "fieldName": "flush"
17641
17681
  },
17642
17682
  {
@@ -17644,7 +17684,7 @@
17644
17684
  "type": {
17645
17685
  "text": "'vertical' | 'horizontal' | 'both' | undefined"
17646
17686
  },
17647
- "description": "Put System 7 scroll rails on the window edge — the classic document\nwindow. The body slot renders inside a built-in `vf-scroll-area` pulled\none system pixel under the frame on every side, so the rails repaint the\nborder lines and a `resizable` window's grow box lands in the corner\ncell. Values mirror `vf-scroll-area`'s `axis`; the `heading` names the\nscroll region; the viewport part is re-exported. Implies `flush` (the\nviewport carries its own padding). The slotted composition (SPEC §5\nvf-scroll-area) still works for windows that want an inset well instead.",
17687
+ "description": "Put System 7 scroll rails on the window edge — the classic document\nwindow. The body slot renders inside a built-in `vf-scroll-area` pulled\none system pixel under the frame on every side, so the rails repaint the\nborder lines and a `resizable` window's grow box lands in the corner\ncell — reserved on a single-axis rail too (the area's `corner`), unless\na populated status strip holds the grow box, when the rail runs edge to\nedge onto the strip's rule. Values mirror `vf-scroll-area`'s `axis`; the\n`heading` names the scroll region; the viewport part is re-exported.\nThe body's own padding goes; the viewport keeps its 8px inset unless\n`flush`, which passes through. The slotted composition (SPEC §5\nvf-scroll-area) still works for windows that want an inset well instead.",
17648
17688
  "fieldName": "scrollbars"
17649
17689
  },
17650
17690
  {
@@ -18,9 +18,13 @@ declare const VfScrollArea_base: (new (...args: any[]) => import("../position.js
18
18
  * dither and thumb filling in only once that axis overflows (System 7 drew
19
19
  * an active window's no-overflow bar as arrows on a bare channel; driven
20
20
  * by {@link ScrollStateController}). Which rails are reserved is set by
21
- * {@link axis}; when both are reserved the bottom-right corner joins them.
21
+ * {@link axis}; when both are reserved the bottom-right corner joins them,
22
+ * and {@link corner} reserves that cell on a single-axis rail too — the
23
+ * rail stops 15px short of the frame, for a grow box to land in.
22
24
  *
23
- * Size the host (width/height) from the outside; the viewport fills it.
25
+ * Size the host (width/height) from the outside; the viewport fills it. The
26
+ * viewport insets its content 8px; {@link flush} drops that inset so content
27
+ * runs to the frame and the rails.
24
28
  *
25
29
  * @slot - Scrollable content.
26
30
  * @csspart viewport - The inner scrolling container.
@@ -39,6 +43,21 @@ export declare class VfScrollArea extends VfScrollArea_base {
39
43
  * natively (wheel, keyboard) but draws no rail.
40
44
  */
41
45
  axis: 'vertical' | 'horizontal' | 'both';
46
+ /**
47
+ * Drop the viewport's 8px inset: slotted content and the (0,0) of placed
48
+ * children sit at the frame's inner edge, one system px from the frame
49
+ * box (the border-floor compensation stays — see the viewport rule).
50
+ * `vf-window[scrollbars]` forwards its own `flush` here.
51
+ */
52
+ flush: boolean;
53
+ /**
54
+ * Reserve the bottom-right corner cell on a single-axis rail: the rail
55
+ * stops 15px short of the frame and the viewport spans the rest, leaving
56
+ * the 15×15 cell — with the two dividers a `both` rail's corner carries —
57
+ * for a grow box to land in. A `both` rail always has the cell, so the
58
+ * flag changes nothing there. `vf-window[scrollbars resizable]` sets it.
59
+ */
60
+ corner: boolean;
42
61
  /**
43
62
  * Accessible name for the scrolling viewport, applied as its `aria-label`
44
63
  * (an `aria-label` on the host would not reach into the shadow DOM). The
@@ -13,7 +13,7 @@ import { property as h, query as g, state as _ } from "lit/decorators.js";
13
13
  //#region src/components/vf-scroll-area.ts
14
14
  var v = class extends r(d) {
15
15
  constructor(...e) {
16
- super(...e), this.scale = new t(this), this.gridSnap = new s(this), this.axis = "vertical", this.label = "", this.scrollState = new c(this, () => this.viewport, () => this.content, (e) => {
16
+ super(...e), this.scale = new t(this), this.gridSnap = new s(this), this.axis = "vertical", this.flush = !1, this.corner = !1, this.label = "", this.scrollState = new c(this, () => this.viewport, () => this.content, (e) => {
17
17
  this._scrollable = e.x || e.y;
18
18
  }), this.rail = new l(this, {
19
19
  getScroll: () => this.viewport,
@@ -46,11 +46,13 @@ var v = class extends r(d) {
46
46
  }
47
47
  :host(:not([axis])) .box,
48
48
  :host([axis='vertical']) .box,
49
- :host([axis='both']) .box {
49
+ :host([axis='both']) .box,
50
+ :host([corner]) .box {
50
51
  grid-template-columns: 1fr auto;
51
52
  }
52
53
  :host([axis='horizontal']) .box,
53
- :host([axis='both']) .box {
54
+ :host([axis='both']) .box,
55
+ :host([corner]) .box {
54
56
  grid-template-rows: 1fr auto;
55
57
  }
56
58
  .viewport {
@@ -73,6 +75,23 @@ var v = class extends r(d) {
73
75
  var(--vf-scale, 1) * 8px + mod(var(--vf-scale, 1) * 1px, 1px)
74
76
  );
75
77
  }
78
+ /* flush: the inset goes, the border-floor term stays — content and the
79
+ (0,0) of placed children sit at the frame's inner edge, exactly one
80
+ system px from the frame box at every scale. */
81
+ :host([flush]) .viewport {
82
+ padding: mod(var(--vf-scale, 1) * 1px, 1px);
83
+ }
84
+ /* A single-axis rail with a reserved corner: the viewport spans the
85
+ track the missing rail would have taken, up to the corner cell, so
86
+ the rail stops 15px short of the frame. (A both-axes rail has no
87
+ missing track — the flag is inert there.) */
88
+ :host([corner][axis='horizontal']) .viewport {
89
+ grid-column: 1 / 3;
90
+ }
91
+ :host([corner]:not([axis])) .viewport,
92
+ :host([corner][axis='vertical']) .viewport {
93
+ grid-row: 1 / 3;
94
+ }
76
95
  .vf-rail--vertical {
77
96
  grid-area: 1 / 2;
78
97
  }
@@ -100,7 +119,7 @@ var v = class extends r(d) {
100
119
  ];
101
120
  }
102
121
  render() {
103
- let e = this.axis !== "horizontal", t = this.axis === "horizontal" || this.axis === "both";
122
+ let e = this.axis !== "horizontal", t = this.axis === "horizontal" || this.axis === "both", n = e && t || this.corner;
104
123
  return p`
105
124
  <div class="box vf-snap">
106
125
  <div
@@ -114,11 +133,17 @@ var v = class extends r(d) {
114
133
  </div>
115
134
  ${e ? u(this.rail, "vertical") : m}
116
135
  ${t ? u(this.rail, "horizontal") : m}
117
- ${e && t ? p`<div class="vf-rail-corner" aria-hidden="true"></div>` : m}
136
+ ${n ? p`<div class="vf-rail-corner" aria-hidden="true"></div>` : m}
118
137
  </div>
119
138
  `;
120
139
  }
121
140
  };
122
- n([h({ reflect: !0 })], v.prototype, "axis", void 0), n([h()], v.prototype, "label", void 0), n([g(".viewport")], v.prototype, "viewport", void 0), n([g(".content")], v.prototype, "content", void 0), n([_()], v.prototype, "_scrollable", void 0), v = n([e("vf-scroll-area")], v);
141
+ n([h({ reflect: !0 })], v.prototype, "axis", void 0), n([h({
142
+ type: Boolean,
143
+ reflect: !0
144
+ })], v.prototype, "flush", void 0), n([h({
145
+ type: Boolean,
146
+ reflect: !0
147
+ })], v.prototype, "corner", void 0), n([h()], v.prototype, "label", void 0), n([g(".viewport")], v.prototype, "viewport", void 0), n([g(".content")], v.prototype, "content", void 0), n([_()], v.prototype, "_scrollable", void 0), v = n([e("vf-scroll-area")], v);
123
148
  //#endregion
124
149
  export { v as VfScrollArea };
@@ -94,16 +94,24 @@ export declare class VfWindow extends VfWindow_base {
94
94
  movable: boolean;
95
95
  /** Show a grow box at the bottom-right corner for resizing. */
96
96
  resizable: boolean;
97
- /** Remove the default 12px body padding. */
97
+ /**
98
+ * Remove the default 12px body padding. Under `scrollbars` the body has
99
+ * none to remove, so the flag reaches the built-in scroll area instead
100
+ * and drops its viewport's 8px inset: content runs to the frame and the
101
+ * rails, and the (0,0) of placed children is the content region's corner.
102
+ */
98
103
  flush: boolean;
99
104
  /**
100
105
  * Put System 7 scroll rails on the window edge — the classic document
101
106
  * window. The body slot renders inside a built-in `vf-scroll-area` pulled
102
107
  * one system pixel under the frame on every side, so the rails repaint the
103
108
  * border lines and a `resizable` window's grow box lands in the corner
104
- * cell. Values mirror `vf-scroll-area`'s `axis`; the `heading` names the
105
- * scroll region; the viewport part is re-exported. Implies `flush` (the
106
- * viewport carries its own padding). The slotted composition (SPEC §5
109
+ * cell reserved on a single-axis rail too (the area's `corner`), unless
110
+ * a populated status strip holds the grow box, when the rail runs edge to
111
+ * edge onto the strip's rule. Values mirror `vf-scroll-area`'s `axis`; the
112
+ * `heading` names the scroll region; the viewport part is re-exported.
113
+ * The body's own padding goes; the viewport keeps its 8px inset unless
114
+ * `flush`, which passes through. The slotted composition (SPEC §5
107
115
  * vf-scroll-area) still works for windows that want an inset well instead.
108
116
  */
109
117
  scrollbars?: 'vertical' | 'horizontal' | 'both';
@@ -201,7 +201,9 @@ var z = 80, B = 54, V = 24, H = 8, U = class extends E(c(N)) {
201
201
  frame on every side, so its own frame border repaints the window's
202
202
  border lines exactly (no doubled frame), the rails run edge to edge,
203
203
  and a resizable window's grow box (z-index 1) lands over the rail
204
- corner cell. */
204
+ corner cell — which the render reserves on a single-axis rail too
205
+ (the area's corner flag), except when the status strip holds the
206
+ grow box instead. */
205
207
  .edge-scroll {
206
208
  width: calc(100% + var(--vf-scale, 1) * 2px);
207
209
  height: calc(100% + var(--vf-scale, 1) * 2px);
@@ -380,6 +382,8 @@ var z = 80, B = 54, V = 24, H = 8, U = class extends E(c(N)) {
380
382
  <vf-scroll-area
381
383
  class="edge-scroll"
382
384
  axis=${this.scrollbars}
385
+ ?flush=${this.flush}
386
+ ?corner=${this.resizable && !this._hasStatus}
383
387
  label=${this.heading || I}
384
388
  exportparts="viewport"
385
389
  >
@@ -150,11 +150,17 @@ var s = i(r["gray-25"]), c = s.width, l = s.height, u = s.rects, d = e(c, l, t(u
150
150
  width: calc(var(--vf-scale, 1) * 16px);
151
151
  }
152
152
 
153
- /* The both-axes corner cell. It supplies the two interior dividers
153
+ /* The corner cell: the rails' own 15px in both dimensions, so it sizes its
154
+ grid track even when only one rail is there to size it (vf-scroll-area's
155
+ corner flag on a single-axis rail). It supplies the two interior dividers
154
156
  (against the vertical increment arrow above and the horizontal one
155
- beside it) that those buttons leave to it; a resizable window's grow box
156
- lands exactly over it. */
157
+ beside it) that those buttons leave to it — on a single-axis rail the
158
+ other divider continues the rail's line across the cell, the way
159
+ DrawGrowIcon drew it; a resizable window's grow box lands exactly over
160
+ it. */
157
161
  .vf-rail-corner {
162
+ width: calc(var(--vf-scale, 1) * 15px);
163
+ height: calc(var(--vf-scale, 1) * 15px);
158
164
  background: var(--vf-white, #fff);
159
165
  border-top: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
160
166
  border-left: calc(var(--vf-scale, 1) * 1px) solid var(--vf-black, #000);
package/docs/SPEC.md CHANGED
@@ -208,7 +208,7 @@ Full-bleed classic desktop container.
208
208
 
209
209
  #### `vf-window` (`VfWindow`, vf-window.ts)
210
210
  The desktop-window shell: the classic document window (see DragThing screenshot), parameterized down to the windoid (see the Group A recipe table).
211
- - **Attributes/props:** `heading: string` (title text), `width: number` / `height: number` (**declare them both** — whole system px, so the window keeps its proportion to the chrome inside it at every density. A window is a fixed box in both axes, the way a WIND resource was: one that grows with its body is one the user can neither predict nor control via the grow box. Each missing dimension falls back to something different — width to block layout, height to the content — and the window names whichever are missing, once, in the console), `active: boolean` (default **true**; reflect), `closable: boolean` (default true), `zoomable: boolean` (default false), `movable: boolean` (default false), `resizable: boolean` (default false), `flush: boolean` (default false — removes body padding), `variant?: 'utility'` (the slim windoid chrome), `scrollbars?: 'vertical' | 'horizontal' | 'both'` (edge scroll rails).
211
+ - **Attributes/props:** `heading: string` (title text), `width: number` / `height: number` (**declare them both** — whole system px, so the window keeps its proportion to the chrome inside it at every density. A window is a fixed box in both axes, the way a WIND resource was: one that grows with its body is one the user can neither predict nor control via the grow box. Each missing dimension falls back to something different — width to block layout, height to the content — and the window names whichever are missing, once, in the console), `active: boolean` (default **true**; reflect), `closable: boolean` (default true), `zoomable: boolean` (default false), `movable: boolean` (default false), `resizable: boolean` (default false), `flush: boolean` (default false — removes the body padding; under `scrollbars`, the built-in viewport's 8px inset instead), `variant?: 'utility'` (the slim windoid chrome), `scrollbars?: 'vertical' | 'horizontal' | 'both'` (edge scroll rails).
212
212
  - **Visual:** `vfChromeFrame` + `vfTitleBar` (§4), plus a full-size flex-column layout on the frame. `display: block`. Sets `--vf-surface: var(--vf-white, #fff)` on itself.
213
213
  - Title bar: from `vfTitleBar` — height `var(--vf-titlebar-height, 18px)`, white bg, bottom `1px solid black`, contains `.vf-stripes` layer (only when `active`). `touch-action: none` only when `[movable]`.
214
214
  - Title: centered, bold, on a white patch (`padding: 0 6px`; cap band on interior rows 4..12, 7px of white between ink and stripes — see §4 `vfTitleBar` for the traced geometry and the lattice hold) above the stripes, with `--vf-title-inset: 60px` of clearance so it ellipsizes before reaching the widgets. Inactive: no stripes, widgets undrawn (transparent ink — they keep their tab stops; see A11y below), the grow box's nested squares hidden, and every managed scroll rail inside the window blanked (see "always-a-rail" §5 vf-scroll-area) — but the title text stays black (System 7 never grayed the window title).
@@ -217,7 +217,7 @@ The desktop-window shell: the classic document window (see DragThing screenshot)
217
217
  - Body: `padding: 12px` (0 if `flush` or `scrollbars`), and `overflow: hidden` — the window being a fixed box, content taller than it is clipped at the frame the way the classic content region was, rather than painting out over the desktop; `scrollbars` is how the user reaches the rest. Two deliberate exemptions: `[scrollbars]` restores `overflow: visible`, because the edge-rail composition below pulls the scroll area one system px *outside* the body on every side and clipping would shave exactly that overhang off (the scroll area does its own clipping); and a control's drop-open panel is not clipped — `vf-select`'s list is `position: fixed` off the control's rect precisely to escape clipping ancestors (§5 vf-select), and it still escapes, because nothing between it and the viewport establishes a containing block for fixed descendants (the grid-snap correction is a `position: relative` left/top offset, never a transform — see §7). A `vf-menu` panel is anchored `position: absolute` and *would* clip, but a menu bar belongs to the desktop, not inside a window body.
218
218
  - Grow box (if `resizable`): 15×15 at bottom-right corner, white bg, 1px black top/left borders, containing two overlapping small square outlines. Inactive: the cell and its borders stay, the nested squares go — System 7 drew a deactivated window's size box hollow, with its blanked scroll rails.
219
219
  - Status bar (`status` slot): the classic bottom readout strip ("40px x 40px") — a 1px black rule (`vfRule`'s `.vf-rule-top`) over a white interior, `--vf-status-bar-height` (15px) in all, the grow box's own height, so a `resizable` window's grow box sits flush in the strip's right end (its top/left borders take over the rule there; the strip reserves 21px of right padding under `resizable` so text clears the cell). Slotted content rides the body face's native 12px line (`--vf-line-height`), whole-pixel centered in the 14px interior, `padding-inline: 6px`, nowrap + clipped. Takes **no space** until the slot is populated (the dialog-footer pattern), and collapses again when it empties. Composes with `scrollbars`: the edge rails' bottom overhang lands its frame line exactly on the strip's rule, so the two never double up — though the grow box then sits in the strip rather than the rail corner cell.
220
- - Edge scroll rails (if `scrollbars`): the body slot renders inside a shadow `vf-scroll-area` (its `axis` = the attribute's value, `label` = the heading, `viewport` part re-exported) carrying the TeachText composition internally — `calc(100% + 2px·scale)` with `margin: -1px·scale`, one system px under the frame on every side, so the area's own frame border repaints the window's border lines and a `resizable` window's grow box (z-index 1) lands exactly over the rail-corner cell. Same caveats as the slotted composition (see vf-scroll-area §5), which remains supported for inset wells.
220
+ - Edge scroll rails (if `scrollbars`): the body slot renders inside a shadow `vf-scroll-area` (its `axis` = the attribute's value, `label` = the heading, `viewport` part re-exported) carrying the TeachText composition internally — `calc(100% + 2px·scale)` with `margin: -1px·scale`, one system px under the frame on every side, so the area's own frame border repaints the window's border lines and a `resizable` window's grow box (z-index 1) lands exactly over the rail-corner cell. `flush` passes through to the area (its viewport drops the 8px inset, keeping the border-floor term, so content and the (0,0) of placed children sit at the content region's corner); a `resizable` window sets the area's `corner`, so a single-axis rail stops at the corner cell too — unless the status strip is populated, when the grow box sits in the strip and the rail runs edge to edge onto the strip's rule. Same caveats as the slotted composition (see vf-scroll-area §5), which remains supported for inset wells.
221
221
  - Utility variant (`variant="utility"`): the slim windoid bar traced from `Windows/utility-window.png` — `--vf-titlebar-height-utility` (12px = 11px interior + 1px rule), the `vfDots` dither instead of stripes (flush to the side borders — see §4 vfDots), 7×7 widgets (`top: 2px`; close `left: 7px`, zoom `right: 8px` — the art is asymmetric by that pixel) with a 2px patch ring where the striped bar's is 1px (`--vf-widget-ring`, internal geometry: the windoid sheet clears two px of dither beside its widgets), and the nested zoom square shrunk so its edges land at sprite col/row 3. No title patch: the display face's 16px line box can't sit in an 11px interior, so `.vf-title` is `display: none` under the variant (a retheming consumer can re-show it via `::part(title)`) and the heading names the widgets. A pressed windoid widget inverts whole — black interior under a white (invisible) borderline — rather than flashing the big bar's 9×9 sunburst, which can't land on a 5×5 interior.
222
222
  - **A11y:** the close/zoom `aria-label`s are qualified by the title when there is one (`Close ${heading}` / `Zoom ${heading}`, falling back to bare `Close` / `Zoom`) — several windows are open at once by design, so a bare repeated "Close" gives an AT user no way to tell which window a widget belongs to. The frame is `role="group"`, named by the title patch via `aria-labelledby` when there is a heading (the utility variant's hidden patch still names it — AccName resolves hidden labelledby targets) — `group` rather than `region` deliberately, so a desktop of windows doesn't pollute landmark navigation; the title bar is a `<div>`, never a `<header>`, which would map to an unnamed `banner` landmark even inside the shadow root. An inactive window's widgets stay in the tree and the tab order but paint no ink (transparent border/background/patch ring — the bare System 7 bar): a background window whose body holds nothing focusable is still reachable, activated by `vf-desktop`'s `focusin` raise the moment Tab lands on a widget, and never drops focus to `<body>` when it deactivates. `npm run verify:window-a11y`.
223
223
  - **Behavior:** close box click → `vf-close` (does NOT remove itself; consumer decides). Zoom box click → `vf-zoom`. If `movable`: dragging the title bar moves the window — the drag seeds its origin from the current offset position (once, converting to system px) and then states `left`/`top` via pointer capture, in whole system px like any authored placement. If `resizable`: dragging the grow box states `width`/`height` the same way, and fires `vf-resize` (detail `{ width, height, commit }`, sizes in whole system px) — one event per size the drag actually writes (`commit: false`), fired *after* the new box is applied so a handler that measures reads the resized layout, then a final `commit: true` as the gesture settles (release or cancel), only when it changed the size. Window content can follow the grow box from this event alone, no ResizeObserver. Fired by the gesture only: a programmatic `width`/`height` write fires nothing, the way a value set fires no `vf-change`.
@@ -389,11 +389,11 @@ Classic list box.
389
389
 
390
390
  #### `vf-scroll-area` (`VfScrollArea`, vf-scroll-area.ts)
391
391
  A container whose scrollbars look like System 7.
392
- - **Attributes/props:** `axis: 'vertical' | 'horizontal' | 'both'` (default `'vertical'`, reflected) — which scroll rails to reserve as permanent placeholders (see "always-a-rail" below); `label: string` — accessible name for the viewport (`aria-label` on the viewport, since an `aria-label` on the host cannot reach into the shadow DOM). The viewport is a **Tab stop only while its content actually overflows** — the same state `ScrollStateController` measures for the rails; a fitting scroll area used to be a focusable stop with `role: generic` and no name, a dead Tab press. Whenever it is a stop it carries a role: `role="region"` when `label` names it (a named landmark), `role="group"` when not (an unnamed region is inert, so that role is reserved for the labelled case).
393
- - **Visual:** `display: block`; the snapped wrapper carries a real 1px black frame and a grid reserving each rail as its own edge column/row — `[viewport | vertical rail]` over `[horizontal rail | corner]` — with the white inner viewport padded `8px` plus the border-floor compensation (a `mod()` term restoring what engines floor off the fractional border-width, so slotted content and the (0,0) of placed children sit exactly 9 system px from the frame box at every scale). Consumer sets width/height on host. The rails are the drawn `vfScrollRail` subtree (§4 — the classic 16px cell counting the frame line: divider, 14px channel, 15px arrow cells, the fixed 16px thumb, the `tileRaster` dot-dither trough), rendered as later siblings of the viewport and synced to its native scrolling by `ScrollRailController`; the viewport carries the `vf-scroll` class, which hides the native bar without touching the native scrolling. When both rails are reserved, the corner cell joins them, supplying the interior dividers the adjacent arrow cells leave to it. Every engine renders the same rail; the old `::-webkit-scrollbar` skin, its `.vf-scroll-frame` overlay contortion (WebKit quantized native scrollbar rects to whole CSS px) and the Firefox `scrollbar-color` fallback are all retired.
392
+ - **Attributes/props:** `axis: 'vertical' | 'horizontal' | 'both'` (default `'vertical'`, reflected) — which scroll rails to reserve as permanent placeholders (see "always-a-rail" below); `flush: boolean` (default false, reflected) — drops the viewport's 8px inset, keeping the border-floor term, so content and the (0,0) of placed children sit at the frame's inner edge; `corner: boolean` (default false, reflected) — reserves the bottom-right corner cell on a single-axis rail (the rail stops 15px short of the frame, the viewport spans the rest), for a grow box to land in; inert on `both`, which always has the cell; `label: string` — accessible name for the viewport (`aria-label` on the viewport, since an `aria-label` on the host cannot reach into the shadow DOM). The viewport is a **Tab stop only while its content actually overflows** — the same state `ScrollStateController` measures for the rails; a fitting scroll area used to be a focusable stop with `role: generic` and no name, a dead Tab press. Whenever it is a stop it carries a role: `role="region"` when `label` names it (a named landmark), `role="group"` when not (an unnamed region is inert, so that role is reserved for the labelled case).
393
+ - **Visual:** `display: block`; the snapped wrapper carries a real 1px black frame and a grid reserving each rail as its own edge column/row — `[viewport | vertical rail]` over `[horizontal rail | corner]` — with the white inner viewport padded `8px` plus the border-floor compensation (a `mod()` term restoring what engines floor off the fractional border-width, so slotted content and the (0,0) of placed children sit exactly 9 system px from the frame box at every scale; `flush` keeps only the compensation, and they sit exactly 1). Consumer sets width/height on host. The rails are the drawn `vfScrollRail` subtree (§4 — the classic 16px cell counting the frame line: divider, 14px channel, 15px arrow cells, the fixed 16px thumb, the `tileRaster` dot-dither trough), rendered as later siblings of the viewport and synced to its native scrolling by `ScrollRailController`; the viewport carries the `vf-scroll` class, which hides the native bar without touching the native scrolling. When both rails are reserved, the corner cell joins them, supplying the interior dividers the adjacent arrow cells leave to it; `corner` reserves the same 15×15 cell beside a single rail, its other divider continuing the rail's line across the cell — DrawGrowIcon's form, for the grow box. Every engine renders the same rail; the old `::-webkit-scrollbar` skin, its `.vf-scroll-frame` overlay contortion (WebKit quantized native scrollbar rects to whole CSS px) and the Firefox `scrollbar-color` fallback are all retired.
394
394
  - **Always-a-rail behavior:** each *reserved* axis (per `axis`) renders its rail element as a permanent placeholder — arrow buttons on an empty white channel (dither off, no thumb; System 7 drew the arrows on any bar in an active window, and a scroller outside a window always counts as active) — until the content overflows that axis, when the dither and thumb fill in and the arrows go live (an idle axis's arrows are drawn but inert — the press guard in `ScrollRailController` skips them). `ScrollStateController` (`src/scroll-state.ts`) measures both axes and writes `data-overflow-x` / `data-overflow-y` (`"true"` / `"false"`) on the scroll element; the recipe keys the dither and thumb off those attributes. The unreserved axis still scrolls natively (wheel, keyboard) but draws no rail. Shared by vf-list and vf-text-area; a future `@container scroll-state(scrollable)` query could replace the JS for slotted-content components.
395
395
  - **Inactive-window blanking:** the HIG's non-frontmost window must not display interactive scroll UX, so the controller also finds the nearest `vf-window` up the composed tree (light-DOM ancestor for a slotted scroller, shadow ancestor for `vf-window[scrollbars]`'s own edge rails), watches its reflected `active` attribute, and toggles a presence-only `data-window-inactive` on the scroll element. While present, the recipe empties dither/thumb/arrows on BOTH axes regardless of overflow — the bare channel, arrows included (unlike the idle rail, which keeps them), exactly as System 7 blanked a deactivated window's bars (its List Manager/TextEdit deactivated in-window scrollbars too). No `vf-window` ancestor → the attribute never appears: dialogs have no inactive state and a bare scroll component always draws live. Like the overflow half, this signal could one day go declarative — a custom property cascaded under `vf-window:not([active])` gating the recipe via an `@container style()` query; the rails being ordinary DOM, that migration is a plain selector swap (see the FUTURE note in scroll-state.ts).
396
- - **Document-window (TeachText) composition:** to put the rails on a window's edge rather than inset in its body, slot the scroll area into a `vf-window[flush]` sized `calc(100% + 2px·scale)` with `margin: -1px·scale` — one system pixel under the window frame on every side. Its own frame border then repaints the window's border lines exactly (no doubled frame), and a resizable window's grow box lands exactly over the rail's corner cell, giving the classic System 7 document window. `vf-window[scrollbars]` renders exactly this composition from its own shadow tree, so the one-liner and the slotted form are geometrically identical; slot it yourself when the well should sit *inset* in the body instead (the installer's read-me well).
396
+ - **Document-window (TeachText) composition:** to put the rails on a window's edge rather than inset in its body, slot the scroll area into a `vf-window[flush]` sized `calc(100% + 2px·scale)` with `margin: -1px·scale` — one system pixel under the window frame on every side. Its own frame border then repaints the window's border lines exactly (no doubled frame), and a resizable window's grow box lands exactly over the rail's corner cell, giving the classic System 7 document window. `vf-window[scrollbars]` renders exactly this composition from its own shadow tree (forwarding its `flush`, and `corner` for a resizable window without a status strip), so the one-liner and the slotted form are geometrically identical; slot it yourself when the well should sit *inset* in the body instead (the installer's read-me well).
397
397
  - **Slots:** default. **Parts:** `viewport`.
398
398
 
399
399
  #### `vf-fieldset` (`VfFieldset`, vf-fieldset.ts)
@@ -932,7 +932,7 @@
932
932
  },
933
933
  {
934
934
  "name": "vf-scroll-area",
935
- "description": "`<vf-scroll-area>` — a container whose scrollbars look like System 7.\n\nWhite box with a 1px black frame, an inner scrolling viewport, and scroll\nrails the kit draws itself as shadow DOM (the shared `vfScrollRail` recipe):\nboxed arrow buttons at each end, a loose 1-bit dot-dither trough, and the\nclassic fixed 16px thumb. The native scrollbar is hidden, never the native\nscrolling — wheel, trackpad momentum, keyboard, touch and assistive-tech\nscrolling stay the platform's, and ScrollRailController keeps the\nrail in sync while driving the classic interactions (thumb drag, trough\npaging, arrow stepping with auto-repeat). Every engine renders the same\nrail — there is no Firefox fallback skin anymore.\n\nEach reserved scroll rail is a permanent placeholder: arrow buttons on an\nempty white channel sit in the gutter even when the content fits, the\ndither and thumb filling in only once that axis overflows (System 7 drew\nan active window's no-overflow bar as arrows on a bare channel; driven\nby ScrollStateController). Which rails are reserved is set by\naxis; when both are reserved the bottom-right corner joins them.\n\nSize the host (width/height) from the outside; the viewport fills it.\n---\n\n\n### **Slots:**\n - _default_ - Scrollable content.\n\n### **CSS Properties:**\n - **--vf-scrollbar-thumb** - scrollbar thumb/elevator (white) _(default: undefined)_\n- **--vf-scrollbar-track** - the scroll trough's base color under the dot-dither (white) _(default: undefined)_\n\n### **CSS Parts:**\n - **viewport** - The inner scrolling container.",
935
+ "description": "`<vf-scroll-area>` — a container whose scrollbars look like System 7.\n\nWhite box with a 1px black frame, an inner scrolling viewport, and scroll\nrails the kit draws itself as shadow DOM (the shared `vfScrollRail` recipe):\nboxed arrow buttons at each end, a loose 1-bit dot-dither trough, and the\nclassic fixed 16px thumb. The native scrollbar is hidden, never the native\nscrolling — wheel, trackpad momentum, keyboard, touch and assistive-tech\nscrolling stay the platform's, and ScrollRailController keeps the\nrail in sync while driving the classic interactions (thumb drag, trough\npaging, arrow stepping with auto-repeat). Every engine renders the same\nrail — there is no Firefox fallback skin anymore.\n\nEach reserved scroll rail is a permanent placeholder: arrow buttons on an\nempty white channel sit in the gutter even when the content fits, the\ndither and thumb filling in only once that axis overflows (System 7 drew\nan active window's no-overflow bar as arrows on a bare channel; driven\nby ScrollStateController). Which rails are reserved is set by\naxis; when both are reserved the bottom-right corner joins them,\nand corner reserves that cell on a single-axis rail too — the\nrail stops 15px short of the frame, for a grow box to land in.\n\nSize the host (width/height) from the outside; the viewport fills it. The\nviewport insets its content 8px; flush drops that inset so content\nruns to the frame and the rails.\n---\n\n\n### **Slots:**\n - _default_ - Scrollable content.\n\n### **CSS Properties:**\n - **--vf-scrollbar-thumb** - scrollbar thumb/elevator (white) _(default: undefined)_\n- **--vf-scrollbar-track** - the scroll trough's base color under the dot-dither (white) _(default: undefined)_\n\n### **CSS Parts:**\n - **viewport** - The inner scrolling container.",
936
936
  "attributes": [
937
937
  {
938
938
  "name": "axis",
@@ -943,6 +943,16 @@
943
943
  { "name": "both" }
944
944
  ]
945
945
  },
946
+ {
947
+ "name": "flush",
948
+ "description": "Drop the viewport's 8px inset: slotted content and the (0,0) of placed\nchildren sit at the frame's inner edge, one system px from the frame\nbox (the border-floor compensation stays — see the viewport rule).\n`vf-window[scrollbars]` forwards its own `flush` here.",
949
+ "values": []
950
+ },
951
+ {
952
+ "name": "corner",
953
+ "description": "Reserve the bottom-right corner cell on a single-axis rail: the rail\nstops 15px short of the frame and the viewport spans the rest, leaving\nthe 15×15 cell — with the two dividers a `both` rail's corner carries —\nfor a grow box to land in. A `both` rail always has the cell, so the\nflag changes nothing there. `vf-window[scrollbars resizable]` sets it.",
954
+ "values": []
955
+ },
946
956
  {
947
957
  "name": "label",
948
958
  "description": "Accessible name for the scrolling viewport, applied as its `aria-label`\n(an `aria-label` on the host would not reach into the shadow DOM). The\nviewport is keyboard-focusable while its content overflows, so without a\nname it is announced only as an anonymous scrollable group; setting\n`label` also promotes it to a named `role=\"region\"` landmark. While\n`label` is empty the viewport is a plain `group` when scrollable (an\nunnamed region is inert) and role-less when not.",
@@ -1356,12 +1366,12 @@
1356
1366
  },
1357
1367
  {
1358
1368
  "name": "flush",
1359
- "description": "Remove the default 12px body padding.",
1369
+ "description": "Remove the default 12px body padding. Under `scrollbars` the body has\nnone to remove, so the flag reaches the built-in scroll area instead\nand drops its viewport's 8px inset: content runs to the frame and the\nrails, and the (0,0) of placed children is the content region's corner.",
1360
1370
  "values": []
1361
1371
  },
1362
1372
  {
1363
1373
  "name": "scrollbars",
1364
- "description": "Put System 7 scroll rails on the window edge — the classic document\nwindow. The body slot renders inside a built-in `vf-scroll-area` pulled\none system pixel under the frame on every side, so the rails repaint the\nborder lines and a `resizable` window's grow box lands in the corner\ncell. Values mirror `vf-scroll-area`'s `axis`; the `heading` names the\nscroll region; the viewport part is re-exported. Implies `flush` (the\nviewport carries its own padding). The slotted composition (SPEC §5\nvf-scroll-area) still works for windows that want an inset well instead.",
1374
+ "description": "Put System 7 scroll rails on the window edge — the classic document\nwindow. The body slot renders inside a built-in `vf-scroll-area` pulled\none system pixel under the frame on every side, so the rails repaint the\nborder lines and a `resizable` window's grow box lands in the corner\ncell — reserved on a single-axis rail too (the area's `corner`), unless\na populated status strip holds the grow box, when the rail runs edge to\nedge onto the strip's rule. Values mirror `vf-scroll-area`'s `axis`; the\n`heading` names the scroll region; the viewport part is re-exported.\nThe body's own padding goes; the viewport keeps its 8px inset unless\n`flush`, which passes through. The slotted composition (SPEC §5\nvf-scroll-area) still works for windows that want an inset well instead.",
1365
1375
  "values": [
1366
1376
  { "name": "vertical" },
1367
1377
  { "name": "horizontal" },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
3
3
  "name": "vintage-frames",
4
- "version": "0.5.4",
4
+ "version": "0.5.5",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -2239,7 +2239,7 @@
2239
2239
  },
2240
2240
  {
2241
2241
  "name": "vf-scroll-area",
2242
- "description": "`<vf-scroll-area>` — a container whose scrollbars look like System 7.\n\nWhite box with a 1px black frame, an inner scrolling viewport, and scroll\nrails the kit draws itself as shadow DOM (the shared `vfScrollRail` recipe):\nboxed arrow buttons at each end, a loose 1-bit dot-dither trough, and the\nclassic fixed 16px thumb. The native scrollbar is hidden, never the native\nscrolling — wheel, trackpad momentum, keyboard, touch and assistive-tech\nscrolling stay the platform's, and ScrollRailController keeps the\nrail in sync while driving the classic interactions (thumb drag, trough\npaging, arrow stepping with auto-repeat). Every engine renders the same\nrail — there is no Firefox fallback skin anymore.\n\nEach reserved scroll rail is a permanent placeholder: arrow buttons on an\nempty white channel sit in the gutter even when the content fits, the\ndither and thumb filling in only once that axis overflows (System 7 drew\nan active window's no-overflow bar as arrows on a bare channel; driven\nby ScrollStateController). Which rails are reserved is set by\naxis; when both are reserved the bottom-right corner joins them.\n\nSize the host (width/height) from the outside; the viewport fills it.\n---\n\n\n### **Slots:**\n - _default_ - Scrollable content.\n\n### **CSS Properties:**\n - **--vf-scrollbar-thumb** - scrollbar thumb/elevator (white) _(default: undefined)_\n- **--vf-scrollbar-track** - the scroll trough's base color under the dot-dither (white) _(default: undefined)_\n\n### **CSS Parts:**\n - **viewport** - The inner scrolling container.",
2242
+ "description": "`<vf-scroll-area>` — a container whose scrollbars look like System 7.\n\nWhite box with a 1px black frame, an inner scrolling viewport, and scroll\nrails the kit draws itself as shadow DOM (the shared `vfScrollRail` recipe):\nboxed arrow buttons at each end, a loose 1-bit dot-dither trough, and the\nclassic fixed 16px thumb. The native scrollbar is hidden, never the native\nscrolling — wheel, trackpad momentum, keyboard, touch and assistive-tech\nscrolling stay the platform's, and ScrollRailController keeps the\nrail in sync while driving the classic interactions (thumb drag, trough\npaging, arrow stepping with auto-repeat). Every engine renders the same\nrail — there is no Firefox fallback skin anymore.\n\nEach reserved scroll rail is a permanent placeholder: arrow buttons on an\nempty white channel sit in the gutter even when the content fits, the\ndither and thumb filling in only once that axis overflows (System 7 drew\nan active window's no-overflow bar as arrows on a bare channel; driven\nby ScrollStateController). Which rails are reserved is set by\naxis; when both are reserved the bottom-right corner joins them,\nand corner reserves that cell on a single-axis rail too — the\nrail stops 15px short of the frame, for a grow box to land in.\n\nSize the host (width/height) from the outside; the viewport fills it. The\nviewport insets its content 8px; flush drops that inset so content\nruns to the frame and the rails.\n---\n\n\n### **Slots:**\n - _default_ - Scrollable content.\n\n### **CSS Properties:**\n - **--vf-scrollbar-thumb** - scrollbar thumb/elevator (white) _(default: undefined)_\n- **--vf-scrollbar-track** - the scroll trough's base color under the dot-dither (white) _(default: undefined)_\n\n### **CSS Parts:**\n - **viewport** - The inner scrolling container.",
2243
2243
  "doc-url": "",
2244
2244
  "attributes": [
2245
2245
  {
@@ -2250,6 +2250,16 @@
2250
2250
  "default": "'vertical'"
2251
2251
  }
2252
2252
  },
2253
+ {
2254
+ "name": "flush",
2255
+ "description": "Drop the viewport's 8px inset: slotted content and the (0,0) of placed\nchildren sit at the frame's inner edge, one system px from the frame\nbox (the border-floor compensation stays — see the viewport rule).\n`vf-window[scrollbars]` forwards its own `flush` here.",
2256
+ "value": { "type": "boolean", "default": "false" }
2257
+ },
2258
+ {
2259
+ "name": "corner",
2260
+ "description": "Reserve the bottom-right corner cell on a single-axis rail: the rail\nstops 15px short of the frame and the viewport spans the rest, leaving\nthe 15×15 cell — with the two dividers a `both` rail's corner carries —\nfor a grow box to land in. A `both` rail always has the cell, so the\nflag changes nothing there. `vf-window[scrollbars resizable]` sets it.",
2261
+ "value": { "type": "boolean", "default": "false" }
2262
+ },
2253
2263
  {
2254
2264
  "name": "label",
2255
2265
  "description": "Accessible name for the scrolling viewport, applied as its `aria-label`\n(an `aria-label` on the host would not reach into the shadow DOM). The\nviewport is keyboard-focusable while its content overflows, so without a\nname it is announced only as an anonymous scrollable group; setting\n`label` also promotes it to a named `role=\"region\"` landmark. While\n`label` is empty the viewport is a plain `group` when scrollable (an\nunnamed region is inert) and role-less when not.",
@@ -2275,6 +2285,16 @@
2275
2285
  "description": "Which scroll rails to reserve as permanent placeholders: `vertical`\n(default), `horizontal`, or `both`. Each reserved rail shows an empty white\nchannel until its axis overflows; the unreserved axis still scrolls\nnatively (wheel, keyboard) but draws no rail.",
2276
2286
  "type": "'vertical' | 'horizontal' | 'both'"
2277
2287
  },
2288
+ {
2289
+ "name": "flush",
2290
+ "description": "Drop the viewport's 8px inset: slotted content and the (0,0) of placed\nchildren sit at the frame's inner edge, one system px from the frame\nbox (the border-floor compensation stays — see the viewport rule).\n`vf-window[scrollbars]` forwards its own `flush` here.",
2291
+ "type": "boolean"
2292
+ },
2293
+ {
2294
+ "name": "corner",
2295
+ "description": "Reserve the bottom-right corner cell on a single-axis rail: the rail\nstops 15px short of the frame and the viewport spans the rest, leaving\nthe 15×15 cell — with the two dividers a `both` rail's corner carries —\nfor a grow box to land in. A `both` rail always has the cell, so the\nflag changes nothing there. `vf-window[scrollbars resizable]` sets it.",
2296
+ "type": "boolean"
2297
+ },
2278
2298
  {
2279
2299
  "name": "label",
2280
2300
  "description": "Accessible name for the scrolling viewport, applied as its `aria-label`\n(an `aria-label` on the host would not reach into the shadow DOM). The\nviewport is keyboard-focusable while its content overflows, so without a\nname it is announced only as an anonymous scrollable group; setting\n`label` also promotes it to a named `role=\"region\"` landmark. While\n`label` is empty the viewport is a plain `group` when scrollable (an\nunnamed region is inert) and role-less when not.",
@@ -3275,12 +3295,12 @@
3275
3295
  },
3276
3296
  {
3277
3297
  "name": "flush",
3278
- "description": "Remove the default 12px body padding.",
3298
+ "description": "Remove the default 12px body padding. Under `scrollbars` the body has\nnone to remove, so the flag reaches the built-in scroll area instead\nand drops its viewport's 8px inset: content runs to the frame and the\nrails, and the (0,0) of placed children is the content region's corner.",
3279
3299
  "value": { "type": "boolean", "default": "false" }
3280
3300
  },
3281
3301
  {
3282
3302
  "name": "scrollbars",
3283
- "description": "Put System 7 scroll rails on the window edge — the classic document\nwindow. The body slot renders inside a built-in `vf-scroll-area` pulled\none system pixel under the frame on every side, so the rails repaint the\nborder lines and a `resizable` window's grow box lands in the corner\ncell. Values mirror `vf-scroll-area`'s `axis`; the `heading` names the\nscroll region; the viewport part is re-exported. Implies `flush` (the\nviewport carries its own padding). The slotted composition (SPEC §5\nvf-scroll-area) still works for windows that want an inset well instead.",
3303
+ "description": "Put System 7 scroll rails on the window edge — the classic document\nwindow. The body slot renders inside a built-in `vf-scroll-area` pulled\none system pixel under the frame on every side, so the rails repaint the\nborder lines and a `resizable` window's grow box lands in the corner\ncell — reserved on a single-axis rail too (the area's `corner`), unless\na populated status strip holds the grow box, when the rail runs edge to\nedge onto the strip's rule. Values mirror `vf-scroll-area`'s `axis`; the\n`heading` names the scroll region; the viewport part is re-exported.\nThe body's own padding goes; the viewport keeps its 8px inset unless\n`flush`, which passes through. The slotted composition (SPEC §5\nvf-scroll-area) still works for windows that want an inset well instead.",
3284
3304
  "value": {
3285
3305
  "type": "'vertical' | 'horizontal' | 'both' | undefined"
3286
3306
  }
@@ -3366,12 +3386,12 @@
3366
3386
  },
3367
3387
  {
3368
3388
  "name": "flush",
3369
- "description": "Remove the default 12px body padding.",
3389
+ "description": "Remove the default 12px body padding. Under `scrollbars` the body has\nnone to remove, so the flag reaches the built-in scroll area instead\nand drops its viewport's 8px inset: content runs to the frame and the\nrails, and the (0,0) of placed children is the content region's corner.",
3370
3390
  "type": "boolean"
3371
3391
  },
3372
3392
  {
3373
3393
  "name": "scrollbars",
3374
- "description": "Put System 7 scroll rails on the window edge — the classic document\nwindow. The body slot renders inside a built-in `vf-scroll-area` pulled\none system pixel under the frame on every side, so the rails repaint the\nborder lines and a `resizable` window's grow box lands in the corner\ncell. Values mirror `vf-scroll-area`'s `axis`; the `heading` names the\nscroll region; the viewport part is re-exported. Implies `flush` (the\nviewport carries its own padding). The slotted composition (SPEC §5\nvf-scroll-area) still works for windows that want an inset well instead.",
3394
+ "description": "Put System 7 scroll rails on the window edge — the classic document\nwindow. The body slot renders inside a built-in `vf-scroll-area` pulled\none system pixel under the frame on every side, so the rails repaint the\nborder lines and a `resizable` window's grow box lands in the corner\ncell — reserved on a single-axis rail too (the area's `corner`), unless\na populated status strip holds the grow box, when the rail runs edge to\nedge onto the strip's rule. Values mirror `vf-scroll-area`'s `axis`; the\n`heading` names the scroll region; the viewport part is re-exported.\nThe body's own padding goes; the viewport keeps its 8px inset unless\n`flush`, which passes through. The slotted composition (SPEC §5\nvf-scroll-area) still works for windows that want an inset well instead.",
3375
3395
  "type": "'vertical' | 'horizontal' | 'both' | undefined"
3376
3396
  },
3377
3397
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vintage-frames",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "Lit web components that emulate the look and feel of classic Mac OS System 7",
5
5
  "type": "module",
6
6
  "license": "MIT",