staffa 0.13.0 → 0.15.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/README.md +19 -16
- package/dist/components/dialog.js +1 -1
- package/dist/components/main.d.ts +37 -48
- package/dist/components/main.js +25 -61
- package/dist/components/menu.d.ts +8 -0
- package/dist/components/menu.js +40 -6
- package/dist/components/panels.d.ts +114 -82
- package/dist/components/panels.js +198 -230
- package/dist/components/select.js +4 -2
- package/dist/components/tabs.js +5 -4
- package/dist/components/tooltip.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/staffa.esm.js +1 -1
- package/dist/theme.d.ts +13 -65
- package/dist/theme.js +21 -8
- package/package.json +1 -1
- package/skill/FloatingMenuOptions.md +10 -0
- package/skill/MainOptions.md +35 -49
- package/skill/Panel.md +31 -32
- package/skill/PanelStack.md +4 -4
- package/skill/SKILL.md +29 -16
- package/skill/main.md +2 -1
- package/src/components/dialog.ts +1 -1
- package/src/components/main.ts +62 -108
- package/src/components/menu.ts +50 -7
- package/src/components/panels.ts +269 -290
- package/src/components/select.ts +4 -2
- package/src/components/tabs.ts +3 -2
- package/src/components/tooltip.ts +2 -1
- package/src/index.ts +1 -1
- package/src/theme.ts +24 -9
package/skill/MainOptions.md
CHANGED
|
@@ -105,16 +105,15 @@ aren't safe integers, such as snowflakes, want a plain `[id]`.
|
|
|
105
105
|
Navigating is just links: the shell handles the clicks itself, so do *not*
|
|
106
106
|
also call Aberdeen's `interceptLinks()`. A link opens its target on top of
|
|
107
107
|
the panel it sits in, closing everything after that panel first. The
|
|
108
|
-
`data-panel` attribute
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
with `aberdeen/route`'s own `go()` works too — a panel with
|
|
108
|
+
`data-panel` attribute keeps less of that context instead: `replace`
|
|
109
|
+
drops the link's own panel too, putting the target in its place, and
|
|
110
|
+
`open` drops it all, giving the target its own stack, the way a nav item
|
|
111
|
+
does. A plain link to something already open goes back to it rather than
|
|
112
|
+
opening it twice, closing whatever was stacked on top — pinned panels
|
|
113
|
+
excepted (see `Panel.pinned`), and panels holding unsaved work,
|
|
114
|
+
which park instead; a `replace` or `open` applies its usual shape, the
|
|
115
|
+
open panel moving into it alive. From code, use `pushPanel` and
|
|
116
|
+
friends: navigating with `aberdeen/route`'s own `go()` works too — a panel with
|
|
118
117
|
`Panel.unsaved` work still survives it — but builds the whole stack
|
|
119
118
|
from the path. A navigation guard the app registered with
|
|
120
119
|
`route.setGuard` (an auth redirect, say) keeps working: the shell
|
|
@@ -124,11 +123,11 @@ registers none of its own.
|
|
|
124
123
|
is called (`Panel.title` — unset, its first line of text stands in)
|
|
125
124
|
and what it can do (`Panel.actions`); everything else in a column is
|
|
126
125
|
the panel's own content, boxes included. The shell writes the stack of
|
|
127
|
-
open panels as breadcrumbs in the top bar — click one to go back to it
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
the
|
|
131
|
-
|
|
126
|
+
open panels as breadcrumbs in the top bar — click one to go back to it —
|
|
127
|
+
and places each panel's actions where the room is: on its own column while
|
|
128
|
+
several fit, in the bar once the shell is narrow and the current panel *is*
|
|
129
|
+
the screen. Nothing in an app measures the viewport to lay its screens out
|
|
130
|
+
twice.
|
|
132
131
|
|
|
133
132
|
Only one routed shell can be mounted at a time (a second one throws) —
|
|
134
133
|
the URL is global, so two of them would fight over it. Nothing else is:
|
|
@@ -207,9 +206,10 @@ answer without drawing anything. From code,
|
|
|
207
206
|
How many panels are *shown* at a time. `"auto"` (the default) shows as
|
|
208
207
|
many columns, side by side, as comfortably fit, ending at the current
|
|
209
208
|
panel; `"single"` shows only the current panel, however wide the screen
|
|
210
|
-
—
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
— one screen at a time at every size, each still at its asked width,
|
|
210
|
+
centred (the nav sidebar still sits beside it). Only the display
|
|
211
|
+
differs: the stack, the breadcrumbs, the URL, Escape and the back
|
|
212
|
+
button behave identically in both. Routed mode only.
|
|
213
213
|
|
|
214
214
|
Live: pass a proxied options object (or make this field a getter) and a
|
|
215
215
|
change is adopted in place — one layout pass, every panel keeping its
|
|
@@ -220,12 +220,13 @@ state.
|
|
|
220
220
|
### mainOptions.linkNavigation · member
|
|
221
221
|
|
|
222
222
|
What a link *without* a `data-panel` attribute does — the per-link
|
|
223
|
-
attribute always wins.
|
|
224
|
-
|
|
225
|
-
`"
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
223
|
+
attribute always wins. The three keep less and less of the link's own
|
|
224
|
+
context: `"push"` (the default) builds on the panel the link sits in,
|
|
225
|
+
`"replace"` swaps that panel out, and `"open"` ignores it and gives the
|
|
226
|
+
target its own stack, the way a nav item does. So with `"open"` every
|
|
227
|
+
click replaces the content as a whole — which, with flat routes, is the
|
|
228
|
+
conventional sidebar-and-content app: one pane, swapped on every click,
|
|
229
|
+
the crumb line simply naming it. Routed mode only.
|
|
229
230
|
|
|
230
231
|
Live, like `MainOptions.columns`: change it and the next click
|
|
231
232
|
uses the new default.
|
|
@@ -240,34 +241,23 @@ Footer content, pinned below the scroll area.
|
|
|
240
241
|
|
|
241
242
|
### mainOptions.maxWidth · member
|
|
242
243
|
|
|
243
|
-
Max width for the
|
|
244
|
+
Max width for the shell's *content*, e.g. `"80rem"`. The header and footer
|
|
244
245
|
backgrounds still span the full shell width, but their contents — and the
|
|
245
246
|
sidebar + separator + content trio (or just the content when there's no
|
|
246
247
|
sidebar) — cap to this width and centre horizontally. When unset, everything
|
|
247
248
|
fills the available width. Either way the content shares the panel surface —
|
|
248
249
|
it is not boxed.
|
|
249
250
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
**Type:** `string`
|
|
255
|
-
|
|
256
|
-
### mainOptions.fullWidth · member
|
|
257
|
-
|
|
258
|
-
How wide a `"full"` panel gets, in pixels — and with it the whole content
|
|
259
|
-
area, since a `"full"` fills it exactly. A `"half"` gets half of this, and
|
|
260
|
-
a `"screen"` ignores it and takes the window. Defaults to 1080; the window
|
|
261
|
-
caps it when there is less room than that. Routed mode only.
|
|
262
|
-
|
|
263
|
-
This plus `MainOptions.navWidth` is the app's standard page — see
|
|
264
|
-
there.
|
|
251
|
+
In routed mode this is what the columns divide up (see
|
|
252
|
+
`Panel.maxWidth`), which is the reason to set it on a very wide
|
|
253
|
+
screen: left uncapped, a stack of small panels will happily march right
|
|
254
|
+
across a 4K display.
|
|
265
255
|
|
|
266
256
|
Live, like `MainOptions.columns`: pass a proxied options object (or
|
|
267
|
-
make this field a getter) and a change is adopted in one layout pass,
|
|
268
|
-
|
|
257
|
+
make this field a getter) and a change is adopted in one layout pass, every
|
|
258
|
+
open panel keeping its state.
|
|
269
259
|
|
|
270
|
-
**Type:** `
|
|
260
|
+
**Type:** `string`
|
|
271
261
|
|
|
272
262
|
### mainOptions.contentAttrs · member
|
|
273
263
|
|
|
@@ -310,13 +300,9 @@ chrome goes assumes they are one.
|
|
|
310
300
|
### mainOptions.navWidth · member
|
|
311
301
|
|
|
312
302
|
How wide the nav sidebar column is, in pixels — its hairline included.
|
|
313
|
-
Defaults to 200.
|
|
314
|
-
|
|
315
|
-
Together with `MainOptions.fullWidth` this is the app's *standard
|
|
316
|
-
page*: the width the top bar and footer keep to, and the width the
|
|
317
|
-
columns settle back to. The defaults come to the familiar 1280px.
|
|
303
|
+
Defaults to 200. Whatever it takes comes off the content area beside it.
|
|
318
304
|
|
|
319
|
-
Live, like `MainOptions.
|
|
305
|
+
Live, like `MainOptions.maxWidth`.
|
|
320
306
|
|
|
321
307
|
**Type:** `number`
|
|
322
308
|
|
package/skill/Panel.md
CHANGED
|
@@ -89,35 +89,35 @@ visible at once, and both of them are really there.
|
|
|
89
89
|
|
|
90
90
|
### panel.maxWidth · member
|
|
91
91
|
|
|
92
|
-
The widest this panel can usefully be
|
|
93
|
-
|
|
94
|
-
*
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
- `"
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
the
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
else is open, so opening or closing a panel never
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
92
|
+
The widest this panel can usefully be — a ceiling the shell never
|
|
93
|
+
exceeds, so the draw function never has to look right past it. It is
|
|
94
|
+
counted in the shell's *columns*: the content area divides into the
|
|
95
|
+
narrowest whole number of columns of at least 360px each (three columns
|
|
96
|
+
of 360 in a 1080px area, four of 380 in 1520px), and a column is never
|
|
97
|
+
wider than 540 — where the area holds just one, a small centres in it
|
|
98
|
+
rather than stretching. So an ask never exceeds its column count × 540:
|
|
99
|
+
|
|
100
|
+
- `"small"` — one column, never above 540px: lists, detail forms.
|
|
101
|
+
- `"medium"` (the default) — two columns, never above 1080px.
|
|
102
|
+
- `"large"` — three columns, never above 1620px: wide tables.
|
|
103
|
+
- `"none"` — the whole content area, unbounded: boards, dashboards.
|
|
104
|
+
Bound it with the shell's own `maxWidth` where that matters.
|
|
105
|
+
|
|
106
|
+
Every size is capped at the content area, so on a phone they all come to
|
|
107
|
+
the same thing: one screen at a time. And a width depends only on the
|
|
108
|
+
window, never on what else is open, so opening or closing a panel never
|
|
109
|
+
resizes another — the run of columns just recentres in the area.
|
|
110
|
+
|
|
111
|
+
Ask only for what your content can actually use: a panel that would cap
|
|
112
|
+
its own content narrower than its ask is holding room that would have
|
|
113
|
+
let another column fit beside it.
|
|
114
114
|
|
|
115
115
|
Set it at the top of your handler and the panel is already that wide when
|
|
116
116
|
you draw (see `Panel.width`); set it later — when your data tells you
|
|
117
117
|
— and the panel reflows without being redrawn, keeping its state, while
|
|
118
118
|
the columns beside it move over.
|
|
119
119
|
|
|
120
|
-
**Type:** `
|
|
120
|
+
**Type:** `PanelSize`
|
|
121
121
|
|
|
122
122
|
### panel.loading · member
|
|
123
123
|
|
|
@@ -132,10 +132,10 @@ affects the animation; the stack and the URL never wait for it.
|
|
|
132
132
|
### panel.pinned · member
|
|
133
133
|
|
|
134
134
|
Keeps this panel from being closed by navigation happening *elsewhere*.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
click away. The user toggles it from the crumb's context menu
|
|
135
|
+
A navigation normally closes everything after the panel it came from (or
|
|
136
|
+
returned to); a pinned panel survives that, staying in the stack — slotted
|
|
137
|
+
in beneath the new panel, or parked out of sight when the new panel was
|
|
138
|
+
already beneath it. Either way it is one crumb click away. The user toggles it from the crumb's context menu
|
|
139
139
|
(right-click or long-press), which is also where the pin shows; setting
|
|
140
140
|
it from code does the same thing.
|
|
141
141
|
|
|
@@ -149,12 +149,11 @@ still close the panel.
|
|
|
149
149
|
|
|
150
150
|
Set this while the panel holds work that must not be lost — a dirty form,
|
|
151
151
|
an upload in flight. An unsaved panel cannot be closed, by anything:
|
|
152
|
-
navigation that would prune it parks it instead,
|
|
153
|
-
|
|
154
|
-
only parks it. `Panel.close` and the crumb menu's Close refuse,
|
|
152
|
+
navigation that would prune it parks it out of sight instead, wearing a
|
|
153
|
+
● in its crumb — even the browser's back button only parks it. `Panel.close` and the crumb menu's Close refuse,
|
|
155
154
|
Escape on it steps left along the stack rather than closing, and closing
|
|
156
|
-
the browser tab runs into the browser's own are-you-sure
|
|
157
|
-
|
|
155
|
+
the browser tab runs into the browser's own are-you-sure, the unsaved
|
|
156
|
+
panel brought on screen as the question is raised.
|
|
158
157
|
|
|
159
158
|
Only the app clears it; the user has no toggle. A Save or Discard button
|
|
160
159
|
clears it and then closes:
|
package/skill/PanelStack.md
CHANGED
|
@@ -53,10 +53,10 @@ unpinned panels that were after it (pinned ones stay, sliding in beneath
|
|
|
53
53
|
the new panel).
|
|
54
54
|
|
|
55
55
|
The same rules as a link click apply: pushing a path that is already open
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
returns to it — closing whatever was stacked on top — rather than opening
|
|
57
|
+
it twice, and a panel holding `Panel.unsaved` work is never closed,
|
|
58
|
+
only parked. That's what a plain link does, and what `data-panel=push`
|
|
59
|
+
says outright.
|
|
60
60
|
|
|
61
61
|
Note that a link builds on the panel it is *drawn in*, which is the
|
|
62
62
|
current panel only while no column beside it has the focus. Code
|
package/skill/SKILL.md
CHANGED
|
@@ -159,11 +159,11 @@ The first key that matches wins, and a segment a param refuses simply doesn't ma
|
|
|
159
159
|
|
|
160
160
|
**Navigating is just links.** Write ordinary `<a href="/...">` links; Staffa handles the clicks (so don't also call Aberdeen's `interceptLinks()`).
|
|
161
161
|
|
|
162
|
-
The open panels form a **stack**, and
|
|
162
|
+
The open panels form a **stack**, and its last panel is the **current** one: the panel the URL names, and the rightmost column on screen. Whatever you navigate to lands there.
|
|
163
163
|
|
|
164
|
-
- A link inside a panel opens its target on top of that panel, closing everything after it first. That's why clicking a second project replaces the open project instead of adding a third column
|
|
165
|
-
- A `data-panel` attribute on the link picks a different one of the three navigations
|
|
166
|
-
- A link to something that's already open goes back to it instead of opening it twice
|
|
164
|
+
- A link inside a panel opens its target on top of that panel, closing everything after it first. That's why clicking a second project replaces the open project instead of adding a third column.
|
|
165
|
+
- A `data-panel` attribute on the link picks a different one of the three navigations, which differ only in how much of the link's own context the target keeps: `push` (the default just described) keeps the link's panel and builds on it; `replace` keeps everything under that panel but not the panel itself — what prev/next buttons want; and `open` keeps none of it, giving the target its own stack exactly as a nav item would — for a search hit or a mention, where the panel you clicked from is coincidence, not context.
|
|
166
|
+
- A plain link to something that's already open goes back to it instead of opening it twice, closing whatever was stacked on top of it; a `replace` or `open` applies its usual shape instead, the open panel moving into place with its state intact. Either way the same path is never in the stack twice.
|
|
167
167
|
- A link that isn't inside a panel (a nav item, or one in a dialog) has no panel to build on, so it replaces the stack as a whole: the panel you asked for, with its ancestor panels opened beneath it (see [below](#ancestors)). Panels that the new stack also contains stay as they are, so clicking the nav item for the section you're already in won't reset it. Clicking a nav item and opening that same URL in a fresh tab therefore give you the same columns.
|
|
168
168
|
|
|
169
169
|
**The stack is an object, not a global.** In routed mode `S.main()` hands back the panel stack, and every panel gets the same object as `$panel.stack` — which is what a route handler uses, since it runs while the `S.main()` call is still going and can't see its return value yet.
|
|
@@ -185,21 +185,24 @@ Navigations settle asynchronously (closes travel through the browser's history),
|
|
|
185
185
|
|
|
186
186
|
Navigating faster than the shell can settle is fine: closing travels through the browser's history, so it takes a moment to land, and anything asked for in the meantime waits for it rather than being dropped. Two quick Escapes (or back gestures) peel two panels, each aimed at the stack the one before it was heading for.
|
|
187
187
|
|
|
188
|
-
**
|
|
188
|
+
**The content area is the window**, minus the nav sidebar — or, when `S.main({ maxWidth })` says so, that much of it, centred. Either way it is the same width whatever is open, so the sidebar, the top bar and the footer never move.
|
|
189
|
+
|
|
190
|
+
The shell divides that area into columns: the narrowest whole number of them that keeps each one at least **360px** wide, and no column ever wider than **540**. A 1080px content area is three columns of 360; a 1520px one is four of 380; below 720px there is a single column — of at most 540, centred. `$panel.maxWidth` counts in those columns:
|
|
189
191
|
|
|
190
192
|
| `maxWidth` | How wide the panel gets | Good for |
|
|
191
193
|
| --- | --- | --- |
|
|
192
|
-
| `"
|
|
193
|
-
| `"
|
|
194
|
-
| `"
|
|
194
|
+
| `"small"` | One column — never above 540px. | lists, detail forms — anything that reads well at phone width |
|
|
195
|
+
| `"medium"` (default) | Two columns — never above 1080px. | ordinary screens; the safe default |
|
|
196
|
+
| `"large"` | Three columns — never above 1620px. | wide tables, dense forms |
|
|
197
|
+
| `"none"` | The whole content area, unbounded. | boards, dashboards |
|
|
195
198
|
|
|
196
|
-
|
|
199
|
+
The ask is a promise in both directions: the shell never draws a panel wider than its column count × 540px, and every size is also capped at the content area — so a draw function has to look right from 360px up to its own ceiling, and nowhere past it. There is nothing below 360 to handle either: a narrower window is shown the 360px layout scaled down to fit (dialogs, menus and toasts scaling along), so 360 really is the floor.
|
|
197
200
|
|
|
198
|
-
|
|
201
|
+
A column's width depends only on the size of the window, never on what else is open. So opening or closing a panel never resizes the ones already on screen, and never reflows what someone was reading. As many columns as fit are shown, ending at the current panel; when they don't fill the content area they sit centred in it, so an arriving column nudges the others over to share the room.
|
|
199
202
|
|
|
200
|
-
|
|
203
|
+
`S.main({ navWidth, maxWidth })` sets the sidebar's width and the cap. Leave `maxWidth` off and the app simply fills the window — worth capping (`"1600px"`, say) if you'd rather it didn't march across a 4K display.
|
|
201
204
|
|
|
202
|
-
Columns tile
|
|
205
|
+
Columns tile the area they're given, separated by a hairline and no gutter — a column brings its own padding, so their contents stay comfortably apart regardless.
|
|
203
206
|
|
|
204
207
|
The panel is sized before your handler runs, and `$panel.width` is the resolved figure in pixels — so a chart, a virtualised list or a column count has the real width from the first frame, with nothing to measure. Set `maxWidth` at the top of your handler and you draw at the new width; set it later and the panel reflows without being redrawn, so nothing in it is rebuilt or loses its state.
|
|
205
208
|
|
|
@@ -217,11 +220,11 @@ function drawTask($panel: S.Panel<{ taskId: number }>) {
|
|
|
217
220
|
|
|
218
221
|
On a wide screen the title becomes the stack's last crumb and the Save button sits in a quiet strip at the top of the column. On a phone the crumb is still there and Save moves into the top bar, where the app menu was. Nothing in your code measures the viewport, and no screen is written twice.
|
|
219
222
|
|
|
220
|
-
**The breadcrumbs are the navigation.** The top bar's second line writes the open panels out as breadcrumbs — `Projects / Trackle / Task 42` — with the panels currently on screen in bold.
|
|
223
|
+
**The breadcrumbs are the navigation.** The top bar's second line writes the open panels out as breadcrumbs — `Projects / Trackle / Task 42` — with the panels currently on screen in bold. A crumb is an ordinary link to its panel, so clicking one goes back to that panel and closes what was stacked on top of it — and the browser's back button brings those columns back. The app's name and logo link to the app's home (the `home` option, `/` by default; `null` links neither), going back to it when it's already open and opening it when it isn't. A stack too long for the bar scrolls sideways, in an `S.scrollStrip` like the tab strip's.
|
|
221
224
|
|
|
222
225
|
That line is the `subtitle`'s while the stack has nothing to add: one panel open, reachable from a nav item that is already highlighted in a visible sidebar. Otherwise the stack takes it, since it is then the only thing naming the screen.
|
|
223
226
|
|
|
224
|
-
Right-click (or long-press) a crumb for **Close** — which takes just that panel out, wherever it sits in the stack — and **Pin**. A pinned panel — its crumb wears a pin — never closes as a side effect of navigation elsewhere: where
|
|
227
|
+
Right-click (or long-press) a crumb for **Close** — which takes just that panel out, wherever it sits in the stack — and **Pin**. A pinned panel — its crumb wears a pin — never closes as a side effect of navigation elsewhere: where a navigation would prune it, it rides along beneath the new panel instead (or parks out of sight, when the panel you went back to was already beneath it), one crumb click away. Pin the reference you keep coming back to, then navigate freely. An *explicit* close (Escape, `close()`, the crumb menu, `data-panel=replace`) still closes it, and it's yours from code as `$panel.pinned`. Because a crumb is a real link whose right-click the menu takes over, the menu also offers **Open in new tab** and **Copy link**.
|
|
225
228
|
|
|
226
229
|
A crumb can also wear a **●**: the panel holds unsaved work, and nothing will close it (see `$panel.unsaved` below).
|
|
227
230
|
|
|
@@ -266,7 +269,7 @@ Closing the current panel hands the focus to the panel on its left. Closing one
|
|
|
266
269
|
|
|
267
270
|
A closed panel is torn down at once: its `A.clean()` hooks run the moment it closes, so subscriptions, timers and requests stop there and then. Only its element hangs around, inert and frozen, for the length of the exit animation.
|
|
268
271
|
|
|
269
|
-
Escape
|
|
272
|
+
Escape closes the current panel — or just steps left, when it holds unsaved work or panels sit parked beyond it — and at the stack's start it jumps to the navigation. The browser's back button replays whole arrangements, re-opening what a navigation closed.
|
|
270
273
|
|
|
271
274
|
<a id="ancestors"></a>
|
|
272
275
|
|
|
@@ -298,7 +301,7 @@ Search params and the `#hash` belong to the current panel only. Anything another
|
|
|
298
301
|
|
|
299
302
|
**A few more things.**
|
|
300
303
|
|
|
301
|
-
- `columns: "single"` shows only the current panel, however wide the screen —
|
|
304
|
+
- `columns: "single"` shows only the current panel, however wide the screen — one screen at a time at every size, each still at its asked width, centred. Only the display changes: the URL, the back button, unsaved panels and the panels' own close buttons all behave the same.
|
|
302
305
|
- `linkNavigation` sets what a link *without* a `data-panel` attribute does: `"push"` (the default), `"replace"`, or `"open"`. With `"open"` every click replaces the content as a whole — which, with flat routes, is the conventional sidebar-and-content app: one pane, swapped on every click, the crumb line simply naming it.
|
|
303
306
|
- Both are live: pass a proxied options object (or make the field a getter) and a change is adopted in place, every open panel keeping its state.
|
|
304
307
|
- Only one routed `S.main()` can be mounted at a time; a second one throws — the URL is global, so two of them would fight over it. Nothing else is global: the stack belongs to its shell, and each handler gets its own `$panel`, since several panels are alive at once.
|
|
@@ -636,6 +639,16 @@ shell needs to know about the panel it is drawing. It's an Aberdeen proxy, so
|
|
|
636
639
|
you can set things later, such as a `title` that arrives with your data or
|
|
637
640
|
`loading` going back to `false`, and the shell keeps up.
|
|
638
641
|
|
|
642
|
+
## PanelSize · type
|
|
643
|
+
|
|
644
|
+
How wide a panel asks to be — a ceiling the shell never exceeds; see
|
|
645
|
+
`Panel.maxWidth`. `"small"` is the column the content area is divided
|
|
646
|
+
into; `"medium"` and `"large"` are two and three of those, and `"none"` is
|
|
647
|
+
the whole area. Each is capped at the content area, so on a narrow window
|
|
648
|
+
they all come to the same thing.
|
|
649
|
+
|
|
650
|
+
**Type:** `"small" | "medium" | "large" | "none"`
|
|
651
|
+
|
|
639
652
|
## Routes · type
|
|
640
653
|
|
|
641
654
|
A route table: path templates mapped to panel draw functions. Used as the
|
package/skill/main.md
CHANGED
|
@@ -11,7 +11,8 @@ right.
|
|
|
11
11
|
Instead of a single `content` slot, pass `MainOptions.routes` and the
|
|
12
12
|
shell takes over navigation: each route draws one screen, called a panel,
|
|
13
13
|
and as many columns as fit are shown at a time, side by side on a wide screen
|
|
14
|
-
and one at a time on a phone.
|
|
14
|
+
and one at a time on a phone; `MainOptions.maxWidth` caps how much room
|
|
15
|
+
they have between them. Each panel *declares* its chrome — its
|
|
15
16
|
`Panel.title` and its `Panel.actions` — and this shell places it:
|
|
16
17
|
the stack of titles as breadcrumbs in the bar, the actions on the panel's
|
|
17
18
|
column while several fit and in the bar once the shell is narrow enough
|
package/src/components/dialog.ts
CHANGED
|
@@ -55,7 +55,7 @@ A.insertGlobalCss({
|
|
|
55
55
|
"position:fixed z-index:200 top:50% left:50% " +
|
|
56
56
|
"display:flex flex-direction:column " +
|
|
57
57
|
"transform:translate(-50%,-50%) " +
|
|
58
|
-
"min-width:20rem max-width:min(90vw,44rem) max-height:min(88vh,800px) " +
|
|
58
|
+
"min-width:min(20rem,90vw) max-width:min(90vw,44rem) max-height:min(88vh,800px) " +
|
|
59
59
|
"r: $s-radius-lg; overflow:hidden " +
|
|
60
60
|
"transition: opacity 0.2s ease-out, transform 0.2s ease-out;",
|
|
61
61
|
"> header":
|