@gjermundgaraba-designs/pixel-paper 0.22.0 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +6 -5
- package/dist/src/bench/bench.d.ts +7 -4
- package/dist/src/bench/bench.d.ts.map +1 -1
- package/dist/src/bench/bench.js +3 -2
- package/package.json +1 -1
- package/src/bench/bench.ts +7 -4
- package/src/pixel-paper.css +21 -5
- package/src/tokens.css +3 -0
package/DESIGN.md
CHANGED
|
@@ -216,6 +216,7 @@ spacing:
|
|
|
216
216
|
reel-gutter: "16px"
|
|
217
217
|
reel-column-min: "280px"
|
|
218
218
|
reel-pane-min: "120px"
|
|
219
|
+
bench-work-min: "152px"
|
|
219
220
|
components:
|
|
220
221
|
button:
|
|
221
222
|
backgroundColor: "{colors.paper}"
|
|
@@ -924,17 +925,17 @@ The Deck is one centred column, `max-width: 1160px` (`--deck`), padded 24px top,
|
|
|
924
925
|
|
|
925
926
|
Frames with no surface of their own (Deck, Wall, Stage, Bench) are described here rather than among the components.
|
|
926
927
|
|
|
927
|
-
**Bench:** a page whose work is the window: a task's terminals and editors side by side, which a reading column would cramp and a frame of its own would scroll twice. Fixed from the top bar's lower edge (hung from it by anchor positioning, like the stage and the rail) to the status bar, the window wide, or from the rail's edge beside a rail (a fixed box takes nothing from `.railed`'s padding, so the bench reads `--rail` itself and follows the reader's width), and from the left edge at 900px and under, where the rail is a drawer. It is a grid of two rows: the head (a PageHead, notices, the rail's open button first) at its own height, padded
|
|
928
|
+
**Bench:** a page whose work is the window: a task's terminals and editors side by side, which a reading column would cramp and a frame of its own would scroll twice. Fixed from the top bar's lower edge (hung from it by anchor positioning, like the stage and the rail) to the status bar, the window wide, or from the rail's edge beside a rail (a fixed box takes nothing from `.railed`'s padding, so the bench reads `--rail` itself and follows the reader's width), and from the left edge at 900px and under, where the rail is a drawer. It is a grid of two rows: the head (a PageHead, notices, the rail's open button first) at its own height, padded 24px at the top and 16px at the sides with 24px between its parts, and the work in all the height left, where a reel takes 100% of it. **The work keeps a floor:** `--bench-work-min` (152px, one pane at `--reel-pane-min` between a reel's gutters, the least a reel still shows a window in), whatever the head holds, or all of the bench but 64px on a window too short for both (a bench under 216px), the head's padding and a small button, so the head's first line, the rail's open button at 900px and under, never vanishes. A head taller than what the floor leaves it (a PageHead, a status and two notices on a landscape phone) stops there and scrolls itself, so all of it can be reached while the work stays where it is: the rows are `minmax(0, max-content) minmax(min(var(--bench-work-min), 100% - 64px), 1fr)`. That was chosen over scrolling the whole bench, which would scroll a page around a reel that scrolls itself (a wheel over the reel, held in it, would never reach the page) and push the work off the window to read the head: the head is read once, the work is what the reader keeps in view. A scroller clips what prints past it, so the head pads its foot by 6px (a button's 3px shadow, a focus ring's 4px) and hands the 6px back in a negative margin, the work starting where it would. A keyboard scrolls the head with the arrows from a control in it, and a screen reader reads it whole. The head's 16px is a reel's gutter (`--reel-gutter`), so the head's edge lines up with the windows' and the reel's own top gutter is the space between them. The page does not scroll: the work scrolls itself where it must (a reel's columns sideways, and down where a column is taller). While a dialog in its work is open the bench is lifted over the rail and the bars (see Dialog). The Deck stays the frame for pages that read; the Stage, for a canvas with no head.
|
|
928
929
|
|
|
929
|
-
**Stage:** the ground itself for a canvas: fixed from the top bar's lower edge (it hangs from the bar by anchor positioning, so a phone's two-line bar fits) to the window's edges. It does not scroll; what is on it pans. Its floating tools sit 16px in from the left edge, centred (along the bottom, centred, on a phone); its bar sits 16px down from the top, centred, wrapping when narrow.
|
|
930
|
+
**Stage:** the ground itself for a canvas: fixed from the top bar's lower edge (it hangs from the bar by anchor positioning, so a phone's two-line bar fits) to the window's edges. It does not scroll; what is on it pans. A dialog in its canvas lifts it over the bars while it is open (see Dialog). Its floating tools sit 16px in from the left edge, centred (along the bottom, centred, on a phone); its bar sits 16px down from the top, centred, wrapping when narrow.
|
|
930
931
|
|
|
931
|
-
Dialogs are native `<dialog>` elements that fill the viewport as a veil; the card centres in a 24px pad (or sits at 18vh for the command palette) at `min(680px, 100%)`, or `min(440px, 100%)` when narrow, capped at `calc(100vh - 48px)` with its body scrolling between a fixed title bar and a fixed action row. The Banner is fixed 16px above the bottom edge, centred, at most `min(680px, 100vw - 32px)`.
|
|
932
|
+
Dialogs are native `<dialog>` elements that fill the viewport as a veil, over everything on the page, from a Deck or from inside a Bench or a Stage alike; the card centres in a 24px pad (or sits at 18vh for the command palette) at `min(680px, 100%)`, or `min(440px, 100%)` when narrow, capped at `calc(100vh - 48px)` with its body scrolling between a fixed title bar and a fixed action row. The Banner is fixed 16px above the bottom edge, centred, at most `min(680px, 100vw - 32px)`.
|
|
932
933
|
|
|
933
934
|
Breakpoints: 600px (phone; the page title steps to 18px, stats two across, the wall's corner joins the flow, toasts span the bottom), 900px (board columns stack, above it they stretch; a stat's figure steps to 22px).
|
|
934
935
|
|
|
935
936
|
### Named Rules
|
|
936
937
|
|
|
937
|
-
**The Panel Scroll Rule.** The page scrolls; a panel does not, except a board column above 900px, a card body inside a dialog, the rail, a window's body (a window is sized by the canvas, not by its content), and a reel, which scrolls sideways, and down where a column is taller than it, its windows sized by its columns. A stage never scrolls, and nor does a bench
|
|
938
|
+
**The Panel Scroll Rule.** The page scrolls; a panel does not, except a board column above 900px, a card body inside a dialog, the rail, a window's body (a window is sized by the canvas, not by its content), and a reel, which scrolls sideways, and down where a column is taller than it, its windows sized by its columns. A stage never scrolls, and nor does a bench: its work scrolls itself, and its head scrolls only when the window leaves it less than it holds once the work has its floor. A wide table, a long code line or a run of bar columns scrolls horizontally inside its own panel and never widens the deck.
|
|
938
939
|
|
|
939
940
|
**The 24px Target Rule.** Every target is at least 24px square. A control drawn smaller (a tab, a glyph-switch option, a filter chip, a row toggle, a clickable mark or tag, a text button, a crumb, an error-summary link) keeps its look and takes the pointer over an invisible 24px square centred on it; an icon button never gives up its 24px to a full line (a tag beside it clips first), and links in a list stand 24px apart so no two squares overlap.
|
|
940
941
|
|
|
@@ -1072,7 +1073,7 @@ The printed button: a paper rectangle in a 2px ink frame that casts a 3px shadow
|
|
|
1072
1073
|
|
|
1073
1074
|
### Cards (dialogs)
|
|
1074
1075
|
|
|
1075
|
-
**Dialog** is a Submodel over `@foldkit/ui`'s Dialog: a `<dialog class="veil">` that fills the viewport, opened with `show()` in place rather than `showModal()` in the top layer. That is a deliberate exception to the baseline's "prefer the platform" for overlays: Foldkit's Dialog (through `Dom.showDialog`) makes everything outside the dialog `inert` and `aria-hidden`, traps focus, handles Escape on the topmost dialog and returns focus on close, so the platform's modal behaviour is reproduced, not dropped; what is lost is the top layer and its `::backdrop`. The veil is therefore an element of its own, `div.veil-backdrop` (fixed, Veil with the ink checker grain, entering in 3 steps over 0.12s), under `div.veil-pad` (`.top` for the palette), which lets a press through everywhere but on the card it holds; a press on the veil, Escape, or a control given the `closeButton` group closes it and reports `Closed`. While its work must land in it (a save whose failure the reader has to see), the parent holds those three: its update passes `isCloseHeld` to the dialog's (`Dialog.update(model, message, { isCloseHeld })`, or `foldDialog`'s `isCloseHeld: (model) => model.isSaving`), read from its own state as each Message arrives, so the hold starts with the work, ends with it, and covers a key pressed before the next render: the dialog stays open and reports no `Closed`. Nothing is stored, so there is nothing to let go of. Opening and closing are the parent's, through `Dialog.open` and `Dialog.close` in its update, and a step the parent asked for reports nothing; `Dialog.foldDialog` lifts a dialog the parent always holds (its update, `open` and `close`) into the parent at once, `Closed` reported only where the parent maps it. The content is the parent's `toView`, which receives the attribute groups to spread (`title`, `description`, `initialFocus`, `closeButton`, `actionBar`). Focus starts on the element given the `initialFocus` group, else the first control. The Card inside names the dialog through its title (the `title` group, `aria-labelledby`); a dialog without a heading takes `label`, printed for screen readers only. `isAlert` makes it an `alertdialog`, and `hasDescription` points `aria-describedby` at the element given the `description` group. Because the page outside is inert and hidden, anything that must be heard or reached while it is open renders inside it: the topmost open dialog hosts the page's live region and the toast stack, both outside the card, through its `toLiveRegionView` (see Building components).
|
|
1076
|
+
**Dialog** is a Submodel over `@foldkit/ui`'s Dialog: a `<dialog class="veil">` that fills the viewport, opened with `show()` in place rather than `showModal()` in the top layer. That is a deliberate exception to the baseline's "prefer the platform" for overlays: Foldkit's Dialog (through `Dom.showDialog`) makes everything outside the dialog `inert` and `aria-hidden`, traps focus, handles Escape on the topmost dialog and returns focus on close, so the platform's modal behaviour is reproduced, not dropped; what is lost is the top layer and its `::backdrop`. **Out of the top layer, a dialog layers where it is rendered:** its inline z-index counts inside its nearest stacking context. In the page's flow (a Deck, a Wall) that is the page, and the veil prints over everything. A fixed frame, a Bench or a Stage, is a stacking context of its own, which the rail (fixed, later in the page) and the bars would print over, so while the frame holds an open dialog (`:is(.bench, .stage):has(dialog.veil[open])`) the stylesheet lifts the frame to `z-index: 250`: over the top bar and the status bar (40), the rail and its splitter, a Banner (150) and a menu's slip (200). It is lifted only then, because at rest the rail's splitter lies over the bench's edge and a slip opened from the head prints over the frame. So a dialog is rendered in the page, in a bench's work (`body`) or in a stage's canvas (`body`): never in the rail, whose column is fixed too and is hidden on a phone, nor in a stage's tools or bar, whose `translate` shrinks a fixed veil to their own box. A lifted frame still prints under a dialog in the page's flow, so a dialog in the page closes before one in a frame opens (a palette's command closes the palette first). The veil is therefore an element of its own, `div.veil-backdrop` (fixed, Veil with the ink checker grain, entering in 3 steps over 0.12s), under `div.veil-pad` (`.top` for the palette), which lets a press through everywhere but on the card it holds; a press on the veil, Escape, or a control given the `closeButton` group closes it and reports `Closed`. While its work must land in it (a save whose failure the reader has to see), the parent holds those three: its update passes `isCloseHeld` to the dialog's (`Dialog.update(model, message, { isCloseHeld })`, or `foldDialog`'s `isCloseHeld: (model) => model.isSaving`), read from its own state as each Message arrives, so the hold starts with the work, ends with it, and covers a key pressed before the next render: the dialog stays open and reports no `Closed`. Nothing is stored, so there is nothing to let go of. Opening and closing are the parent's, through `Dialog.open` and `Dialog.close` in its update, and a step the parent asked for reports nothing; `Dialog.foldDialog` lifts a dialog the parent always holds (its update, `open` and `close`) into the parent at once, `Closed` reported only where the parent maps it. The content is the parent's `toView`, which receives the attribute groups to spread (`title`, `description`, `initialFocus`, `closeButton`, `actionBar`). Focus starts on the element given the `initialFocus` group, else the first control. The Card inside names the dialog through its title (the `title` group, `aria-labelledby`); a dialog without a heading takes `label`, printed for screen readers only. `isAlert` makes it an `alertdialog`, and `hasDescription` points `aria-describedby` at the element given the `description` group. Because the page outside is inert and hidden, anything that must be heard or reached while it is open renders inside it: the topmost open dialog hosts the page's live region and the toast stack, both outside the card, through its `toLiveRegionView` (see Building components).
|
|
1076
1077
|
|
|
1077
1078
|
**Card** → `div.card` (`.narrow`; `form.card` from `Card.formView`, named by its title (`aria-label`), so a form landmark; no role of its own, the Dialog around it is the dialog): a paper panel with the card shadow, `min(680px, 100%)` (440px narrow), entering in 3 steps over 0.14s from `scale(0.97)`. An inverted title bar `header.card-tb` (`6px 8px 6px 12px`, 13px uppercase 0.06em (`--tracking-head`), a close IconButton when it has `closeAttributes`, held by `Card.formView`'s `isBusy` while work the reader may not walk away from runs: `aria-disabled`, in the keyboard, its `closeAttributes` and so its handler dropped, faded to 0.6 on the bar, as a held button in a panel's title bar), a scrolling `div.card-body` (16px, 14px gap; a word longer than the card, a path or an id, breaks rather than widening it), and `div.card-actions` (`12px 16px`) over a 2px ink rule: `lead` first, then `span.card-acts` holding the actions at the right, which drop below the lead together when the bar wraps. Inside a Dialog, where the page's keys wait, the bar moves focus between its actions: `h` or ← to the one before, `l` or → to the one after, in the order they print, stopping at the ends, never pressing one (Enter, Space and Tab stay the browser's). The keys are bound by a Mount on the bar (`BindActionKeys`), which reads the real key event: only a key whose target is one of that bar's own buttons or links, unmodified, outside an IME and not already handled, and only when there is an action that way, moves focus and has its default prevented. A field, the title bar's close, a menu's items and a nested dialog's bar keep their keys. A disabled action is passed over; an `aria-disabled` one (held: busy, done or disabled) is still a stop and still ignores presses. **Card.formView** is the one way to make a form card: its `body` in one Fields group, then the action bar's `lead` (a form's own delete, before the push), cancel (`cancel`, closing through `closeAttributes`) and the primary default submit button (`submit`, its id `Card.submitId(id)`). One flag, `isBusy`, holds every way the form could change or leave while its work runs: the submit button prints busy and turns `type="button"`, the close glyph and cancel are held with their close attributes dropped, and the Fields group is natively disabled and `aria-busy`, so nothing changes under the send and nothing sends twice. In a Dialog, the state that sets `isBusy` is the `isCloseHeld` the parent passes the Dialog's update, so Escape and the veil are held with it, and a failed send frees both, the reason on the field (the specimen's rename refuses a name with a slash). `notices` print above the Fields group, outside the hold: what the page says while the form is open (a lost connection with its retry), whose controls stay live while it sends. `isSubmitDisabled` holds the submit button alone while there is nothing to send (a name unchanged), the fields and cancel live. The fields leave the keyboard as they are held, so the update moves focus to the submit button as it sends (`Focus.Focus({ id: Card.submitId(id) })`), and it still ignores `onSubmit` while busy, for an Enter that raced the render. A ConfirmDialog with `isDanger` still opens on cancel.
|
|
1078
1079
|
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { Html, HtmlBuilder } from "foldkit/html";
|
|
2
2
|
/** Configuration for rendering a bench with `view`. */
|
|
3
3
|
export type ViewConfig = Readonly<{
|
|
4
|
-
/** Above the work, at its own height
|
|
4
|
+
/** Above the work, at its own height while the work keeps its floor, past which it scrolls:
|
|
5
|
+
* a PageHead, notices, and a Rail's open button first. */
|
|
5
6
|
head: ReadonlyArray<Html | string>;
|
|
6
|
-
/** The work, taking the rest of the window's height
|
|
7
|
+
/** The work, taking the rest of the window's height and never less than
|
|
8
|
+
* `--bench-work-min`: a Reel, which fills it, and the page's dialogs. */
|
|
7
9
|
body: ReadonlyArray<Html | string>;
|
|
8
10
|
}>;
|
|
9
11
|
/** A page whose work is the window: its head at its own height, then the work in all the
|
|
10
12
|
* height left, from under the top bar to the window's bottom and edge to edge (beside a Rail,
|
|
11
|
-
* from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll
|
|
12
|
-
* the work scrolls itself where it must (a reel's columns, sideways)
|
|
13
|
+
* from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll:
|
|
14
|
+
* the work scrolls itself where it must (a reel's columns, sideways), and on a short window
|
|
15
|
+
* the head scrolls in what the work's floor leaves it. */
|
|
13
16
|
export declare const view: <Message>(config: ViewConfig, h: HtmlBuilder<Message>) => Html;
|
|
14
17
|
//# sourceMappingURL=bench.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bench.d.ts","sourceRoot":"","sources":["../../../src/bench/bench.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAItD,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC
|
|
1
|
+
{"version":3,"file":"bench.d.ts","sourceRoot":"","sources":["../../../src/bench/bench.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAItD,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC;+DAC2D;IAC3D,IAAI,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACnC;8EAC0E;IAC1E,IAAI,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;CACpC,CAAC,CAAC;AAEH;;;;2DAI2D;AAC3D,eAAO,MAAM,IAAI,GAAI,OAAO,UAAU,UAAU,KAAK,WAAW,CAAC,OAAO,CAAC,KAAG,IAO3E,CAAC"}
|
package/dist/src/bench/bench.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
|
|
2
2
|
/** A page whose work is the window: its head at its own height, then the work in all the
|
|
3
3
|
* height left, from under the top bar to the window's bottom and edge to edge (beside a Rail,
|
|
4
|
-
* from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll
|
|
5
|
-
* the work scrolls itself where it must (a reel's columns, sideways)
|
|
4
|
+
* from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll:
|
|
5
|
+
* the work scrolls itself where it must (a reel's columns, sideways), and on a short window
|
|
6
|
+
* the head scrolls in what the work's floor leaves it. */
|
|
6
7
|
export const view = (config, h) => {
|
|
7
8
|
const { head, body } = config;
|
|
8
9
|
return __foldkitBrandViewResult((h.main([h.Id("main"), h.Class("bench")], [h.div([h.Class("bench-head")], head), h.div([h.Class("bench-work")], body)])), "@gjermundgaraba-designs/pixel-paper/src/bench/bench.js#view");
|
package/package.json
CHANGED
package/src/bench/bench.ts
CHANGED
|
@@ -4,16 +4,19 @@ import type { Html, HtmlBuilder } from "foldkit/html";
|
|
|
4
4
|
|
|
5
5
|
/** Configuration for rendering a bench with `view`. */
|
|
6
6
|
export type ViewConfig = Readonly<{
|
|
7
|
-
/** Above the work, at its own height
|
|
7
|
+
/** Above the work, at its own height while the work keeps its floor, past which it scrolls:
|
|
8
|
+
* a PageHead, notices, and a Rail's open button first. */
|
|
8
9
|
head: ReadonlyArray<Html | string>;
|
|
9
|
-
/** The work, taking the rest of the window's height
|
|
10
|
+
/** The work, taking the rest of the window's height and never less than
|
|
11
|
+
* `--bench-work-min`: a Reel, which fills it, and the page's dialogs. */
|
|
10
12
|
body: ReadonlyArray<Html | string>;
|
|
11
13
|
}>;
|
|
12
14
|
|
|
13
15
|
/** A page whose work is the window: its head at its own height, then the work in all the
|
|
14
16
|
* height left, from under the top bar to the window's bottom and edge to edge (beside a Rail,
|
|
15
|
-
* from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll
|
|
16
|
-
* the work scrolls itself where it must (a reel's columns, sideways)
|
|
17
|
+
* from the rail's edge). The main landmark (`<main id="main">`). The page does not scroll:
|
|
18
|
+
* the work scrolls itself where it must (a reel's columns, sideways), and on a short window
|
|
19
|
+
* the head scrolls in what the work's floor leaves it. */
|
|
17
20
|
export const view = <Message>(config: ViewConfig, h: HtmlBuilder<Message>): Html => {
|
|
18
21
|
const { head, body } = config;
|
|
19
22
|
|
package/src/pixel-paper.css
CHANGED
|
@@ -2732,6 +2732,15 @@ dialog.veil:focus {
|
|
|
2732
2732
|
outline: none;
|
|
2733
2733
|
}
|
|
2734
2734
|
|
|
2735
|
+
/* out of the top layer, a dialog's z-index counts inside its nearest stacking context, and a
|
|
2736
|
+
fixed frame is one: while a bench or a stage holds an open dialog the frame itself is lifted,
|
|
2737
|
+
over the bars (40), the rail and its splitter, a banner (150) and a slip (200), as a dialog
|
|
2738
|
+
in the page's flow already prints over them. Lifted only then: at rest the rail's splitter
|
|
2739
|
+
lies over the frame's edge and a slip from its head prints over it */
|
|
2740
|
+
:is(.bench, .stage):has(dialog.veil[open]) {
|
|
2741
|
+
z-index: 250;
|
|
2742
|
+
}
|
|
2743
|
+
|
|
2735
2744
|
.veil-pad {
|
|
2736
2745
|
position: relative;
|
|
2737
2746
|
min-height: 100%;
|
|
@@ -5186,8 +5195,10 @@ dialog.veil:focus {
|
|
|
5186
5195
|
|
|
5187
5196
|
/* hung from the top bar's lower edge like the stage, down to the status bar, edge to edge, or
|
|
5188
5197
|
from the rail's edge beside one (a fixed box takes nothing from .railed's padding). The head
|
|
5189
|
-
takes its own height
|
|
5190
|
-
|
|
5198
|
+
takes its own height while the work keeps at least --bench-work-min, or all but the head's
|
|
5199
|
+
first 64px (its padding and a small button: the rail's open button) on a window too short
|
|
5200
|
+
for both; past that the head scrolls itself. The work takes the rest and lays out what fills it (a reel's height is 100%
|
|
5201
|
+
of it). The page does not scroll */
|
|
5191
5202
|
.bench {
|
|
5192
5203
|
position: fixed;
|
|
5193
5204
|
top: anchor(--topbar bottom, 0px);
|
|
@@ -5195,7 +5206,7 @@ dialog.veil:focus {
|
|
|
5195
5206
|
bottom: var(--statusbar-h, 0px);
|
|
5196
5207
|
left: 0;
|
|
5197
5208
|
display: grid;
|
|
5198
|
-
grid-template-rows:
|
|
5209
|
+
grid-template-rows: minmax(0, max-content) minmax(min(var(--bench-work-min), 100% - 64px), 1fr);
|
|
5199
5210
|
}
|
|
5200
5211
|
|
|
5201
5212
|
.railed > .bench {
|
|
@@ -5203,11 +5214,16 @@ dialog.veil:focus {
|
|
|
5203
5214
|
}
|
|
5204
5215
|
|
|
5205
5216
|
/* the head lines up with a reel's windows, a reel's gutter in from the edge; the reel's own
|
|
5206
|
-
gutter is the space between the head and the windows
|
|
5217
|
+
gutter is the space between the head and the windows. A scroller clips at its padding, so
|
|
5218
|
+
the head pads its foot by the ink a control prints past its box (a 3px shadow, a 4px focus
|
|
5219
|
+
ring) and hands that back to the work, which starts where it would */
|
|
5207
5220
|
.bench-head {
|
|
5208
5221
|
display: grid;
|
|
5222
|
+
align-content: start;
|
|
5209
5223
|
gap: var(--gap);
|
|
5210
|
-
|
|
5224
|
+
margin-bottom: -6px;
|
|
5225
|
+
padding: var(--gap) var(--reel-gutter) 6px;
|
|
5226
|
+
overflow-y: auto;
|
|
5211
5227
|
}
|
|
5212
5228
|
|
|
5213
5229
|
.bench-head > *,
|
package/src/tokens.css
CHANGED
|
@@ -145,6 +145,9 @@
|
|
|
145
145
|
--reel-column-min: 280px; /* the narrowest a column prints, whatever its width */
|
|
146
146
|
--reel-pane-min: 120px; /* the shortest a pane prints */
|
|
147
147
|
|
|
148
|
+
/* ---------- the bench: a page whose work is the window ---------- */
|
|
149
|
+
--bench-work-min: 152px; /* the least of its height the work keeps: a 120px pane, 16px gutters */
|
|
150
|
+
|
|
148
151
|
/* ---------- charts ---------- */
|
|
149
152
|
--chart-plot: 160px; /* a line chart's plot, between its top line and its axis */
|
|
150
153
|
|