@justai/cuts 0.61.0 → 0.62.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 +2 -2
- package/src/Toolbar.astro +45 -2
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.62.0",
|
|
4
|
+
"description": "A persona's named parts \u2014 the page shell that holds them, and the cuts themselves.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
package/src/Toolbar.astro
CHANGED
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
// • BackToZone — takes no props → internalised here (the persona no longer imports it).
|
|
18
18
|
// • the three nav aria-labels — resolved strings (like every other cut: Posts, LangPicker) → props.
|
|
19
19
|
// • kernelIcon — the ONE per-persona nav glyph (⚡ / clock / globe …) → required slot.
|
|
20
|
+
// • profileIcon — OPTIONAL. The persona's own mark, in place of the generic bust. The Profile cut is
|
|
21
|
+
// WHO, so its icon may say *whose* profile this is rather than that a profile exists; the face is the
|
|
22
|
+
// persona's, so it comes from the persona. Omit it and the bust stays — adopting this is each
|
|
23
|
+
// persona's own decision, taken when its mark exists, and nothing moves in the fleet without it.
|
|
24
|
+
// Note what a mark cannot do: an <img> ignores `currentColor`, so `.active`'s accent never reaches
|
|
25
|
+
// it. Slot presence adds `.tb-mark`, which carries "you are here" as opacity instead.
|
|
20
26
|
// • langPicker — needs the persona's own locale data (the list must NOT live in the shared package —
|
|
21
27
|
// it bit us twice; see @justai/ui/locale) → a slot the persona fills with its <LangPicker/>.
|
|
22
28
|
// • navExtra — optional extra nav item after Posts (e.g. the timers' fullscreen button) → slot.
|
|
@@ -52,8 +58,29 @@ const { sectionsLabel, profileLabel, kernelLabel, postsLabel, home = true, files
|
|
|
52
58
|
<div class="tb-left">
|
|
53
59
|
{home && <BackToZone />}
|
|
54
60
|
<nav class="tb-nav-group" aria-label={sectionsLabel}>
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
{/* The Profile cut is WHO, so a persona may put its OWN FACE here instead of the generic bust —
|
|
62
|
+
the icon then says whose profile this is rather than that a profile exists. Passed as a slot
|
|
63
|
+
for the same reason `kernelIcon` is: the face belongs to the persona, not to the shell.
|
|
64
|
+
|
|
65
|
+
The fallback matters as much as the slot. A persona that passes nothing keeps the bust it has
|
|
66
|
+
today, so adopting this is a decision each persona makes when its own mark is ready — nothing
|
|
67
|
+
in the fleet moves on the day this ships.
|
|
68
|
+
|
|
69
|
+
`tb-mark` is set from slot PRESENCE, not from a prop somebody could forget to keep in step. It
|
|
70
|
+
exists because a mark cannot take `currentColor`: an <img> ignores it, so the accent that says
|
|
71
|
+
"you are here" would never reach it. The class moves that signal to opacity instead. */}
|
|
72
|
+
<a
|
|
73
|
+
class:list={["tb-nav", { "tb-mark": Astro.slots.has("profileIcon") }]}
|
|
74
|
+
id="navProfile"
|
|
75
|
+
href="#profile"
|
|
76
|
+
aria-label={profileLabel}
|
|
77
|
+
title={profileLabel}
|
|
78
|
+
>
|
|
79
|
+
{Astro.slots.has("profileIcon") ? (
|
|
80
|
+
<slot name="profileIcon" />
|
|
81
|
+
) : (
|
|
82
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
|
83
|
+
)}
|
|
57
84
|
</a>
|
|
58
85
|
<a class="tb-nav" id="navKernel" href="#kernel" aria-label={kernelLabel} title={kernelLabel}>
|
|
59
86
|
<slot name="kernelIcon" />
|
|
@@ -144,6 +171,22 @@ const { sectionsLabel, profileLabel, kernelLabel, postsLabel, home = true, files
|
|
|
144
171
|
.tb-nav:hover { color: var(--text); }
|
|
145
172
|
.tb-nav:active { transform: scale(0.9); }
|
|
146
173
|
.tb-nav.active { color: var(--accent); }
|
|
174
|
+
|
|
175
|
+
/* A MARK SAYS "YOU ARE HERE" WITH OPACITY, BECAUSE IT CANNOT SAY IT WITH COLOUR.
|
|
176
|
+
The three stroke icons are painted by `currentColor`, so `.active` turning them accent is enough. An
|
|
177
|
+
<img> mark ignores `currentColor` entirely — it carries its own paint — so on the mark that rule is a
|
|
178
|
+
declaration with no effect, and the one icon a person is looking at would be the one that never lit.
|
|
179
|
+
Opacity is the same answer BackToZone reached when it took the mark: dimmed at rest, whole when
|
|
180
|
+
current. `!important`-free, because these are more specific than the colour rules above. */
|
|
181
|
+
.tb-nav.tb-mark { opacity: 0.72; transition: opacity 0.25s var(--ease-out); }
|
|
182
|
+
.tb-nav.tb-mark:hover,
|
|
183
|
+
.tb-nav.tb-mark.active { opacity: 1; }
|
|
184
|
+
/* The shell sizes the mark and says NOTHING about `display`, deliberately. Two files arrive for the two
|
|
185
|
+
themes — an SVG's internal `prefers-color-scheme` does not survive <img>, measured — and the persona
|
|
186
|
+
hides one with a media query. A `display: block` here would be two classes deep against the persona's
|
|
187
|
+
one and would WIN, showing both marks stacked. That exact mistake shipped once in this shell and the
|
|
188
|
+
founder counted the duplicate logos before anyone read the CSS. Width and height only. */
|
|
189
|
+
.tb-nav.tb-mark :global(img) { width: 19px; height: 19px; }
|
|
147
190
|
.tb-nav :global(svg) { width: 19px; height: 19px; }
|
|
148
191
|
</style>
|
|
149
192
|
|