@gjermundgaraba-designs/pixel-paper 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +11 -8
- package/dist/src/iconButton/iconButton.d.ts +6 -1
- package/dist/src/iconButton/iconButton.d.ts.map +1 -1
- package/dist/src/iconButton/iconButton.js +7 -2
- package/dist/src/panel/panel.d.ts +3 -0
- package/dist/src/panel/panel.d.ts.map +1 -1
- package/dist/src/panel/panel.js +2 -1
- package/dist/src/rail/index.d.ts +1 -1
- package/dist/src/rail/index.d.ts.map +1 -1
- package/dist/src/rail/index.js +1 -1
- package/dist/src/rail/rail.d.ts +78 -17
- package/dist/src/rail/rail.d.ts.map +1 -1
- package/dist/src/rail/rail.js +98 -41
- package/dist/src/reel/index.d.ts +1 -1
- package/dist/src/reel/index.d.ts.map +1 -1
- package/dist/src/reel/index.js +1 -1
- package/dist/src/reel/reel.d.ts +85 -7
- package/dist/src/reel/reel.d.ts.map +1 -1
- package/dist/src/reel/reel.js +232 -115
- package/dist/src/tips/tips.d.ts +30 -1
- package/dist/src/tips/tips.d.ts.map +1 -1
- package/dist/src/tips/tips.js +53 -31
- package/package.json +1 -1
- package/src/iconButton/iconButton.ts +19 -2
- package/src/panel/panel.ts +5 -0
- package/src/pixel-paper.css +167 -4
- package/src/rail/index.ts +2 -0
- package/src/rail/rail.ts +119 -41
- package/src/reel/index.ts +2 -0
- package/src/reel/reel.ts +221 -31
- package/src/tips/tips.ts +71 -35
- package/src/tokens.css +1 -0
package/DESIGN.md
CHANGED
|
@@ -208,6 +208,7 @@ spacing:
|
|
|
208
208
|
deck-max: "1160px"
|
|
209
209
|
rail: "272px"
|
|
210
210
|
rail-drawer: "320px"
|
|
211
|
+
rail-folded: "64px"
|
|
211
212
|
card-max: "680px"
|
|
212
213
|
card-narrow: "440px"
|
|
213
214
|
row-min: "34px"
|
|
@@ -921,7 +922,7 @@ The Deck is one centred column, `max-width: 1160px` (`--deck`), padded 24px top,
|
|
|
921
922
|
|
|
922
923
|
**Reel:** a row of columns of windows that fills whatever holds it and scrolls sideways when the columns are wider than it, and down where a column's panes need more than its height, `--reel-gutter` (16px) between columns, between a column's panes and at all four edges (with no column head, the gutter above the panes is the reel's own). A column's width is a share of the reel's (`width × (view − gutter) − gutter`, so columns whose shares add up to one fill it exactly), never under `--reel-column-min` (280px); a column is the reel's height less the gutters above and below it, and a pane's height its share of its column by weight, never under `--reel-pane-min` (120px), a column of more panes than fit growing taller. The shares a width steps through (a third, half, two thirds, the whole) are the component's, in its code, not tokens: they are the words it says as much as the sizes it prints.
|
|
923
924
|
|
|
924
|
-
**Rail:** a column of panels beside the deck (`--rail`, 272px, then the deck centred in what is left), fixed from the top bar's lower edge (hung from it by anchor positioning, like the stage) to the window's bottom,
|
|
925
|
+
**Rail:** a column of panels beside the deck (`--rail`, 272px, then the deck centred in what is left), fixed from the top bar's lower edge (hung from it by anchor positioning, like the stage) to the window's bottom, padded `24px 10px 24px 20px` so its panels' shadows print. **Its top stays put:** it is a column in which what comes before its last panel keeps its own height and the last panel takes the room left, at most its own height, its title bar, shelf and foot staying while its body scrolls (the padded body, or a flush body's list): a sidebar is one panel whose bar is its head, the field that picks what it lists on the shelf under the bar, its rows scrolling, its action in the foot. A short list leaves its panel at its own height. The rail scrolls as a whole only when what comes before its last panel is taller than the window, and its last panel then has no room of its own. **The reader can hide it:** the toggle in the first panel's bar folds the rail to that bar stood on end on the ground, `--rail-folded` (64px) wide, an ink tab with the toggle at its top and the title and count reading down (`writing-mode: vertical-rl`), the bar's actions, the rest of the panel, the other panels and the splitter gone; the deck's padding and a bench's left read the strip's width. Folding and unfolding move the width in three steps over `--motion-card`, as the drawer enters, and at once under reduced motion or while the splitter is dragged (a transition, so it never plays on load; a width or a fold the parent restores after hydration steps once, and an arrow on the splitter steps its 16px too). Hidden is a preference that lasts, not an overlay, and only above 900px: the drawer opens whole. The reader sizes it from its right edge, between 220px (the least its panels still fit: a tree's row keeps its glyph, a dot and a few words of its title) and 480px (the most, which leaves the deck at least 421px of a 901px window, the narrowest the rail stands in, more than a phone has); the width they give is set as `--railed-width` on `.railed`, so the page's padding and the rail's width move together, and a bench beside it follows; without one they read `--rail`. **The width is not inherited:** `--railed-width` is registered with `inherits: false` and handed by name to the rail, its splitter and a bench (`.railed > :is(.rail, .rail-resize, .bench)`), so a width that changes under a dragged splitter restyles those boxes and the shell, not every row inside them. A rule of the adopter's that reads `--rail` inside the rail reads the token, not the reader's width. At 900px and under it leaves the page: the deck starts with a small button (the `sidebar` glyph and the rail's name) that opens the same element as a drawer, `--rail-drawer` (320px) wide whatever width the reader gave the rail, since a width chosen beside a page is no measure of a drawer over a phone.
|
|
925
926
|
|
|
926
927
|
Frames with no surface of their own (Deck, Wall, Stage, Bench) are described here rather than among the components.
|
|
927
928
|
|
|
@@ -935,7 +936,7 @@ Breakpoints: 600px (phone; the page title steps to 18px, stats two across, the w
|
|
|
935
936
|
|
|
936
937
|
### Named Rules
|
|
937
938
|
|
|
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.
|
|
939
|
+
**The Panel Scroll Rule.** The page scrolls; a panel does not, except a board column above 900px, a card body inside a dialog, the body of the rail's last panel (under its bar, its shelf and its foot, which stay; the rail itself only when what comes before that panel is taller than the window), 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.
|
|
939
940
|
|
|
940
941
|
**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.
|
|
941
942
|
|
|
@@ -1018,7 +1019,7 @@ The printed button: a paper rectangle in a 2px ink frame that casts a 3px shadow
|
|
|
1018
1019
|
- **Default ring (`isDefault`):** the action Enter takes in a card; one ring at a time across the action row. A held default that does not hold focus (a confirm's cancel while its delete runs) prints as any held button, with no ring and no shadow; its 4px margin stays, so nothing moves.
|
|
1019
1020
|
- **Toggle:** a button that stays pressed (a tool in force, a filter) takes `aria-pressed` from `Button.pressedAttribute(isPressed, h)` in its `attributes`, the one source of it for every pressable in the system.
|
|
1020
1021
|
- **Key hint (`keyHint`):** the key that does the same, as its Foldkit key binding names it (`"N"`, `"U"`, `"Mod+K"`), printed after the words as `kbd.key-hint[aria-hidden="true"]`: 8px clear of them, the 10px pixel face with no case change or tracking, in the button's own colour at 0.65. It is for the eye; the button's name stays its words. A done button drops it.
|
|
1021
|
-
- **TextButton** → `button.textbtn`: the control register with no box and a dotted underline on hover ("sign out"). **IconButton** → `button.iconbtn[aria-label][data-tip]` (`.quiet`): a 24px square glyph button whose `label`, required, is both its accessible name and its tip; quiet is Muted Ink until hovered. A Secret or a PropsList row that copies carries a CopyButton (see Code surface).
|
|
1022
|
+
- **TextButton** → `button.textbtn`: the control register with no box and a dotted underline on hover ("sign out"). **IconButton** → `button.iconbtn[aria-label][data-tip]` (`.quiet`): a 24px square glyph button whose `label`, required, is both its accessible name and its tip; quiet is Muted Ink until hovered. Its `keyHint`, with no words to print beside, goes in `data-tip-key` (the key as the help prints it) and prints in its tip after the label. A Secret or a PropsList row that copies carries a CopyButton (see Code surface).
|
|
1022
1023
|
|
|
1023
1024
|
### Navigation
|
|
1024
1025
|
|
|
@@ -1054,13 +1055,13 @@ The printed button: a paper rectangle in a 2px ink frame that casts a 3px shadow
|
|
|
1054
1055
|
|
|
1055
1056
|
### Panels
|
|
1056
1057
|
|
|
1057
|
-
- **Panel** → `section.panel[aria-labelledby]` (`[aria-label]` with `name`) `> header.panel-tb > span.panel-lead + h2 + span.meta`, then `div.panel-body` (or the body directly when `isFlush`), then `div.panel-foot`. The section is named by its title, or by `name` where the title repeats among its siblings (panels titled by a kind, one per account), so each landmark keeps a name of its own. It is keyed by its `id`, so a panel among siblings that come and go keeps its own element, and a panel under another id is another element: one that replaces another in the same place is built anew (a live region inside it is inserted, not kept), so keep one panel under one id across states that should share it. Square, 2px ink border, Paper White, panel shadow. The title bar is inverted Departure Mono 13px uppercase 0.08em (`--tracking-title`), `padding: 6px 12px`; its meta is 11px at 75% opacity (`--fade-on-ink`). A control in a title bar (a panel's, a window's or a card's) rings in paper, 2px inside its own edge, because the ink ring would vanish on the ink bar. The body pads 16px with a 14px grid gap; the foot pads `10px 12px` over a 1px rule, with a `.push` slot that goes right. `actions` puts small Buttons and IconButtons in `span.panel-acts` (6px apart) at the title bar's right end, after the meta; the bar trims to `3px 3px 3px 12px` at 31px or more. `lead` puts a quiet IconButton in `span.panel-lead` before the title (a Sortable's grip), and the bar trims its left to 3px the same way; a quiet icon button there prints in paper, hovered too, and held at 60% (`--fade-held`). On the ink bar a button is a paper outline (a primary one fills paper), flat, nudged 1px when pressed, its ring 4px inside in its own colour; disabled, it prints at 60% (`--fade-held`).
|
|
1058
|
+
- **Panel** → `section.panel[aria-labelledby]` (`[aria-label]` with `name`) `> header.panel-tb > span.panel-lead + h2 + span.meta`, then `div.panel-shelf`, then `div.panel-body` (or the body directly when `isFlush`), then `div.panel-foot`. The section is named by its title, or by `name` where the title repeats among its siblings (panels titled by a kind, one per account), so each landmark keeps a name of its own. It is keyed by its `id`, so a panel among siblings that come and go keeps its own element, and a panel under another id is another element: one that replaces another in the same place is built anew (a live region inside it is inserted, not kept), so keep one panel under one id across states that should share it. Square, 2px ink border, Paper White, panel shadow. The title bar is inverted Departure Mono 13px uppercase 0.08em (`--tracking-title`), `padding: 6px 12px`; its meta is 11px at 75% opacity (`--fade-on-ink`). A control in a title bar (a panel's, a window's or a card's) rings in paper, 2px inside its own edge, because the ink ring would vanish on the ink bar. The body pads 16px with a 14px grid gap; the foot pads `10px 12px` over a 1px rule, with a `.push` slot that goes right. `shelf` is a strip on Head Tint between the bar and the body, `10px 12px 12px` over a 1px rule, for a field that picks what the body shows (an area over its tasks in a rail); a field's label there prints in On Head, since Muted Ink misses AA on the tint. `actions` puts small Buttons and IconButtons in `span.panel-acts` (6px apart) at the title bar's right end, after the meta; the bar trims to `3px 3px 3px 12px` at 31px or more. `lead` puts a quiet IconButton in `span.panel-lead` before the title (a Sortable's grip), and the bar trims its left to 3px the same way; a quiet icon button there prints in paper, hovered too, and held at 60% (`--fade-held`). On the ink bar a button is a paper outline (a primary one fills paper), flat, nudged 1px when pressed, its ring 4px inside in its own colour; disabled, it prints at 60% (`--fade-held`).
|
|
1058
1059
|
- **Deck** → `main.deck#main`: the column of panels.
|
|
1059
1060
|
- **Bench** → `main.bench#main > div.bench-head + div.bench-work`: see Layout. `head` and `body` are both the caller's; beside a Rail it is what `toDeckView` returns, with the open button first in its head.
|
|
1060
1061
|
- **EmptyState** → `div.empty > h3.empty-title + p`: `headingLevel` is required and picks the title's element, which looks the same at every level. Where the empty state is a page's or a section's main content it is a heading, `3` inside a Panel (whose title is an `h2`), `1` for a gate or a missing page; `"Strong"` prints `strong.empty-title` where it is not (a chart with nothing to chart, a picture of the state). Centred, `26px 16px`, a 12px uppercase 0.08em (`--tracking-title`) headline, a muted 46ch sentence, an optional action 6px below.
|
|
1061
1062
|
- **Wall** → `main.wall`, `Wall.markView` → `div.wall-mark` (a 30px ink-bordered glyph box beside the 22px wordmark). `Wall.cornerView` → `aside.wall-corner[aria-label]`, rendered just before the Wall: a paper slip in a 2px ink box on the 3px shadow, `6px 8px`, holding what a top bar would (see Layout).
|
|
1062
1063
|
- **Banner** → `div.banner > span.glyph (.error, .ok, .quiet) + span`: a fixed paper slip on the 3px shadow with a 26px glyph box in the Notice's tones and a sentence that says what happens to the reader's work. It holds a state the whole interface is in, for as long as it lasts, one at a time. It is not a live region (it arrives already holding its sentence, which would go unheard): the application says the state once, when it begins, with the `Announcer.Announce` Command. `"Error"` (the default; red, bang): a state that stops work (offline). `"Warn"` (amber): a state that is passing (reconnecting). `"Ok"` (ink, check): the state just ended (back online), shown briefly and then taken away. `"Quiet"` (head, info): news. With the connection word it is one pair: LinkState `"Reconnecting"` beside a warn Banner, `"Offline"` beside an error Banner with a retry, then `"Online"` beside an ok Banner for a moment; `"Connecting"` takes none.
|
|
1063
|
-
- **Rail** (Submodel) → `div.railed > main.deck#main + aside.rail[popover="auto"][aria-label] + div.rail-resize` (a `main.bench#main` in the deck's place for a page whose work is the window): the rail's panels (a tree, places, filters) beside the deck's, after it in the markup so the page's main content and its h1 come first in reading order; the stylesheet fixes the rail at the left under the top bar. One element serves both layouts, so nothing in it renders twice or loses its state: at rest it stands there (its `popover` attribute is inert until opened), and at 900px and under it is hidden and `span.rail-open > button.btn.small[aria-expanded]` at the top of the deck opens it as a drawer: a slice of the dithered ground, `min(var(--rail-drawer), 100vw - 40px)` (320px) wide from the left edge, whatever width the reader gave the rail, closed by a 2px ink rule and the 8px card shadow, entering from the left in three steps over a veil. Its head (`div.rail-head`: the name in the label register and a close IconButton) shows only in the drawer. Opening focuses its first control; Escape, a click on the veil, the close glyph or focus leaving closes it, and all but the last return focus to the button. Widening the window past 900px closes it. The parent reads whether the drawer is open with `Rail.isOpen`, to hold its own page keys while the drawer covers the page. **Its width is the reader's:** after the aside, `div.rail-resize[role="separator"][aria-orientation="vertical"]` ("Width of <label>", `aria-controls` the rail, its width as `aria-valuenow` between `aria-valuemin` 220 and `aria-valuemax` 480 and as "300 pixels" in `aria-valuetext`) is a 12px strip from the rail's right edge outward, over the page's margin and never over the rail's own scrollbar, fixed beside the rail rather than in it (the rail scrolls, and the drawer's first Tab stop is its first control), a `col-resize` cursor showing a 2px ink line down the edge while hovered or focused, hidden with the rail at 900px and under. A pointer drags it, the rail printing the new width as it moves, and Escape or the browser's cancel puts it back; the side arrows, unmodified, step it 16px, a modified arrow being the application's. Let go where it changes the width, or stepped, it reports `ResizedRail` with the width in whole pixels within the bounds, and the parent keeps it and passes it back as `maybeWidth`: the rail holds no width of its own, as the reel holds no layout. Until one is given, the splitter says 272px, a copy of `--rail` in the component's code: the server render needs the number before anything is measured, and the package is compiled from `src/` by `tsc` alone, which the specimen's token scanner (a dev dependency, fed through Vite's `?raw`) cannot reach without a build step of its own. Its test reads the stylesheet and holds that copy, and the 900px the drawer follows, to it. The parent keeps it per client, as it keeps focus and scroll, since a width suits a window, not a task. The splitter's handlers are the reel's (`src/drag`), and the rail's Subscriptions, which follow a dragged splitter and take Escape, are lifted behind a key prefix of the parent's. A file tree flush in a rail panel (or any panel) drops its own border.
|
|
1064
|
+
- **Rail** (Submodel) → `div.railed > main.deck#main + aside.rail[popover="auto"][aria-label] + div.rail-resize` (a `main.bench#main` in the deck's place for a page whose work is the window): the rail's panels (a tree, places, filters) beside the deck's, after it in the markup so the page's main content and its h1 come first in reading order; the stylesheet fixes the rail at the left under the top bar. One element serves both layouts, so nothing in it renders twice or loses its state: at rest it stands there (its `popover` attribute is inert until opened), and at 900px and under it is hidden and `span.rail-open > button.btn.small[aria-expanded]` at the top of the deck opens it as a drawer: a slice of the dithered ground, `min(var(--rail-drawer), 100vw - 40px)` (320px) wide from the left edge, whatever width the reader gave the rail, closed by a 2px ink rule and the 8px card shadow, entering from the left in three steps over a veil. Its head (`div.rail-head`: the name in the label register and a close IconButton) shows only in the drawer. Opening focuses its first control; Escape, a click on the veil, the close glyph or focus leaving closes it, and all but the last return focus to the button. Widening the window past 900px closes it. The parent reads whether the drawer is open with `Rail.isOpen`, to hold its own page keys while the drawer covers the page. **Its width is the reader's:** after the aside, `div.rail-resize[role="separator"][aria-orientation="vertical"]` ("Width of <label>", `aria-controls` the rail, its width as `aria-valuenow` between `aria-valuemin` 220 and `aria-valuemax` 480 and as "300 pixels" in `aria-valuetext`) is a 12px strip from the rail's right edge outward, over the page's margin and never over the rail's own scrollbar, fixed beside the rail rather than in it (a panel's body in the rail scrolls, and the drawer's first Tab stop is its first control), a `col-resize` cursor showing a 2px ink line down the edge while hovered or focused, hidden with the rail at 900px and under. A pointer drags it, the rail printing the new width as it moves, and Escape or the browser's cancel puts it back; the side arrows, unmodified, step it 16px, a modified arrow being the application's. Let go where it changes the width, or stepped, it reports `ResizedRail` with the width in whole pixels within the bounds, and the parent keeps it and passes it back as `maybeWidth`: the rail holds no width of its own, as the reel holds no layout. Until one is given, the splitter says 272px, a copy of `--rail` in the component's code: the server render needs the number before anything is measured, and the package is compiled from `src/` by `tsc` alone, which the specimen's token scanner (a dev dependency, fed through Vite's `?raw`) cannot reach without a build step of its own. Its test reads the stylesheet and holds that copy, and the 900px the drawer follows, to it. The parent keeps it per client, as it keeps focus and scroll, since a width suits a window, not a task. The splitter's handlers are the reel's (`src/drag`), and the rail's Subscriptions, which follow a dragged splitter and take Escape, are lifted behind a key prefix of the parent's. A file tree flush in a rail panel (or any panel) drops its own border. A panel's title in the rail stays on one line and ends in an ellipsis rather than wrapping the bar. **Its top is pinned and it folds** (see Layout): the rail hands `toAsideView` its toggle, `span.rail-toggle > button.iconbtn.quiet[aria-expanded][aria-controls]` with the `sidebar` glyph, "Hide <label>" or "Show <label>", as it hands `toDeckView` the open button, and the first panel prints it as its `lead`, so the folded tab finds it where the stylesheet looks. It is chrome, not a mark: never amber. Pressed, it reports `ToggledRail`, and the parent flips whether it keeps the rail hidden and passes it back as `isHidden`, kept per client as the width is; the rail holds neither. A key of the parent's does the same through `Rail.toggle`, and its key prints in the toggle's tip (`maybeToggleKeyHint`, in Button's `keyHint` shape). Hidden, `div.railed.folded` drops the reader's width for `--rail-folded`, the splitter leaves the markup, and the first panel (`.rail-head + .panel`) prints only its bar on end; everything else in the rail is `display: none`, so out of the tab order and the accessibility tree, and the aside, still named by its label, holds the toggle and the title. Folding or unfolding with focus in the rail or on its splitter puts focus on the toggle (one element in both states, so a pointer's press keeps it there too); focus elsewhere stays where it is. At 900px and under the drawer opens whole whether the rail is hidden or not, and prints no toggle (`.panel-lead` holding it is hidden, the bar keeping its own padding): a drawer opens and closes but does not fold, and its first Tab stop passes the toggle over. **Where the design degrades:** the fold is CSS over the first panel, so a rail whose first panel does not lead with the toggle folds to a bar with no way back but the parent's key, and a rail that does not print the toggle at all can be hidden by nothing but that key; put the toggle in the first panel's `lead`.
|
|
1064
1065
|
- **Stage** → `main.stage#main > div.stage-work > div.stage-canvas + div.stage-tools + div.stage-bar`: see Layout. `paused` (a Notice saying why: the link dropped, the page is read-only) veils the work when editing stops: `div.stage-paused[role="status"]` lays the dialog veil and its ink grain over everything and centres that Notice on the 3px button shadow, while the work beneath is `inert`. It lifts when `paused` is not given; the connection word says reconnecting meanwhile.
|
|
1065
1066
|
- **Window** → `section.panel.window (.flush) > header.panel-tb + div.window-body + div.panel-foot`: a Panel for a stage or a reel, as tall and wide as whatever places it (and moved by it, if anything moves it). Its title bar is the panel's, trimmed to hold tools: 30px tall (`3px 3px 3px 10px`, its left trimmed to 3px under a `lead`), centred, with an optional `lead` (`span.panel-lead`, a quiet IconButton: a Reel's grip), an optional kind glyph, the title (clipped with an ellipsis), a status chip (its border turns paper so it reads on ink), tools and a close IconButton, both in the bar's paper. Tools a child Submodel hands back come as one element, `span.window-tools`, which is no box of its own (`display: contents`), so its buttons sit in the bar as the others do. The body scrolls inside (`16px`, a 14px grid); flush, what fills it (a code surface, a file tree, a diff) drops its border and fills it. A foot is a panel foot; a notice there takes the whole line.
|
|
1066
1067
|
- **Loading** → `div.loading[role="status"]`: where content is on its way, centred like an EmptyState at `26px 16px`, a 12px uppercase 0.08em (`--tracking-title`) muted line ("loading the items") ending in the 6×11px working cursor. Its status element stays in the page and only its words change: with `isLoading` false it is `div.loading-idle[role="status"]`, empty and out of the flow (`position: absolute`, never `display: none`, which would drop the live region), so it takes no room and no gap at the top of a panel's or a card's body, and a screen reader hears the line when it arrives. The content or an EmptyState takes its place on screen; the line never prints beside either. It is not the page's live region (the Announcer's).
|
|
@@ -1091,7 +1092,7 @@ One keyboard for the page, Vim first, with the arrows beside the letters. The ke
|
|
|
1091
1092
|
|
|
1092
1093
|
### Tips and toolbars
|
|
1093
1094
|
|
|
1094
|
-
**Tips** (Submodel; `Tips.subscriptions(keyPrefix)` follow the pointer, focus and keys across the page, keyed behind the parent's prefix: `Tips.subscriptions("tip")` is keyed `tipPointerAndFocus` and `tipKeys`) → one `div.tip[popover="manual"][aria-hidden="true"]` for the page, rendered once beside the Announcer, which shows the words of any element carrying `data-tip
|
|
1095
|
+
**Tips** (Submodel; `Tips.subscriptions(keyPrefix)` follow the pointer, focus and keys across the page, keyed behind the parent's prefix: `Tips.subscriptions("tip")` is keyed `tipPointerAndFocus` and `tipKeys`) → one `div.tip[popover="manual"][aria-hidden="true"]` for the page, rendered once beside the Announcer, which shows the words of any element carrying `data-tip`, then the key in its `data-tip-key` where it has one, as a button's key hint prints (the 10px face, no case change, at 0.75): a label, not a surface, so flat Printer Ink with Paper White text and no print shadow, ringed by a 2px paper outline so it parts from an ink bar under it; the 11px pixel face, uppercase, 0.05em (`--tracking-state`), `3px 7px`, at most 36ch. It is placed by anchor positioning 6px above its control (the control is the tip's source, so its implicit anchor), hangs from the control's side near a window edge and flips below near the top; inside a vertical strip, or on a control set in vertical writing (a folded rail's toggle), it opens to the right. It opens on a resting pointer after 400ms (at once while another tip has just closed, so sweeping a toolbar reads each name), never on touch, and on keyboard focus (`:focus-visible`) a beat later, only if the control is still on the page and still the keyboard's, so focus a closing dialog or menu hands back does not open a tip mid top-layer change; it can be hovered, it closes on leave and blur (which also cancels a tip still waiting), and using the control (a press, any key) closes it, so a control that renames itself is read afresh next time. Escape closes a tip that focus opened, and nothing else, never the menu or card around it. **The Tip Rule:** a tip shows its element's accessible name and nothing else but the key that does the same, which a key hint shows beside a button's words for the eye alone, which is why it stays out of the accessibility tree; a control that needs a description says it in words beside it. IconButton, the glyph switch, Mark, a chip's dot, the board grip, a menu's glyph toggle and an abbreviated Tag carry one. A pressed toggle keeps its name and lets `aria-pressed` carry the change. The system uses no `title` attribute tooltips.
|
|
1095
1096
|
|
|
1096
1097
|
**Toolbar** (a Mount moves focus, reporting through `toParentMessage`) → `div.toolbar[role="toolbar"][aria-orientation]` (`.floating`): one strip of tools that is one stop for Tab: its own buttons and links, not the items of a menu one of them opens. Arrows on either axis move between tools and stop at the ends, as a cursor's, the palette's and a dialog's action bar's do (a menu and tabs wrap, as their platform patterns do; a vertical strip lies flat along the bottom of a stage on a phone), Home and End go to the ends, and the tool last used is where Tab returns (a roving `tabindex`). The strip is a 2px ink box whose ink shows through a 2px gap between tools, so the rules between them never change with a tool's state. Tools are 28px tall, glyph-only IconButtons 30px wide, labelled Buttons `0 10px` in the 11px pixel face, all paper, head on hover, inverted when `aria-pressed` (the tool in force), muted when disabled, nudged 1px while pressed. A tool's focus ring sits 4px inside it in the tool's own text colour, so it reads on a pressed tool and never lands on the strip's ink. Floating (over a canvas) it takes the 3px button shadow; vertical, its tips open to the right.
|
|
1097
1098
|
|
|
@@ -1119,7 +1120,7 @@ One keyboard for the page, Vim first, with the arrows beside the letters. The ke
|
|
|
1119
1120
|
|
|
1120
1121
|
### Reel
|
|
1121
1122
|
|
|
1122
|
-
**Reel** (Submodel, holding its own drag state rather than `@foldkit/ui`'s DragAndDrop, whose targets are positions in a list and whose pointer reads the items under it; for a workspace of windows side by side: terminals, an editor, a browser, a canvas, in columns the reader arranges) → `div.reel[role="group"][aria-label][data-reel]` holding the scroller `div.reel-view`, whose `div.reel-track` holds, in order, `div.reel-gap` (the gap before the first column), then per column `div.reel-column[data-reel-column]` (the column's id; its share in `--reel-width`) with a `div.reel-slot` per pane (`--reel-weight`, `--reel-anchor`) and between two slots `div.reel-split[role="separator"][aria-orientation="horizontal"]` ("Height of <pane>", `data-reel-split` the id of the pane above it), and after each column `div.reel-gap.reel-resize[role="separator"][aria-orientation="vertical"]` ("Width of column 2", its share as `aria-valuenow` and in words as `aria-valuetext`, `data-reel-resize` its column's id), then `div.reel-panes` with a `div.reel-pane[data-reel-pane][tabindex="-1"]` per pane, each the parent's Window with the pane's grip as its `lead
|
|
1123
|
+
**Reel** (Submodel, holding its own drag state rather than `@foldkit/ui`'s DragAndDrop, whose targets are positions in a list and whose pointer reads the items under it; for a workspace of windows side by side: terminals, an editor, a browser, a canvas, in columns the reader arranges) → `div.reel[role="group"][aria-label][data-reel]` holding the scroller `div.reel-view`, whose `div.reel-track` holds, in order, `div.reel-gap` (the gap before the first column), then per column `div.reel-column[data-reel-column]` (the column's id; its share in `--reel-width`) with a `div.reel-slot` per pane (`--reel-weight`, `--reel-anchor`) and between two slots `div.reel-split[role="separator"][aria-orientation="horizontal"]` ("Height of <pane>", `data-reel-split` the id of the pane above it), and after each column `div.reel-gap.reel-resize[role="separator"][aria-orientation="vertical"]` ("Width of column 2", its share as `aria-valuenow` and in words as `aria-valuetext`, `data-reel-resize` its column's id), then `div.reel-panes` with a `div.reel-pane[data-reel-pane][tabindex="-1"]` per pane, each the parent's Window with the pane's grip as its `lead` (under tabs, see below, the panes have no grip and the track a stage in place of its columns); after the scroller, the grips' keyboard help in a `p.sr-only` and, while a pointer carries a pane, `div.reel-lift` with its copy. The reel takes its height from whatever holds it. The layout is the parent's (`Reel.Layout`: columns, each an id, a width and its panes, each an id, a label and a weight), passed to the view and, as `{ layout }`, to `update`, so the reel never holds a copy that could go stale. Whenever the parent changes the layout (a request it applied, another client's, a pane it closed), it calls `Reel.reconcile` with the layout as it is now.
|
|
1123
1124
|
|
|
1124
1125
|
**A column has no head.** It is its panes and nothing else, so the only title bars in a reel are its windows'. That was chosen over a head above each column, which read as a second title bar over its panes and printed what the width splitter already says.
|
|
1125
1126
|
|
|
@@ -1135,6 +1136,8 @@ The reel binds no page keys: the application binds its own and calls `Reel.perfo
|
|
|
1135
1136
|
|
|
1136
1137
|
Focus is the reel's: one pane is focused (`.focused`, its window on the 8px card shadow), the one that last took focus or that a key moved to; `reconcile` reads its place again from each changed layout, so when it goes, focus finds the pane now nearest where it was, whoever moved it. A focus key puts the keyboard in the pane's control marked `data-reel-focus` (a terminal's input), else on the pane itself (ringed outside its window), and the browser scrolls the pane into view by the least distance either way, its gutter kept by `scroll-margin` (motion is stepped or instant, and a follow is instant); a pointer focusing a pane does not scroll the reel. When the focused pane leaves the layout with the keyboard in it, `reconcile` puts the keyboard in the pane now nearest where it was; focus the reader put elsewhere stays there. Each focus and move is said ("Diff, column 2 of 3.", "Shell moved to 1 of 2 in column 2 of 3.", "Column 1 takes two thirds of the width."). Every move and resize reports what it asks (`MovedPane`, `PulledOutPane`, `MovedColumn`, `ResizedColumn`, `ResizedPanes`), which `Reel.apply` applies to a layout, so the parent can apply it at once and keep or replace it when its source answers; a pane that joins a column takes that column's mean weight and an emptied column is dropped. An application that draws something of its own over a pane (a native view) measures the pane's bounds itself, which follows the reel's scroll, moves and resizes alike.
|
|
1137
1138
|
|
|
1139
|
+
**Tabs.** The same reel prints its panes one at a time when the parent passes `arrangement: "Tabs"` to the view and to `perform`, for a reader who works in one pane at a time or a window too narrow for columns: `div.reel.tabbed` holds a `div.nav.tabs.reel-tabs[role="tablist"]` (named by the reel's label, a gutter in from the reel's edges) over the scroller, whose track holds one `div.reel-slot.reel-stage`, the view less a gutter at every edge, where the columns were. There is a `button[role="tab"]` per pane in reading order (column by column, down each column), saying the pane's label in a `span.reel-tab-words`, which ends in an ellipsis when the list runs out of width, after what the parent's `toTabLeadView` gives (a kind glyph), `aria-controls` its window; the focused pane is the selected tab, so the arrangement adds no state, and a pane closed under its tab hands the tab to the pane focus finds. A press shows the pane and puts the keyboard in it; the side arrows (wrapping), Home and End select as they move and keep the keyboard on the tabs, only the selected tab in the Tab order, a modified arrow being the application's. `perform` steps the focus keys from tab to tab (left and up back, right and down on, past neither end) and says "Notes, tab 2 of 4."; it moves and sizes nothing, and no grip or splitter prints, since a tab has no column. The layout is untouched, so the columns come back as they were. **The panes stay in their layer:** every pane is pinned to the stage, the focused one drawn and the others `.behind` (`visibility: hidden`, `inert`), so changing the arrangement or the tab takes no pane out of the page, and a pane behind keeps its size: a terminal sized by its box is not resized to nothing as the tabs change, as it would be under `display: none`. A pane behind its tab is not on top at any point, so an application that draws over a pane (a native view) sees it hidden, as it sees a pane scrolled out of the reel.
|
|
1140
|
+
|
|
1138
1141
|
### Inputs / Fields
|
|
1139
1142
|
|
|
1140
1143
|
- **Field** (a View over `@foldkit/ui`'s Input) → `div.field (.boxed, .mono) > label + input + p.field-error + p.field-help`, the label naming the input and the help describing it; a failed field prints why in `p.field-error` (sans, Urgent Red) under the control, which is `aria-invalid` and described by it before its help, and the ErrorSummary above the fields says it again; a required field's control is `aria-required`; the input's `type` the platform's (`"date"` for the browser's date control) when given. A field whose place says what it is (a browser's address bar) hides its label (`label.sr-only`), which still names the input. **SelectField** (over `@foldkit/ui`'s Select) → `div.field > label + select + p.field-error + p.field-help`, its options in order and a group's under an `optgroup` heading, an option that is listed but not choosable `disabled`; **TextareaField** (over `@foldkit/ui`'s Textarea) → `div.field (.mono) > label + textarea + p.field-error + p.field-help`, opening at `rows` lines. Both name, describe and mark their control as a Field does. **Fieldset** → `fieldset.field > legend.field-label`, then the controls, `p.field-error` and `p.field-help`, its error and its help linked with `aria-describedby`; **FieldGrid** → `div.field-grid` (auto-fit, 160px minimum); **Fields** → `fieldset.stack.gap-m`: a form's fields as one column `--space-m` (14px) apart, a body's gap, on the layout primitives with no rule of its own. `isBusy` (a save in flight) sets `disabled` and `aria-busy` on it, so every control holds at once and nothing changes under the save; the submit Button stays outside it, `isBusy`, so it keeps focus. A disabled control prints its value in Muted Ink; a boxless one also drops its dotted baseline (the mark of a place to type), a boxed one or a select mutes its box and caret.
|
|
@@ -1228,7 +1231,7 @@ Installing: see README.md beside this file. The package is a Foldkit library. It
|
|
|
1228
1231
|
|
|
1229
1232
|
The peers in `package.json` are pinned to the Foldkit line pixel-paper is built and tested against. Foldkit is pre-1.0, so a caret range admits patches only; a new Foldkit minor is a new pixel-paper release.
|
|
1230
1233
|
|
|
1231
|
-
Without Foldkit: link `pixel-paper.css` and write the markup named in each component above. The stylesheet relies on these attributes: `aria-current` (`="page"` on a nav segment, a crumb, a menu link, a place's button and a linked row's link; `="true"` on `.row` and `.board-card` for the cursor, given `tabindex="0"` while the others take `-1`, on the open file and on a history's current entry), `aria-selected`, `aria-pressed`, `aria-checked`, `aria-expanded`, `aria-disabled` (on buttons, on a board card's `.title`, on menu items, on a select-all box), `aria-invalid`, `disabled` and `aria-busy` on the Fields `fieldset` while a save is in flight, `aria-hidden="true"` on a button's or menu item's `kbd.key-hint`, `data-label` on stacked-table cells, `data-drag-over` on a drop zone while a file hovers, `data-pixel-paper-dragging` on the root while a sortable's item or a reel's pane is pressed or carried, `--reel-width`, `--reel-weight` and `--reel-anchor` on a reel's columns, slots and panes, `--
|
|
1234
|
+
Without Foldkit: link `pixel-paper.css` and write the markup named in each component above. The stylesheet relies on these attributes: `aria-current` (`="page"` on a nav segment, a crumb, a menu link, a place's button and a linked row's link; `="true"` on `.row` and `.board-card` for the cursor, given `tabindex="0"` while the others take `-1`, on the open file and on a history's current entry), `aria-selected`, `aria-pressed`, `aria-checked`, `aria-expanded`, `aria-disabled` (on buttons, on a board card's `.title`, on menu items, on a select-all box), `aria-invalid`, `disabled` and `aria-busy` on the Fields `fieldset` while a save is in flight, `aria-hidden="true"` on a button's or menu item's `kbd.key-hint`, `data-label` on stacked-table cells, `data-drag-over` on a drop zone while a file hovers, `data-pixel-paper-dragging` on the root while a sortable's item or a reel's pane is pressed or carried, `--reel-width`, `--reel-weight` and `--reel-anchor` on a reel's columns, slots and panes, `--railed-width` on `.railed` for a width the reader gave the rail and `.folded` on it while the reader has hidden the rail, `data-reel-focus` on the control in a pane focus lands on, `data-tip` on glyph-only controls (the words the page's one tip shows), native `<dialog>` for overlays and native `[popover]` for the rail's drawer and tips. Behaviour the components own (board moves, a reel's moves, sizes and focus, a menu's placement and arrow keys, a context menu's placement and focus, tips, a toolbar's roving focus, the palette cursor, tab arrows, focus into dialogs, an error summary's focus, the flash, the remembered palette, the toast stack's hold and focus, a player's controls, the key help) is the adopter's to write.
|
|
1232
1235
|
|
|
1233
1236
|
Palette: with no `data-scheme` the page follows `prefers-color-scheme`, live, in CSS alone. `Scheme.SchemeSwitch` is a Submodel with no service to provide: choosing a scheme returns its `PinScheme` Command, which sets or clears `data-scheme` on `<html>` (`"light"` for paper, `"dark"` for plum) and remembers the choice in `localStorage` (storage that refuses still switches the page; the choice is just not kept); `SchemeSwitch.select` does the same from outside the switch (a palette entry). `SchemeSwitch.init()` returns the switch on `"System"`, as the server renders it, with a `ReadScheme` Command the client runs after hydration, which reads the scheme `schemeScript` pinned before first paint; map its Commands into the application's `init`. Its Subscription follows `prefers-color-scheme` (Foldkit's `Dom.streamFromMediaQuery`), so the switch knows the palette `"System"` prints in. Read the choice with `SchemeSwitch.scheme` and the palette the page prints in, `"Paper"` or `"Plum"` (`Scheme.Palette`), with `SchemeSwitch.palette`: the pinned one, or under `"System"` the system's, followed as it changes (`"Paper"` until the browser reports, as the server renders). A scheme chosen in another tab is seen on that page's next load, not live. Put `schemeScript` inline in the page's `<head>` so a remembered palette applies before first paint. A subtree with `color-scheme: dark` prints plum colours inside a paper page, the dither too, which is how the specimen shows both palettes side by side.
|
|
1234
1237
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Html, HtmlBuilder } from "foldkit/html";
|
|
2
2
|
import type { Attributes } from "../attributes/attributes.ts";
|
|
3
|
+
import type { KeyHintConfig } from "../button/button.ts";
|
|
3
4
|
import type { GlyphName } from "../glyph/glyphs.ts";
|
|
4
5
|
/** Configuration for rendering an icon button with `view`. */
|
|
5
6
|
export type ViewConfig<Message> = Readonly<{
|
|
@@ -11,9 +12,13 @@ export type ViewConfig<Message> = Readonly<{
|
|
|
11
12
|
isQuiet?: boolean;
|
|
12
13
|
/** Unavailable but focusable (`aria-disabled`), as in `@foldkit/ui`. */
|
|
13
14
|
isDisabled?: boolean;
|
|
15
|
+
/** The key that does the same, printed in the tip after the label (`data-tip-key`): the
|
|
16
|
+
* button has no words to print it beside. */
|
|
17
|
+
keyHint?: KeyHintConfig;
|
|
14
18
|
/** Further attributes for the `<button>`, never a class. */
|
|
15
19
|
attributes?: Attributes<Message>;
|
|
16
20
|
}>;
|
|
17
|
-
/** A bare glyph button, 24px square. Its label is its accessible name and its tip
|
|
21
|
+
/** A bare glyph button, 24px square. Its label is its accessible name and its tip, and its
|
|
22
|
+
* key, where it has one, prints in the tip after the label. */
|
|
18
23
|
export declare const view: <Message>(config: ViewConfig<Message>, h: HtmlBuilder<Message>) => Html;
|
|
19
24
|
//# sourceMappingURL=iconButton.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iconButton.d.ts","sourceRoot":"","sources":["../../../src/iconButton/iconButton.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"iconButton.d.ts","sourceRoot":"","sources":["../../../src/iconButton/iconButton.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAKpD,8DAA8D;AAC9D,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC;IACzC,KAAK,EAAE,SAAS,CAAC;IACjB,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uDAAuD;IACvD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;kDAC8C;IAC9C,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;CAClC,CAAC,CAAC;AAEH;gEACgE;AAChE,eAAO,MAAM,IAAI,GAAI,OAAO,UAAU,UAAU,CAAC,OAAO,CAAC,KAAK,WAAW,CAAC,OAAO,CAAC,KAAG,IAgCpF,CAAC"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
|
|
2
2
|
import { Button as UiButton } from "@foldkit/ui";
|
|
3
3
|
import * as Glyph from "../glyph/glyph.js";
|
|
4
|
-
|
|
4
|
+
import { keyLabel } from "../keyHint/keyLabel.js";
|
|
5
|
+
/** A bare glyph button, 24px square. Its label is its accessible name and its tip, and its
|
|
6
|
+
* key, where it has one, prints in the tip after the label. */
|
|
5
7
|
export const view = (config, h) => {
|
|
6
|
-
const { glyph, label, onClick, isQuiet = false, isDisabled = false, attributes = [] } = config;
|
|
8
|
+
const { glyph, label, onClick, isQuiet = false, isDisabled = false, keyHint, attributes = [], } = config;
|
|
7
9
|
return __foldkitBrandViewResult((UiButton.view({
|
|
8
10
|
...(onClick !== undefined && { onClick }),
|
|
9
11
|
isDisabled,
|
|
@@ -12,6 +14,9 @@ export const view = (config, h) => {
|
|
|
12
14
|
...groups.button,
|
|
13
15
|
h.AriaLabel(label),
|
|
14
16
|
h.DataAttribute("tip", label),
|
|
17
|
+
...(keyHint === undefined
|
|
18
|
+
? []
|
|
19
|
+
: [h.DataAttribute("tip-key", keyLabel(keyHint.keys, keyHint.platform))]),
|
|
15
20
|
h.Class(isQuiet ? "iconbtn quiet" : "iconbtn"),
|
|
16
21
|
], [Glyph.view({ name: glyph }, h)])), "@gjermundgaraba-designs/pixel-paper/src/iconButton/iconButton.js#toView"),
|
|
17
22
|
}, h)), "@gjermundgaraba-designs/pixel-paper/src/iconButton/iconButton.js#view");
|
|
@@ -21,6 +21,9 @@ export type ViewConfig = Readonly<{
|
|
|
21
21
|
/** Small Buttons and IconButtons at the title bar's right end, after the meta. On the ink
|
|
22
22
|
* bar they print in paper, flat, and ring in their own colour inside their edge. */
|
|
23
23
|
actions?: ReadonlyArray<Html | string>;
|
|
24
|
+
/** A strip on the head tint between the title bar and the body, for a field that picks what
|
|
25
|
+
* the body shows (an area over its tasks). Its labels print in on-head. */
|
|
26
|
+
shelf?: ReadonlyArray<Html | string>;
|
|
24
27
|
body: ReadonlyArray<Html | string>;
|
|
25
28
|
/** A ruled foot under the body: a note line, then actions pushed right. */
|
|
26
29
|
foot?: ReadonlyArray<Html | string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../../src/panel/panel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMtD,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC;;;;kCAI8B;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd;;oCAEgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;2DACuD;IACvD,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACpC,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;yFACqF;IACrF,OAAO,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACvC,IAAI,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACnC,2EAA2E;IAC3E,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACpC,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC,CAAC;AAEH,iDAAiD;AACjD,eAAO,MAAM,OAAO,OAAQ,MAAM,KAAG,MAAuB,CAAC;AAE7D;8FAC8F;AAC9F,eAAO,MAAM,IAAI,GAAI,OAAO,UAAU,UAAU,KAAK,WAAW,CAAC,OAAO,CAAC,KAAG,
|
|
1
|
+
{"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../../src/panel/panel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMtD,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC;;;;kCAI8B;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd;;oCAEgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;2DACuD;IACvD,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACpC,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;yFACqF;IACrF,OAAO,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACvC;gFAC4E;IAC5E,KAAK,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACrC,IAAI,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACnC,2EAA2E;IAC3E,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;IACpC,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC,CAAC;AAEH,iDAAiD;AACjD,eAAO,MAAM,OAAO,OAAQ,MAAM,KAAG,MAAuB,CAAC;AAE7D;8FAC8F;AAC9F,eAAO,MAAM,IAAI,GAAI,OAAO,UAAU,UAAU,KAAK,WAAW,CAAC,OAAO,CAAC,KAAG,IAoC3E,CAAC"}
|
package/dist/src/panel/panel.js
CHANGED
|
@@ -5,7 +5,7 @@ export const titleId = (id) => __foldkitBrandViewResult((`${id}-title`), "@gjerm
|
|
|
5
5
|
/** The unit of the system: paper in a 2px ink box on a 5px print shadow, under a title bar. A
|
|
6
6
|
* region landmark (`<section>`) named by its `h2` title, or by `name`, keyed by its `id`. */
|
|
7
7
|
export const view = (config, h) => {
|
|
8
|
-
const { id, title, name, lead = [], meta, actions = [], body, foot = [], isFlush = false, } = config;
|
|
8
|
+
const { id, title, name, lead = [], meta, actions = [], shelf = [], body, foot = [], isFlush = false, } = config;
|
|
9
9
|
return __foldkitBrandViewResult((h.keyed("section")(id, [
|
|
10
10
|
h.Id(id),
|
|
11
11
|
name === undefined ? h.AriaLabelledBy(titleId(id)) : h.AriaLabel(name),
|
|
@@ -17,6 +17,7 @@ export const view = (config, h) => {
|
|
|
17
17
|
...(meta === undefined ? [] : [h.span([h.Class("meta")], [meta])]),
|
|
18
18
|
...slotView("span", "panel-acts", actions, h),
|
|
19
19
|
]),
|
|
20
|
+
...slotView("div", "panel-shelf", shelf, h),
|
|
20
21
|
...(isFlush ? body : [h.div([h.Class("panel-body")], body)]),
|
|
21
22
|
...slotView("div", "panel-foot", foot, h),
|
|
22
23
|
])), "@gjermundgaraba-designs/pixel-paper/src/panel/panel.js#view");
|
package/dist/src/rail/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { FollowRailDrawer, HideRailDrawer, Message, Model, OutMessage, ShowRailDrawer, close, id, init, isOpen, subscriptions, update, view, } from "./rail.ts";
|
|
1
|
+
export { FocusRailToggle, FollowRailDrawer, HideRailDrawer, Message, Model, OutMessage, ShowRailDrawer, close, id, init, isOpen, subscriptions, toggle, update, view, } from "./rail.ts";
|
|
2
2
|
export type { InitConfig, ViewInputs } from "./rail.ts";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/rail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,KAAK,EACL,UAAU,EACV,cAAc,EACd,KAAK,EACL,EAAE,EACF,IAAI,EACJ,MAAM,EACN,aAAa,EACb,MAAM,EACN,IAAI,GACL,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/rail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,KAAK,EACL,UAAU,EACV,cAAc,EACd,KAAK,EACL,EAAE,EACF,IAAI,EACJ,MAAM,EACN,aAAa,EACb,MAAM,EACN,MAAM,EACN,IAAI,GACL,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/src/rail/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { FollowRailDrawer, HideRailDrawer, Message, Model, OutMessage, ShowRailDrawer, close, id, init, isOpen, subscriptions, update, view, } from "./rail.js";
|
|
1
|
+
export { FocusRailToggle, FollowRailDrawer, HideRailDrawer, Message, Model, OutMessage, ShowRailDrawer, close, id, init, isOpen, subscriptions, toggle, update, view, } from "./rail.js";
|
package/dist/src/rail/rail.d.ts
CHANGED
|
@@ -4,9 +4,10 @@ import type { Html } from "foldkit/html";
|
|
|
4
4
|
import * as Mount from "foldkit/mount";
|
|
5
5
|
import * as Subscription from "foldkit/subscription";
|
|
6
6
|
import type * as Update from "foldkit/update";
|
|
7
|
+
import * as Button from "../button/button.ts";
|
|
7
8
|
/** Schema for a rail: whether it is open as a drawer (at 900px and under; wider, it is always
|
|
8
|
-
* in the page and this stays false), and its splitter while a pointer drags it. Its width
|
|
9
|
-
* the parent's. */
|
|
9
|
+
* in the page and this stays false), and its splitter while a pointer drags it. Its width,
|
|
10
|
+
* and whether the reader hid it, are the parent's. */
|
|
10
11
|
export declare const Model: Schema.Struct<{
|
|
11
12
|
readonly id: Schema.String;
|
|
12
13
|
readonly isOpen: Schema.Boolean;
|
|
@@ -23,6 +24,7 @@ export type Model = typeof Model.Type;
|
|
|
23
24
|
* the window growing past 900px while it is open, where the rail is back in the page. */
|
|
24
25
|
export declare const Message: import("foldkit/message").MessageUnion<{
|
|
25
26
|
readonly ClickedOpen: {};
|
|
27
|
+
readonly ClickedToggle: {};
|
|
26
28
|
readonly PressedSplitter: {
|
|
27
29
|
pointerId: Schema.Number;
|
|
28
30
|
clientX: Schema.Number;
|
|
@@ -45,15 +47,19 @@ export declare const Message: import("foldkit/message").MessageUnion<{
|
|
|
45
47
|
readonly WidenedPastDrawer: {};
|
|
46
48
|
readonly CompletedShowRailDrawer: {};
|
|
47
49
|
readonly CompletedHideRailDrawer: {};
|
|
50
|
+
readonly CompletedFocusRailToggle: {};
|
|
48
51
|
}>;
|
|
49
52
|
export type Message = typeof Message.Type;
|
|
50
53
|
/** What a rail asks of its parent. `ResizedRail`: its splitter was let go, or stepped by a
|
|
51
54
|
* key, at `width` pixels, within the rail's bounds; the parent keeps it (per client) and
|
|
52
|
-
* passes it back as the view's `maybeWidth`.
|
|
55
|
+
* passes it back as the view's `maybeWidth`. `ToggledRail`: its toggle was pressed; the
|
|
56
|
+
* parent flips whether it keeps the rail hidden (per client) and passes it back as the view's
|
|
57
|
+
* `isHidden`. */
|
|
53
58
|
export declare const OutMessage: import("foldkit/message").MessageUnion<{
|
|
54
59
|
readonly ResizedRail: {
|
|
55
60
|
width: Schema.Number;
|
|
56
61
|
};
|
|
62
|
+
readonly ToggledRail: {};
|
|
57
63
|
}>;
|
|
58
64
|
export type OutMessage = typeof OutMessage.Type;
|
|
59
65
|
/** Configuration for creating a rail with `init`. The `id` is the rail's, unique in the
|
|
@@ -80,7 +86,8 @@ export declare const id: (model: Model) => string;
|
|
|
80
86
|
/** Whether the rail is open as a drawer: a parent pauses its own page keys while it is. */
|
|
81
87
|
export declare const isOpen: (model: Model) => boolean;
|
|
82
88
|
/** The drawer's first Tab stop past its head: a control the keyboard reaches, so a tree's
|
|
83
|
-
* items other than its one stop (`tabindex="-1"`) are passed over
|
|
89
|
+
* items other than its one stop (`tabindex="-1"`) are passed over, and so is the toggle,
|
|
90
|
+
* which the drawer does not print. */
|
|
84
91
|
export declare const firstTabStop: (rail: Element) => Option.Option<HTMLElement>;
|
|
85
92
|
/** Opens the rail as a drawer over the page and puts focus on its first control past its
|
|
86
93
|
* head. */
|
|
@@ -97,11 +104,25 @@ export declare const HideRailDrawer: Command.CommandDefinitionWithArgs<"HideRail
|
|
|
97
104
|
}, Effect.Effect<{
|
|
98
105
|
readonly _tag: "CompletedHideRailDrawer";
|
|
99
106
|
}, never, never>>;
|
|
107
|
+
/** Puts focus on the rail's toggle once the rail has folded or unfolded, if focus was in the
|
|
108
|
+
* rail or on its splitter: folding takes away every control in it but the toggle, which
|
|
109
|
+
* brings it back, and the splitter with them. Focus anywhere else stays where it is. */
|
|
110
|
+
export declare const FocusRailToggle: Command.CommandDefinitionWithArgs<"FocusRailToggle", {
|
|
111
|
+
railId: Schema.String;
|
|
112
|
+
toggleId: Schema.String;
|
|
113
|
+
}, Effect.Effect<{
|
|
114
|
+
readonly _tag: "CompletedFocusRailToggle";
|
|
115
|
+
}, never, never>>;
|
|
100
116
|
type UpdateReturn = Update.Return<Model, Message>;
|
|
101
117
|
/** Closes the rail's drawer, focus back on its button. */
|
|
102
118
|
export declare const close: (model: Model) => UpdateReturn;
|
|
119
|
+
/** Folds or unfolds the rail from a key of the parent's: the parent flips whether it keeps the
|
|
120
|
+
* rail hidden, as it does for `ToggledRail`, and folds this in, which moves focus in the rail
|
|
121
|
+
* onto the toggle. */
|
|
122
|
+
export declare const toggle: (model: Model) => UpdateReturn;
|
|
103
123
|
/** Processes a rail Message and returns the next Model, Commands and OutMessage: a splitter let
|
|
104
|
-
* go where it changes the width, or stepped by a key, asks for the width
|
|
124
|
+
* go where it changes the width, or stepped by a key, asks for the width, and the toggle asks
|
|
125
|
+
* to fold or unfold the rail. */
|
|
105
126
|
export declare const update: (model: Model, message: Message) => Readonly<{
|
|
106
127
|
model: {
|
|
107
128
|
readonly id: string;
|
|
@@ -123,8 +144,12 @@ export declare const update: (model: Model, message: Message) => Readonly<{
|
|
|
123
144
|
readonly _tag: "ClickedClose";
|
|
124
145
|
} | {
|
|
125
146
|
readonly _tag: "ClickedOpen";
|
|
147
|
+
} | {
|
|
148
|
+
readonly _tag: "ClickedToggle";
|
|
126
149
|
} | {
|
|
127
150
|
readonly _tag: "ClosedDrawer";
|
|
151
|
+
} | {
|
|
152
|
+
readonly _tag: "CompletedFocusRailToggle";
|
|
128
153
|
} | {
|
|
129
154
|
readonly _tag: "CompletedHideRailDrawer";
|
|
130
155
|
} | {
|
|
@@ -149,6 +174,8 @@ export declare const update: (model: Model, message: Message) => Readonly<{
|
|
|
149
174
|
outMessage?: {
|
|
150
175
|
readonly _tag: "ResizedRail";
|
|
151
176
|
readonly width: number;
|
|
177
|
+
} | {
|
|
178
|
+
readonly _tag: "ToggledRail";
|
|
152
179
|
};
|
|
153
180
|
}>;
|
|
154
181
|
type DrawerMessage = typeof Message.ClosedDrawer.Type | typeof Message.BlurredDrawer.Type | typeof Message.WidenedPastDrawer.Type;
|
|
@@ -197,8 +224,12 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
|
|
|
197
224
|
readonly _tag: "ClickedClose";
|
|
198
225
|
} | {
|
|
199
226
|
readonly _tag: "ClickedOpen";
|
|
227
|
+
} | {
|
|
228
|
+
readonly _tag: "ClickedToggle";
|
|
200
229
|
} | {
|
|
201
230
|
readonly _tag: "ClosedDrawer";
|
|
231
|
+
} | {
|
|
232
|
+
readonly _tag: "CompletedFocusRailToggle";
|
|
202
233
|
} | {
|
|
203
234
|
readonly _tag: "CompletedHideRailDrawer";
|
|
204
235
|
} | {
|
|
@@ -243,8 +274,12 @@ export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) =
|
|
|
243
274
|
readonly _tag: "ClickedClose";
|
|
244
275
|
} | {
|
|
245
276
|
readonly _tag: "ClickedOpen";
|
|
277
|
+
} | {
|
|
278
|
+
readonly _tag: "ClickedToggle";
|
|
246
279
|
} | {
|
|
247
280
|
readonly _tag: "ClosedDrawer";
|
|
281
|
+
} | {
|
|
282
|
+
readonly _tag: "CompletedFocusRailToggle";
|
|
248
283
|
} | {
|
|
249
284
|
readonly _tag: "CompletedHideRailDrawer";
|
|
250
285
|
} | {
|
|
@@ -280,20 +315,28 @@ export type ViewInputs = Readonly<{
|
|
|
280
315
|
* (for this client: another reader's window is not this one's); none for the stylesheet's.
|
|
281
316
|
* A width out of the rail's bounds prints at the nearer bound. */
|
|
282
317
|
maybeWidth: Option.Option<number>;
|
|
283
|
-
/**
|
|
284
|
-
*
|
|
285
|
-
|
|
286
|
-
|
|
318
|
+
/** Whether the reader folded the rail to its first panel's title bar, as the parent keeps it
|
|
319
|
+
* from `ToggledRail` (for this client, as it keeps the width). The drawer ignores it. */
|
|
320
|
+
isHidden: boolean;
|
|
321
|
+
/** The parent's key for the toggle, which its tip prints after its label; the parent binds
|
|
322
|
+
* it to `toggle`. */
|
|
323
|
+
maybeToggleKeyHint: Option.Option<Button.KeyHintConfig>;
|
|
324
|
+
/** The rail's panels: a tree, places, filters, given the toggle that folds the rail to put in
|
|
325
|
+
* its first panel's `lead`. A function because a Submodel's viewInputs may hold functions
|
|
326
|
+
* only at the top level, and Foldkit runs this one in the parent's boundary, so the
|
|
327
|
+
* handlers in what it returns dispatch the parent's Messages. */
|
|
328
|
+
toAsideView: (toggle: Html) => ReadonlyArray<Html>;
|
|
287
329
|
/** The page beside the rail, `main.deck#main` or `main.bench#main`, given the button that
|
|
288
330
|
* opens the drawer to print first in it. A function because it receives that button, and
|
|
289
331
|
* runs in the parent's boundary like `toAsideView`. */
|
|
290
332
|
toDeckView: (openButton: Html) => Html;
|
|
291
333
|
}>;
|
|
292
334
|
/**
|
|
293
|
-
* A column of panels beside the deck, fixed under the top bar
|
|
294
|
-
* `
|
|
295
|
-
*
|
|
296
|
-
*
|
|
335
|
+
* A column of panels beside the deck, fixed under the top bar: `div.railed >` the deck, then
|
|
336
|
+
* `aside.rail[popover="auto"][aria-label]`, then its splitter, `div.rail-resize[role="separator"]`,
|
|
337
|
+
* on its right edge. What comes before its last panel keeps its height, and the last panel
|
|
338
|
+
* shrinks to the room left, its bar and foot staying while its body scrolls. One element
|
|
339
|
+
* serves both layouts, so nothing in it renders twice or loses its state. At 900px and under it leaves the page, and
|
|
297
340
|
* `span.rail-open > button.btn.small` at the top of the deck opens the same element as a drawer
|
|
298
341
|
* over a veil, its head (the name and a close glyph) showing. Opening focuses its first
|
|
299
342
|
* control; Escape, a press on the veil, the close glyph, focus leaving or the window growing
|
|
@@ -305,6 +348,13 @@ export type ViewInputs = Readonly<{
|
|
|
305
348
|
* and the rail's width follow it (without one, `--rail`). The drawer keeps its own width. Lift
|
|
306
349
|
* `subscriptions(keyPrefix)` into the application's, or a dragged splitter follows nothing.
|
|
307
350
|
*
|
|
351
|
+
* Its toggle, `span.rail-toggle > button.iconbtn.quiet[aria-expanded]` ("Hide <label>"), comes
|
|
352
|
+
* to `toAsideView` to print as the first panel's `lead`. Pressed, it reports `ToggledRail` for
|
|
353
|
+
* the parent to keep and pass back as `isHidden`: `div.railed.folded` then stands the first
|
|
354
|
+
* panel's title bar on end on the ground (the toggle at its top, "Show <label>"), the rest of
|
|
355
|
+
* the rail and its splitter gone, and the deck takes the width. Focus in the rail lands on the
|
|
356
|
+
* toggle. The drawer, at 900px and under, prints neither the toggle nor the fold.
|
|
357
|
+
*
|
|
308
358
|
* Its state is its own, not `@foldkit/ui`'s Popover: that panel is placed by Floating UI and
|
|
309
359
|
* rendered only while open, and this one is always in the page, placed by the stylesheet, and
|
|
310
360
|
* opened as a native popover so the browser keeps it in the top layer.
|
|
@@ -328,8 +378,12 @@ export declare const view: import("foldkit/submodel").View<{
|
|
|
328
378
|
readonly _tag: "ClickedClose";
|
|
329
379
|
} | {
|
|
330
380
|
readonly _tag: "ClickedOpen";
|
|
381
|
+
} | {
|
|
382
|
+
readonly _tag: "ClickedToggle";
|
|
331
383
|
} | {
|
|
332
384
|
readonly _tag: "ClosedDrawer";
|
|
385
|
+
} | {
|
|
386
|
+
readonly _tag: "CompletedFocusRailToggle";
|
|
333
387
|
} | {
|
|
334
388
|
readonly _tag: "CompletedHideRailDrawer";
|
|
335
389
|
} | {
|
|
@@ -358,10 +412,17 @@ export declare const view: import("foldkit/submodel").View<{
|
|
|
358
412
|
* (for this client: another reader's window is not this one's); none for the stylesheet's.
|
|
359
413
|
* A width out of the rail's bounds prints at the nearer bound. */
|
|
360
414
|
maybeWidth: Option.Option<number>;
|
|
361
|
-
/**
|
|
362
|
-
*
|
|
363
|
-
|
|
364
|
-
|
|
415
|
+
/** Whether the reader folded the rail to its first panel's title bar, as the parent keeps it
|
|
416
|
+
* from `ToggledRail` (for this client, as it keeps the width). The drawer ignores it. */
|
|
417
|
+
isHidden: boolean;
|
|
418
|
+
/** The parent's key for the toggle, which its tip prints after its label; the parent binds
|
|
419
|
+
* it to `toggle`. */
|
|
420
|
+
maybeToggleKeyHint: Option.Option<Button.KeyHintConfig>;
|
|
421
|
+
/** The rail's panels: a tree, places, filters, given the toggle that folds the rail to put in
|
|
422
|
+
* its first panel's `lead`. A function because a Submodel's viewInputs may hold functions
|
|
423
|
+
* only at the top level, and Foldkit runs this one in the parent's boundary, so the
|
|
424
|
+
* handlers in what it returns dispatch the parent's Messages. */
|
|
425
|
+
toAsideView: (toggle: Html) => ReadonlyArray<Html>;
|
|
365
426
|
/** The page beside the rail, `main.deck#main` or `main.bench#main`, given the button that
|
|
366
427
|
* opens the drawer to print first in it. A function because it receives that button, and
|
|
367
428
|
* runs in the parent's boundary like `toAsideView`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rail.d.ts","sourceRoot":"","sources":["../../../src/rail/rail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAU,MAAM,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AAC9E,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAE3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,KAAK,KAAK,MAAM,eAAe,CAAC;AAIvC,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,KAAK,MAAM,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"rail.d.ts","sourceRoot":"","sources":["../../../src/rail/rail.ts"],"names":[],"mappings":"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"}
|