@jsenv/navi 0.29.348 → 0.29.349
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/dist/dev/jsenv_navi.js +43 -1
- package/dist/dev/jsenv_navi.js.map +2 -2
- package/dist/jsenv_navi.js +40 -1
- package/dist/jsenv_navi.js.map +2 -2
- package/docs/AI_INSTRUCTIONS.md +3 -1
- package/docs/popup_lift.md +120 -1
- package/docs/popup_open.md +7 -3
- package/package.json +1 -1
package/docs/AI_INSTRUCTIONS.md
CHANGED
|
@@ -172,7 +172,9 @@ to start when unsure which export solves a problem.
|
|
|
172
172
|
- `popup_lift.md` — `animation="lifting"`: the pressed card brought to the
|
|
173
173
|
front. `data-lift` names what is lifted and is rendered at once; the
|
|
174
174
|
trigger's box is the card's box; `lift="box"` for a card, `"scene"` for a
|
|
175
|
-
drawing framed the same way;
|
|
175
|
+
drawing framed the same way; one popup for a whole row, walked from the front
|
|
176
|
+
through a `SlideContainer`, `liftAnchor` naming where the closing comes back
|
|
177
|
+
to; what an opening costs and where the time goes;
|
|
176
178
|
the wall at half strength on the frame before the movement. Read before
|
|
177
179
|
giving a `Dialog` or a `Picker` `animation="lifting"`, or before measuring
|
|
178
180
|
why one opens slowly.
|
package/docs/popup_lift.md
CHANGED
|
@@ -18,6 +18,7 @@ and everything below follows from that one fact.
|
|
|
18
18
|
- [Two kinds: a card, or a scene](#two-kinds-a-card-or-a-scene)
|
|
19
19
|
- [The lifted node paints itself](#the-lifted-node-paints-itself)
|
|
20
20
|
- [Same width, or a wider box](#same-width-or-a-wider-box)
|
|
21
|
+
- [A row of cards: one popup that walks](#a-row-of-cards-one-popup-that-walks)
|
|
21
22
|
- [What it costs, and where the time goes](#what-it-costs-and-where-the-time-goes)
|
|
22
23
|
- [The wall, and the frame before the movement](#the-wall-and-the-frame-before-the-movement)
|
|
23
24
|
- [What the browser does around it](#what-the-browser-does-around-it)
|
|
@@ -38,6 +39,10 @@ lifts the card; a dialog that is the card wears `data-lift` itself.
|
|
|
38
39
|
</Picker>
|
|
39
40
|
```
|
|
40
41
|
|
|
42
|
+
That names one end. The other is the anchor — the box the opening came out of,
|
|
43
|
+
and the box the closing goes back into unless `liftAnchor` names another (see
|
|
44
|
+
[a row of cards](#a-row-of-cards-one-popup-that-walks)).
|
|
45
|
+
|
|
41
46
|
The opening waits for it. What a popup holds often arrives after the tap —
|
|
42
47
|
code fetched for the address, a row fetched for the popup — and a movement
|
|
43
48
|
started before the lifted node exists would carry the card into an empty box.
|
|
@@ -128,6 +133,118 @@ gaining room on the right, then the wider layout arrives.
|
|
|
128
133
|
Both read well; what does not is a box that is neither: a card whose width the
|
|
129
134
|
sheet changes by a few pixels for no reason the eye can name. Decide.
|
|
130
135
|
|
|
136
|
+
## A row of cards: one popup that walks
|
|
137
|
+
|
|
138
|
+
A row of small drawings — trophies on a profile, photos, badges — where
|
|
139
|
+
pressing one brings it to the front, big, and from there the next one is
|
|
140
|
+
reached without going back to the row. The popup is then about the whole row,
|
|
141
|
+
and the press only says where it opens: one `Dialog` for the row, lifting,
|
|
142
|
+
holding a `SlideContainer` the walk moves through.
|
|
143
|
+
|
|
144
|
+
```jsx
|
|
145
|
+
const currentKeySignal = useSignal(undefined);
|
|
146
|
+
|
|
147
|
+
<Button
|
|
148
|
+
id={`cup_tile_${cup.key}`}
|
|
149
|
+
command="--navi-open"
|
|
150
|
+
commandFor={ZOOM_ID}
|
|
151
|
+
value={cup.key}
|
|
152
|
+
variant="bare"
|
|
153
|
+
>
|
|
154
|
+
<Trophy medal={cup.medal} />
|
|
155
|
+
</Button>
|
|
156
|
+
|
|
157
|
+
<Dialog
|
|
158
|
+
id={ZOOM_ID}
|
|
159
|
+
animation="lifting"
|
|
160
|
+
mount="while-opened"
|
|
161
|
+
onOpen={(e) => {
|
|
162
|
+
currentKeySignal.value = e.detail.value;
|
|
163
|
+
}}
|
|
164
|
+
liftAnchor={`cup_tile_${currentKeySignal.value}`}
|
|
165
|
+
expand
|
|
166
|
+
data-slide-container-follows={SLIDES_ID}
|
|
167
|
+
>
|
|
168
|
+
<SlideContainer id={SLIDES_ID} signal={currentKeySignal} expandY>
|
|
169
|
+
{cups.map((cup) => (
|
|
170
|
+
<Slide key={cup.key} area={cup.key}>
|
|
171
|
+
<Box data-lift={cup.key === currentKeySignal.value ? "" : undefined}>
|
|
172
|
+
<Trophy medal={cup.medal} size="min(46vw, 180px)" />
|
|
173
|
+
</Box>
|
|
174
|
+
<Circumstances cup={cup} />
|
|
175
|
+
</Slide>
|
|
176
|
+
))}
|
|
177
|
+
</SlideContainer>
|
|
178
|
+
<SlideContainer.Left commandFor={SLIDES_ID} />
|
|
179
|
+
<SlideContainer.Right commandFor={SLIDES_ID} />
|
|
180
|
+
</Dialog>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**One popup, because the popup is about the row.** A picker per drawing is the
|
|
184
|
+
first thing one writes, and it is a dead end: each popup would have to hold the
|
|
185
|
+
whole row to be walkable, so a row of N costs N×N slides, and a walk opened on
|
|
186
|
+
the second drawing ends in a popup whose trigger is somewhere else. That is a
|
|
187
|
+
reason of its own to share a popup, beside the two in
|
|
188
|
+
[popup_open.md](./popup_open.md#when-a-shared-popup-is-still-the-right-answer):
|
|
189
|
+
what the popup shows is more than what was pressed.
|
|
190
|
+
|
|
191
|
+
**Which drawing it opens on is the command's `value`.** The press says it the
|
|
192
|
+
way it says it everywhere ([opening it ON
|
|
193
|
+
something](./popup_open.md#opening-it-on-something)), and `onOpen` writes it
|
|
194
|
+
into the container's own signal — the press seeds the walk rather than keeping
|
|
195
|
+
a second copy of it, and from then on the chevrons, the arrows and a thumb
|
|
196
|
+
write the same signal (see [state_binding.md](./state_binding.md)).
|
|
197
|
+
|
|
198
|
+
**`data-lift` moves with the walk, and has to be right on the first frame.**
|
|
199
|
+
There is one lifted node per document, and here it is the current slide's
|
|
200
|
+
drawing — a condition on the signal, not a mark written once on the popup. The
|
|
201
|
+
lift takes the first `data-lift` it finds on the frame the popup opens:
|
|
202
|
+
`mount="while-opened"` is what makes that frame the right one, since the
|
|
203
|
+
content is built after `onOpen`, on the drawing the open named. Content kept
|
|
204
|
+
across openings still carries the mark of the drawing the walk was left on, and
|
|
205
|
+
the lift takes that one. The closing reads it the same way, and a mark left on
|
|
206
|
+
a slide the walk moved off is a picture taken where that slide stands — off
|
|
207
|
+
screen — so the box flies in from outside the surface. The bill for rebuilding
|
|
208
|
+
is the row's, not one card's — every slide is built on every opening (see
|
|
209
|
+
[costs](#what-it-costs-and-where-the-time-goes)).
|
|
210
|
+
|
|
211
|
+
**The trigger's box is what travels, so the button is the drawing and nothing
|
|
212
|
+
else.** That is [the trigger's box is the card's
|
|
213
|
+
box](#the-triggers-box-is-the-cards-box) read backwards: everything inside the
|
|
214
|
+
button is stretched into the popup's box on the way. A tile is usually more
|
|
215
|
+
than its drawing — a count floating in a corner, a level written
|
|
216
|
+
underneath — and those belong outside the button, positioned against the tile
|
|
217
|
+
or placed under it. Layout, not a prop.
|
|
218
|
+
|
|
219
|
+
**The anchor comes with the press.** A button opening a popup names itself as
|
|
220
|
+
the anchor ([the anchor](./popup_open.md#the-anchor), third rule), so the lift
|
|
221
|
+
starts on the drawing that was pressed, with no `anchor` prop and no
|
|
222
|
+
`triggerNaviCommand`. Writing an `anchor` prop is how to lose that: the prop is
|
|
223
|
+
what answers when no press does, and it wins over the press.
|
|
224
|
+
|
|
225
|
+
**The arrows reach the walk from anywhere on the surface.** Only slides go in a
|
|
226
|
+
`SlideContainer`, so the chevrons pinned to the edges of a full-screen surface
|
|
227
|
+
are outside it, and the keyboard, once it lands on one of them, walks nothing.
|
|
228
|
+
`data-slide-container-follows={SLIDES_ID}` on the `Dialog` — the outermost
|
|
229
|
+
element, which is what holds the keyboard when nothing in it does — makes the
|
|
230
|
+
whole surface a follower.
|
|
231
|
+
|
|
232
|
+
**Where it comes back to is named too.** The opening's anchor is the drawing
|
|
233
|
+
that was pressed, and a walk that moved on has something else in front by the
|
|
234
|
+
time it closes: left alone, the silver cup flies home into the gold cup's
|
|
235
|
+
tile. `liftAnchor` says the other end — same grammar as `anchor` (element, ref
|
|
236
|
+
or id), read at the close rather than kept from the opening, so what names the
|
|
237
|
+
tile currently in front is read then. An id built from the signal the walk is
|
|
238
|
+
bound to is the shortest way to say it, the row's tiles carrying the matching
|
|
239
|
+
ids. Left out, the box comes back where it came from, which is right exactly
|
|
240
|
+
as long as nothing walked.
|
|
241
|
+
|
|
242
|
+
**A press on the surface that dismisses is `data-navi-popup-outside`.** Marking
|
|
243
|
+
the see-through box as backdrop (see
|
|
244
|
+
[popup_backdrop.md](./popup_backdrop.md)) is read on the press itself. A close
|
|
245
|
+
written by hand on a click has to tell a click from the end of a swipe — and
|
|
246
|
+
that guard is the sign the marker was missed.
|
|
247
|
+
|
|
131
248
|
## What it costs, and where the time goes
|
|
132
249
|
|
|
133
250
|
Measured at CPU ×6 on the demo bench (`12_picker_card_demo.html#lift-bench`),
|
|
@@ -147,7 +264,9 @@ hot spot, plus `showModal()` and one layout. So the lever is the content:
|
|
|
147
264
|
|
|
148
265
|
- **Build less, or earlier.** A sheet that is the same across openings keeps
|
|
149
266
|
`mount="from-first-open"`. A sheet that must be rebuilt (`while-opened`)
|
|
150
|
-
pays its build on every tap; keep it as light as the page allows.
|
|
267
|
+
pays its build on every tap; keep it as light as the page allows. A popup
|
|
268
|
+
whose lifted node changes from one opening to the next has no choice — see
|
|
269
|
+
[a row of cards](#a-row-of-cards-one-popup-that-walks).
|
|
151
270
|
- **Do not rebuild by accident.** A sheet whose code or data is tied to the
|
|
152
271
|
address (`?edit=<id>` driving a route action) is thrown away when the
|
|
153
272
|
address clears and rebuilt through a `null` render on the next opening —
|
package/docs/popup_open.md
CHANGED
|
@@ -585,15 +585,19 @@ frame it would cover it, and every press on the empty plan would open it.
|
|
|
585
585
|
|
|
586
586
|
### When a shared popup is still the right answer
|
|
587
587
|
|
|
588
|
-
|
|
588
|
+
Three cases, and only three:
|
|
589
589
|
|
|
590
590
|
- **the press can come from anywhere** — a keyboard shortcut, a menu, a button,
|
|
591
591
|
all opening the same thing. Written per press it would exist several times
|
|
592
592
|
over, each with its own open state;
|
|
593
593
|
- **the popup has to outlive its trigger** — a row that leaves while its dialog
|
|
594
|
-
is open (a list refreshing under it) takes a popup written inside it with it
|
|
594
|
+
is open (a list refreshing under it) takes a popup written inside it with it;
|
|
595
|
+
- **the popup is about more than what was pressed** — a viewer one walks
|
|
596
|
+
through, where the press only says which item it opens on. Written per item,
|
|
597
|
+
each popup would have to hold the whole row to be walkable. See
|
|
598
|
+
[popup_lift.md](./popup_lift.md#a-row-of-cards-one-popup-that-walks).
|
|
595
599
|
|
|
596
|
-
|
|
600
|
+
None of them is "one popup per row of a list", which is what a picker is for.
|
|
597
601
|
|
|
598
602
|
Do not mix the two. A `<Form>` at the root of a picker's popup IS the mirrored
|
|
599
603
|
control, so its value is the picker's value: handing the picker something else
|