@justai/cuts 0.75.0 → 0.77.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/package.json +3 -3
- package/src/BackToZone.astro +57 -2
- package/src/Toolbar.astro +71 -7
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justai/cuts",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A persona's named parts
|
|
3
|
+
"version": "0.77.0",
|
|
4
|
+
"description": "A persona's named parts — the page shell that holds them, and the cuts themselves.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@justai/core": "^0.10.0",
|
|
40
|
-
"@justai/ui": "^0
|
|
40
|
+
"@justai/ui": "^0",
|
|
41
41
|
"@justai/atrium": "^0.1.9"
|
|
42
42
|
}
|
|
43
43
|
}
|
package/src/BackToZone.astro
CHANGED
|
@@ -2,10 +2,46 @@
|
|
|
2
2
|
// Home affordance → app.zone (the platform / App Store home). Standard on every app:
|
|
3
3
|
// always visible at the top-left of the toolbar. Also tidies the ?ref / ?lang hints
|
|
4
4
|
// from the URL so shared links stay clean.
|
|
5
|
+
//
|
|
6
|
+
// IT IS THE ZONE'S MARK NOW, NOT A HOUSE. The generic roof-and-walls said "home" in the abstract and
|
|
7
|
+
// nothing about WHERE home is — every app in the fleet drew the same house, so a visitor who had not
|
|
8
|
+
// already seen app.zone learned nothing from it. The four-bracket mark names the destination.
|
|
9
|
+
//
|
|
10
|
+
// INLINE, and it has to be. A shared component cannot reference `/appzone-mark.svg`: every persona
|
|
11
|
+
// serves its own host, so that path would resolve to a file each one had to carry. Inline also buys
|
|
12
|
+
// what an <img> forecloses — an <img> ignores `currentColor`, and this mark has to be able to speak
|
|
13
|
+
// in the toolbar's ink.
|
|
14
|
+
//
|
|
15
|
+
// MONOCHROME AT REST, ITS OWN COLOURS ON HOVER. app.zone's own toolbar does the same thing against a
|
|
16
|
+
// different state: there the mark is ink until the Profile cut is current, because there the mark IS
|
|
17
|
+
// the persona. Here it can never become current — it is a link OUT — so the idea is mapped onto the
|
|
18
|
+
// only state this control has. At rest it sits level with the row it stands in; engage with it and
|
|
19
|
+
// the zone shows itself. `:focus-visible` counts as the same event: somebody arriving by Tab should
|
|
20
|
+
// be shown what a pointer shows.
|
|
21
|
+
// On touch there is no hover and it stays ink, which is the correct resting appearance rather than a
|
|
22
|
+
// degraded one. Press feedback is untouched: `:active`'s scale applies to the whole anchor.
|
|
23
|
+
//
|
|
24
|
+
// HOUSE-LIGHTING: EXCEPTION — inline, and unlit. The mark carries double inner shadows in
|
|
25
|
+
// app.zone's own appzone-mark.svg; at 20px a `stdDeviation` of 3.84 in a 928 box is 0.08px, so the
|
|
26
|
+
// lighting was never visible at this size, and in one flat ink there is nothing to shade. The
|
|
27
|
+
// geometry here is a second copy of the one in that file, which is authored by hand and generated by
|
|
28
|
+
// nothing — a redraw has to be carried across to this component as well.
|
|
5
29
|
---
|
|
6
30
|
|
|
7
31
|
<a class="home" href="https://app.zone" data-home aria-label="app.zone" title="app.zone">
|
|
8
|
-
<svg
|
|
32
|
+
<svg class="azmark" viewBox="-8.5 0 928 928" aria-hidden="true">
|
|
33
|
+
<path class="arm a1" d="M360.365 0C372.599 0 382.517 9.91778 382.517 22.152V97.7555C382.517 109.99 372.599 119.907 360.365 119.907H203.398C157.082 119.907 119.537 157.453 119.537 203.769V353.64C119.537 370.244 106.077 383.704 89.4732 383.704H22.152C9.91778 383.704 0 373.786 0 361.552V175.633C0 78.6337 78.6338 0 175.634 0H360.365Z"/>
|
|
34
|
+
<path class="arm a2" d="M550.635 2.37305C538.401 2.37305 528.483 12.2908 528.483 24.525V100.129C528.483 112.363 538.401 122.28 550.635 122.28H707.602C753.918 122.28 791.463 159.826 791.463 206.142V356.013C791.463 372.617 804.923 386.077 821.527 386.077H888.848C901.082 386.077 911 376.159 911 363.925V178.006C911 81.0068 832.366 2.37305 735.366 2.37305H550.635Z"/>
|
|
35
|
+
<path class="arm a3" d="M550.635 928.009C538.401 928.009 528.483 918.092 528.483 905.857V830.254C528.483 818.02 538.401 808.102 550.635 808.102H707.602C753.918 808.102 791.463 770.556 791.463 724.241V574.369C791.463 557.765 804.923 544.305 821.527 544.305H888.848C901.082 544.305 911 554.223 911 566.457V752.376C911 849.376 832.366 928.009 735.366 928.009H550.635Z"/>
|
|
36
|
+
<path class="arm a4" d="M360.365 928.009C372.599 928.009 382.517 918.092 382.517 905.857V830.254C382.517 818.02 372.599 808.102 360.365 808.102L203.398 808.102C157.082 808.102 119.537 770.556 119.537 724.241L119.537 574.369C119.537 557.765 106.077 544.305 89.4732 544.305H22.152C9.91778 544.305 0 554.223 0 566.457L0 752.376C0 849.376 78.6338 928.009 175.634 928.009L360.365 928.009Z"/>
|
|
37
|
+
<rect class="ctr" x="348.103" y="367.09" width="203.323" height="203.323" rx="16.614"/>
|
|
38
|
+
<defs>
|
|
39
|
+
<linearGradient id="azHome1" x1="435.524" y1="-60.9179" x2="6.32917" y2="377.375" gradientUnits="userSpaceOnUse"><stop stop-color="#CCDA3E"/><stop offset="1" stop-color="#5FA82C"/></linearGradient>
|
|
40
|
+
<linearGradient id="azHome2" x1="460.049" y1="-96.9153" x2="904.671" y2="379.748" gradientUnits="userSpaceOnUse"><stop stop-color="#F2694A"/><stop offset="1" stop-color="#E04A30"/></linearGradient>
|
|
41
|
+
<linearGradient id="azHome3" x1="425.634" y1="1029.67" x2="904.671" y2="550.635" gradientUnits="userSpaceOnUse"><stop stop-color="#F8C24A"/><stop offset="1" stop-color="#EFA229"/></linearGradient>
|
|
42
|
+
<linearGradient id="azHome4" x1="450.555" y1="993.674" x2="6.32921" y2="550.635" gradientUnits="userSpaceOnUse"><stop stop-color="#5285DC"/><stop offset="1" stop-color="#2E62C6"/></linearGradient>
|
|
43
|
+
</defs>
|
|
44
|
+
</svg>
|
|
9
45
|
</a>
|
|
10
46
|
|
|
11
47
|
<style>
|
|
@@ -17,7 +53,26 @@
|
|
|
17
53
|
}
|
|
18
54
|
.home:hover { color: var(--text); }
|
|
19
55
|
.home:active { transform: scale(0.9); }
|
|
20
|
-
.home svg { width: 20px; height: 20px; }
|
|
56
|
+
.home svg { width: 20px; height: 20px; display: block; }
|
|
57
|
+
|
|
58
|
+
/* At rest every part of the mark is the row's ink, so the silhouette reads as one shape rather than
|
|
59
|
+
a logo parked in a toolbar. The centre is FILLED rather than knocked out: in the coloured drawing
|
|
60
|
+
it is a counter-shape separating four saturated arms, and in one colour there is nothing to
|
|
61
|
+
separate — a hole there would be a gap the mark does not have. */
|
|
62
|
+
.azmark .arm,
|
|
63
|
+
.azmark .ctr { fill: currentColor; }
|
|
64
|
+
|
|
65
|
+
.home:hover .azmark .a1, .home:focus-visible .azmark .a1 { fill: url(#azHome1); }
|
|
66
|
+
.home:hover .azmark .a2, .home:focus-visible .azmark .a2 { fill: url(#azHome2); }
|
|
67
|
+
.home:hover .azmark .a3, .home:focus-visible .azmark .a3 { fill: url(#azHome3); }
|
|
68
|
+
.home:hover .azmark .a4, .home:focus-visible .azmark .a4 { fill: url(#azHome4); }
|
|
69
|
+
/* The centre follows the ground, and both values are the project's own: #F5F1E8 is the centre of
|
|
70
|
+
Logo Black, drawn for dark grounds, and #2B2724 the centre of Logo White, drawn for pale ones.
|
|
71
|
+
Dark is the un-queried default because the fleet's tokens are dark-first. */
|
|
72
|
+
.home:hover .azmark .ctr, .home:focus-visible .azmark .ctr { fill: #F5F1E8; }
|
|
73
|
+
@media (prefers-color-scheme: light) {
|
|
74
|
+
.home:hover .azmark .ctr, .home:focus-visible .azmark .ctr { fill: #2B2724; }
|
|
75
|
+
}
|
|
21
76
|
</style>
|
|
22
77
|
|
|
23
78
|
<script>
|
package/src/Toolbar.astro
CHANGED
|
@@ -163,14 +163,47 @@ import AuthMount from "./AuthMount.astro";
|
|
|
163
163
|
margin-inline: calc(-1 * max(var(--edge, 16px), env(safe-area-inset-left))) calc(-1 * max(var(--edge, 16px), env(safe-area-inset-right)));
|
|
164
164
|
padding-block: max(8px, env(safe-area-inset-top)) 8px;
|
|
165
165
|
padding-inline: max(var(--edge, 16px), env(safe-area-inset-left)) max(var(--edge, 16px), env(safe-area-inset-right));
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
166
|
+
|
|
167
|
+
/* ── THE BAR IS A SHELF, NOT A TINT ──────────────────────────────────────────────────────
|
|
168
|
+
*
|
|
169
|
+
* queries: the toolbar reads as a black strip · why is the bar darker in dark than in light ·
|
|
170
|
+
* the bar looks flat against the column · toolbar material · --toolbar-bg
|
|
171
|
+
*
|
|
172
|
+
* It used to derive its fill from `--bg` — `color-mix(--bg 70%, transparent)` under a blur.
|
|
173
|
+
* One declaration, but it meant two different things: `--bg` is a near-white in light and #000
|
|
174
|
+
* in dark, so the same rule read "lighten a near-white a little" on one ground and "pull a
|
|
175
|
+
* lifted surface to pure black" on the other. Measured against the column it sits on: **-6 in
|
|
176
|
+
* light, -17 in dark.** That asymmetry was a by-product of the token, never a decision.
|
|
177
|
+
*
|
|
178
|
+
* So it takes the CARD's material instead, and the light comes from above like everything else:
|
|
179
|
+
* an opaque fill with a shadow cast downward, and the page sliding under it. The fill is opaque
|
|
180
|
+
* ON PURPOSE — the blur was inert in light anyway, because the column is 92% opaque and there is
|
|
181
|
+
* nothing behind it to refract.
|
|
182
|
+
*
|
|
183
|
+
* WHY IT IS HERE NOW. app.zone settled this, qr copied it verbatim — same two hex values, same
|
|
184
|
+
* two shadows — and BOTH left a comment saying it belongs in cuts. Two consumers is the
|
|
185
|
+
* promotion trigger, and the note the second one wrote is the specification:
|
|
186
|
+
*
|
|
187
|
+
* "the right end state is cuts reading `var(--toolbar-bg, <its current expression>)`,
|
|
188
|
+
* after which these four declarations delete themselves and the tokens alone do the work."
|
|
189
|
+
*
|
|
190
|
+
* The token remains the seam: a persona whose ground is genuinely different sets `--toolbar-bg`
|
|
191
|
+
* and `--toolbar-shadow` and this rule steps aside. */
|
|
192
|
+
background: var(--toolbar-bg, #1e202a);
|
|
193
|
+
box-shadow: var(--toolbar-shadow, 0 2px 12px -2px rgba(0, 0, 0, 0.55));
|
|
194
|
+
/* No hairline: it was the only thing separating the bar from the column, and the shadow does
|
|
195
|
+
that now. A line under an OPAQUE shelf reads as a seam rather than as a separation. */
|
|
196
|
+
border-block-end: none;
|
|
197
|
+
}
|
|
198
|
+
@media (prefers-color-scheme: light) {
|
|
199
|
+
.toolbar {
|
|
200
|
+
background: var(--toolbar-bg, #fbfcfe);
|
|
201
|
+
box-shadow: var(--toolbar-shadow, 0 1px 2px rgba(16, 24, 40, 0.06), 0 8px 20px -8px rgba(16, 24, 40, 0.16));
|
|
202
|
+
}
|
|
172
203
|
}
|
|
173
|
-
|
|
204
|
+
/* `.stuck` is still set by the script below and still means "content is under the bar" — it simply
|
|
205
|
+
has nothing to paint now that the shelf is opaque and always shadowed. Kept because the class is
|
|
206
|
+
part of this cut's contract and a consumer may hang its own behaviour on it. */
|
|
174
207
|
@media (min-width: 768px) { .toolbar { margin-inline: -28px; padding-inline: 28px; } }
|
|
175
208
|
/* icons row + the scroll-reactive title strip below it */
|
|
176
209
|
.tb-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
@@ -219,6 +252,37 @@ import AuthMount from "./AuthMount.astro";
|
|
|
219
252
|
shrink the identity. */
|
|
220
253
|
.tb-nav.tb-mark :global(img) { width: 19px; height: 19px; }
|
|
221
254
|
.tb-nav :global(svg) { width: 19px; height: 19px; }
|
|
255
|
+
|
|
256
|
+
/* ── EQUAL INK, TWO BOXES ────────────────────────────────────────────────────────────────────
|
|
257
|
+
*
|
|
258
|
+
* queries: the toolbar icons are not the same size · the mark looks bigger than the glyphs ·
|
|
259
|
+
* the row is not level · 25.33px
|
|
260
|
+
*
|
|
261
|
+
* The paragraph above ends by naming the way out — *"grow the GLYPHS, not the identity"* — and
|
|
262
|
+
* this is that, arriving from the two repos that measured it.
|
|
263
|
+
*
|
|
264
|
+
* "19px" means two different things in this row. A Lucide glyph is drawn in a 24 viewBox with its
|
|
265
|
+
* ink between 3 and 21, so a 19px box puts **14.25px** of ink on screen; a mark runs to the edge
|
|
266
|
+
* of its own viewBox and puts **18.65px**. The mark therefore reads about a third larger, which is
|
|
267
|
+
* exactly what it did — and while the mark was still coloured, colour carried part of that
|
|
268
|
+
* difference. Now that it is monochrome at rest, the size gap is the only thing left and it shows.
|
|
269
|
+
*
|
|
270
|
+
* 19 × 24/18 = 25.33px is the box at which a glyph's INK measures 19px, the same 19px the mark
|
|
271
|
+
* occupies. `:not(.tb-mark)` is not a special case — it is the same rule read the other way: a
|
|
272
|
+
* glyph carries padding inside its viewBox and a mark does not, so equal ink needs unequal boxes.
|
|
273
|
+
*
|
|
274
|
+
* app.zone settled it, qr arrived at the identical number, and qr's own comment says why it is
|
|
275
|
+
* here: *"otherwise every persona has to remember to carry it, which is precisely the thing the
|
|
276
|
+
* shared shell exists to prevent."* */
|
|
277
|
+
.tb-nav:not(.tb-mark) :global(svg) { width: 25.33px; height: 25.33px; }
|
|
278
|
+
|
|
279
|
+
/* THE BUBBLE HANGS. Its silhouette's centre measures 1.05px below the line the other three sit on
|
|
280
|
+
(39.05 against 38.0) because the tail is part of the shape and pulls the box down with it — the
|
|
281
|
+
glyph is centred while the thing you SEE is not. A pixel is inside the noise on most rows; on
|
|
282
|
+
four icons at one size sharing one baseline it is the only thing left that is not level.
|
|
283
|
+
Nudged rather than redrawn, and `transform` on the svg never collides with the press feedback:
|
|
284
|
+
`.tb-nav:active`'s scale lives on the anchor. Both repos carry this verbatim. */
|
|
285
|
+
#navPosts :global(svg) { transform: translateY(-1px); }
|
|
222
286
|
</style>
|
|
223
287
|
|
|
224
288
|
<script>
|