@bongos/core 1.19.400 → 1.19.401
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/.bongos-core.json +22 -22
- package/docs/copy-inventory.md +233 -232
- package/docs/copy-registry.json +293 -284
- package/docs/design/projects-hub-direction-v2.md +38 -0
- package/docs/recipes/ui-look-before-you-ship.md +1 -1
- package/modules/ui-design/kit/lib.js +6 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/assets/cosmos.css +88 -35
- package/public-landing/index.html +13 -15
- package/public-landing/index.probes.json +8 -5
- package/public-landing/projects.html +23 -13
- package/public-landing/projects.probes.json +17 -10
- package/public-landing/projects.states.json +1 -1
- package/src/module-api.js +3 -1
- package/tests/landing_page.mjs +8 -4
- package/tests/projects_hub.mjs +28 -1
- package/tests/ui_design_kit.mjs +5 -4
|
@@ -106,3 +106,41 @@ The criterion `apex-hub-chrome-and-card` moves to the builds: task 1003300 (the
|
|
|
106
106
|
- **Task 1003300** builds v2's bar, menus (Sky / Table / Your projects / New project) and search, with Only mine beside the search and the toolbar retired, into `public-landing/projects.html` + `cosmos.css` (the hub's sheet moves onto the world's derived tier the way `world.css` did, keeping `--line` and the status vocabulary), retargets the tests in §6, regenerates the copy registry.
|
|
107
107
|
- **Task 1003301** builds the picked card and its ladder, adds the enrichment fields (§6) inside the same `Promise.allSettled` with the shared null object, gates the hall entry on the new hall-address field and membership, and keeps the orbs and the hover card untouched.
|
|
108
108
|
- The unpicked versions stay on disk as built and verified; what they leave behind is listed per version in §3.
|
|
109
|
+
|
|
110
|
+
## 9. The owner's review of the shipped chrome, and the table in the world (task 1003332)
|
|
111
|
+
|
|
112
|
+
**Date:** 2026-08-28 · three corrections from the owner's screenshot review of `/projects` (the Projects band open, the table view). Each overrides §7 where they conflict. Rendered through the kit before and after (`node modules/ui-design/kit/render.js --page /projects`, both modes, 1440 / 390 / 320; the landing the same) — ALL CLEAN throughout; the probes 26/26 on the hub and 11/11 on the landing.
|
|
113
|
+
|
|
114
|
+
### 9.1 About and Docs leave the Projects band: the footer row
|
|
115
|
+
|
|
116
|
+
They are site pages, not project views. Two placements were rendered as a before/after on both pages (dark and light, 1440 and 390): **(A)** beside the identity slot as two lowercase text triggers (`about docs projects`), folding away under 900; **(B)** the footer row the landing already had (About · Docs · Privacy · Terms · Contact · Builders' hall). **Pick: B, the footer, on both pages.** One home at every width (A needs the footer anyway under 900 — two homes for two links); the bar stays the Operate bar given 3 asked for ("this way we dont clutter the bar"); About and Docs are the same kind of thing as Privacy / Terms / Contact. Consequences: the `bandMore` rung and its rules left both sheets; the hub's footer row wraps (`flex-wrap`) and `--foot-h` was re-measured with six links in it (136px under 420, 154px under 340, so the sky still fits the viewport); the About anchor stays the landing's lifecycle band (`/#about` from the hub, `#about` on the landing) until goal 1000063's page takes it. Probes retargeted: the band's last item is New project, the signed-out band is three cells, the footer carries both hrefs on both pages.
|
|
117
|
+
|
|
118
|
+
### 9.2 The bands overlay; the page does not reflow
|
|
119
|
+
|
|
120
|
+
`.menuBand` is `position:absolute; left:0; right:0; top:var(--top-h); z-index:49` against the document in both sheets. Everything else the disclosure did stays: full width on `bg-card` closed by one hairline, `aria-expanded` + `aria-controls` and no menu role, Escape / arrows / Enter / Tab-out / click-outside, one open at a time, the 220ms rise + fade on the world's ease-out, dead under the kill switch. The stack: band 49 < bar 50 < the folded search row 51 < the card scrim 60. The kit gained a `top[[sel,px]]` expectation for exactly this proof; the probes assert `#hubMain` at 64px (60 at 390) and the landing's `#main` at 72px both before and after a band opens. DESIGN.md's Navigation paragraph now says overlay.
|
|
121
|
+
|
|
122
|
+
### 9.3 Found on the way: the Table deep link landed on the sky
|
|
123
|
+
|
|
124
|
+
`setView()` rewrites the URL to `?view=map` at boot, and the shipped boot read `sub=table` *after* it — so the landing's Table item (and any shared `/projects?view=map&sub=table`) opened the sky. The boot query is now read once, before `setView`; a probe opens the deep link and expects the table on stage with Table current; `tests/projects_hub.mjs` pins the order.
|
|
125
|
+
|
|
126
|
+
### 9.4 The table in the world: one grammar, three mastheads
|
|
127
|
+
|
|
128
|
+
**Shared by every treatment (built):** the panel is gone — no `--card` ground, no 20px radius, no `--shadow-card`. The rows are DESIGN.md's ledger rows: 1px `rule-soft` hairlines, 17px of vertical air, the header a `rule` hairline under mono labels in `--label-face`. Builders is set in the figure voice (Manrope 300, 22px, tabular); the project name at 17px/500; the relationship pill is a mono label on a hairline — it states a fact and is not pressable, so the accent left it (the One Warm Thing Rule, §5); the row's door is `open →`, lowercase `accent-deep` text with an underline (the footer-link grammar, 24px tall) in place of the ghost pill; a row's hover is its hairline taking ink, the band cells' grammar, not an accent tint; the status chip keeps its fixed vocabulary; the view title is the display voice (`every project, as rows`). The objects are the landing's alpha **cutouts in both modes** — the view wrap is a stacking context, so a black plate under `lighten` could not reach the page ground the way the hero's do, and a cutout needs no blend — with the world's one contact shadow in light and none in dark. The plate tokens (`--plate-*-cut`) joined cosmos's derived tier by root-absolute path; the mode mapping (`--mast-shadow`, `--mast-scrim`) is in both dark blocks.
|
|
129
|
+
|
|
130
|
+
Three mastheads, rendered dark and light at 1440 / 390 / 320 (ALL CLEAN) and measured:
|
|
131
|
+
|
|
132
|
+
| # | Masthead | Height 1440 / 390 | Honest risk |
|
|
133
|
+
|---|---|---|---|
|
|
134
|
+
| **T1 the ledger** | the title at the left, the set's small bead (the landing's `.o3` crop) at the right | 218 / 121 px | the least new information — a chrome object beside a word; also the quietest and the cheapest |
|
|
135
|
+
| **T2 the field** | the sweeping form (the landing's `.form` crop) crossing the masthead behind the title, its left edge masked, a black scrim under the title in dark | 300 / 150 px (+5px over the viewport at 1440) | the crop is cut flat by the wrap's right edge and the masthead's bottom: on black the bottom edge shows, on paper both read as a torn photograph — DESIGN.md's own warning about a cropped form; a pick needs a bottom mask and a right feather, and the title wraps to two lines at 14ch |
|
|
136
|
+
| **T3 the specimen** | the bongo pair (the hero object, whole) at the left, the title beside it, two leader-line callouts with the rows' own numbers (projects, builders) — the landing's hero grammar | 294 / 283 px (+360px of scroll at 390) | the most height on a phone; the figures are live code, and the builders figure summed the rows before the platform's own count had landed (13, not 26) — a pick wires it to refresh when `#selfBuilders` lands and pins it in `tests/projects_hub.mjs` |
|
|
137
|
+
|
|
138
|
+
**Recommendation: T1.** It carries the world's material into the view at the smallest cost, holds at 390 and 320 without an edge problem in either mode, and is the treatment the mine view and the wizard can repeat (a title and one object). The owner picked from the rendered screens, not from this table.
|
|
139
|
+
|
|
140
|
+
**The owner's pick (2026-08-28): T1, the ledger — with the title cut to two words.** "t1, but I dont want the ', as rows'": the view title is `every project`. The two unpicked mastheads, the `?tbl=` switch, the three render-round states and T3's figure writes left with the pick; `tests/projects_hub.mjs` pins the masthead, the ledger rules, the row's door and the absence of the switch.
|
|
141
|
+
|
|
142
|
+
### 9.5 What carries forward
|
|
143
|
+
|
|
144
|
+
- Task 1003301 (the poster card): the ledger grammar above is the card's facts strip, too.
|
|
145
|
+
- Task 1003319 (the planets): the masthead object rides the same crop maths the orbs will take.
|
|
146
|
+
- The mine view and the wizard are the next views to take a masthead in the picked treatment.
|
|
@@ -69,7 +69,7 @@ Then a state's own `expect` (a band open, a dialog present, a field's value, a c
|
|
|
69
69
|
}
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
Actions: `click`, `focus`, `press`, `fill`, `wait`, `clickAt x y`, `clickIfVisible`, `dispatchClick`, `check`, `back`, `forward`. Expectations: `expanded`, `dialog`, `visible[]`, `hidden[]`, `open`, `closed`, `activeId`, `activeText`, `expandedIds[]`, `param{}`, `attr[[sel,name,value]]`, `text[[sel,value]]`, `href[[sel,value]]`, `count[[sel,n]]`, `value[[sel,v]]`, `hasClass[[sel,class,bool]]`, `checked`, `noOverflow
|
|
72
|
+
Actions: `click`, `focus`, `press`, `fill`, `wait`, `clickAt x y`, `clickIfVisible`, `dispatchClick`, `check`, `back`, `forward`. Expectations: `expanded`, `dialog`, `visible[]`, `hidden[]`, `open`, `closed`, `activeId`, `activeText`, `expandedIds[]`, `param{}`, `attr[[sel,name,value]]`, `text[[sel,value]]`, `href[[sel,value]]`, `count[[sel,n]]`, `value[[sel,v]]`, `hasClass[[sel,class,bool]]`, `checked`, `noOverflow`, `top[[sel,px]]` (an element's viewport top — assert it closed, open a band, assert it again: the proof an overlay did not push the page). The kit validates the file before it opens a browser and names every problem.
|
|
73
73
|
|
|
74
74
|
The worked examples: `public-landing/projects.states.json` (the hub's thirteen), `public-landing/index.states.json` (the landing's four), `modules/hall-ui/public/ranks.states.json` (a second surface under its own prefix — it renders **red**, deliberately: the hall predates the 24px floor and Ranks has no `<h1>`, and the states file declares the shell's un-fixtured feeds rather than hiding the findings; idea 1000863 carries them).
|
|
75
75
|
|
|
@@ -123,7 +123,9 @@ async function runActions(page, actions = []) {
|
|
|
123
123
|
// A state may EXPECT (render.js) and a probe must EXPECT (probe.js). Selectors are
|
|
124
124
|
// evaluated in the page; scalars compared here. `open`/`visible` = present and not
|
|
125
125
|
// hidden; `closed`/`hidden` = absent or hidden.
|
|
126
|
-
|
|
126
|
+
// `top` pins an element's viewport top in px (rounded) — the probe that proves an overlay
|
|
127
|
+
// did not push the page (task 1003332): assert it closed, open it, assert it again.
|
|
128
|
+
const EXPECT_KEYS = Object.freeze(['expanded', 'dialog', 'visible', 'hidden', 'open', 'closed', 'activeId', 'activeText', 'expandedIds', 'param', 'attr', 'text', 'href', 'count', 'checked', 'value', 'hasClass', 'noOverflow', 'top']);
|
|
127
129
|
function validateExpect(expect, at) {
|
|
128
130
|
if (expect === undefined) return [];
|
|
129
131
|
if (!expect || typeof expect !== 'object' || Array.isArray(expect)) return [`${at}: an object`];
|
|
@@ -134,7 +136,7 @@ function validateExpect(expect, at) {
|
|
|
134
136
|
for (const k of ['expanded', 'dialog', 'noOverflow']) if (expect[k] !== undefined && typeof expect[k] !== 'boolean') errors.push(`${at}.${k}: a boolean`);
|
|
135
137
|
if (expect.expandedIds !== undefined && !Array.isArray(expect.expandedIds)) errors.push(`${at}.expandedIds: an array of ids`);
|
|
136
138
|
if (expect.param !== undefined && (typeof expect.param !== 'object' || Array.isArray(expect.param))) errors.push(`${at}.param: an object of name → value (null = absent)`);
|
|
137
|
-
for (const k of ['attr', 'text', 'href', 'count', 'value', 'hasClass']) if (expect[k] !== undefined && !(Array.isArray(expect[k]) && expect[k].every(Array.isArray))) errors.push(`${at}.${k}: an array of [selector, ...]`);
|
|
139
|
+
for (const k of ['attr', 'text', 'href', 'count', 'value', 'hasClass', 'top']) if (expect[k] !== undefined && !(Array.isArray(expect[k]) && expect[k].every(Array.isArray))) errors.push(`${at}.${k}: an array of [selector, ...]`);
|
|
138
140
|
return errors;
|
|
139
141
|
}
|
|
140
142
|
// Runs IN THE PAGE: collects the facts the expectations compare against, plus the
|
|
@@ -183,6 +185,7 @@ function factsInPage(spec) {
|
|
|
183
185
|
if (e.checked) { const el = q(e.checked); out.checked = el ? !!el.checked : null; }
|
|
184
186
|
if (e.value) out.value = e.value.map(([s]) => { const el = q(s); return el ? el.value : null; });
|
|
185
187
|
if (e.hasClass) out.hasClass = e.hasClass.map(([s, c]) => { const el = q(s); return el ? el.classList.contains(c) : null; });
|
|
188
|
+
if (e.top) out.top = e.top.map(([s]) => { const el = q(s); return el ? Math.round(el.getBoundingClientRect().top) : null; });
|
|
186
189
|
return out;
|
|
187
190
|
}
|
|
188
191
|
// Pure: compare collected facts against an expectation. Returns problem strings.
|
|
@@ -208,6 +211,7 @@ function expectProblems(facts, expect = {}) {
|
|
|
208
211
|
if (expect.checked !== undefined && facts.checked !== true) p.push(`${expect.checked} is not checked`);
|
|
209
212
|
(expect.value || []).forEach(([s, v], i) => { if (facts.value[i] !== v) p.push(`${s} value "${facts.value[i]}", expected "${v}"`); });
|
|
210
213
|
(expect.hasClass || []).forEach(([s, c, want = true], i) => { if (facts.hasClass[i] !== want) p.push(`${s} ${want ? 'lacks' : 'still has'} class "${c}"`); });
|
|
214
|
+
(expect.top || []).forEach(([s, v], i) => { if (facts.top[i] !== v) p.push(`${s} top ${facts.top[i]}px, expected ${v}px`); });
|
|
211
215
|
if (expect.noOverflow && facts.scrollWidth > facts.clientWidth + 1) p.push(`horizontal overflow ${facts.scrollWidth} > ${facts.clientWidth}`);
|
|
212
216
|
return p;
|
|
213
217
|
}
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.401",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.401",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.401",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
|
@@ -130,6 +130,8 @@
|
|
|
130
130
|
--label-face:var(--font-body);
|
|
131
131
|
--label-size:11.5px;
|
|
132
132
|
--label-space:.1em;
|
|
133
|
+
/* the view masthead's object (task 1003332): dark drops the contact shadow */
|
|
134
|
+
--mast-shadow:none;
|
|
133
135
|
color-scheme:dark;
|
|
134
136
|
}
|
|
135
137
|
@media (prefers-color-scheme: dark){
|
|
@@ -165,6 +167,8 @@
|
|
|
165
167
|
--label-face:var(--font-body);
|
|
166
168
|
--label-size:11.5px;
|
|
167
169
|
--label-space:.1em;
|
|
170
|
+
/* the view masthead's object (task 1003332): dark drops the contact shadow */
|
|
171
|
+
--mast-shadow:none;
|
|
168
172
|
color-scheme:dark;
|
|
169
173
|
}
|
|
170
174
|
}
|
|
@@ -246,6 +250,15 @@
|
|
|
246
250
|
--radius:16px; --radius-sm:10px; --radius-pill:999px;
|
|
247
251
|
--top-h:64px;
|
|
248
252
|
--gutter:clamp(16px,4vw,34px);
|
|
253
|
+
/* the world's object for the hub's view masthead (task 1003332): the apex
|
|
254
|
+
shares the landing's plates because it is the same world (DESIGN.md
|
|
255
|
+
"Materials"); the hub takes the alpha CUTOUT in both modes — the view
|
|
256
|
+
wraps are stacking contexts, so a black plate under `lighten` could not
|
|
257
|
+
reach the page ground the way the hero's do, and a cutout needs no blend.
|
|
258
|
+
Root-absolute path: a url() in a custom property resolves against the
|
|
259
|
+
DOCUMENT. Light gives the object the world's one contact shadow. */
|
|
260
|
+
--plate-set-cut:url(/assets/world/r2-chrome-blobs-set-cut.webp);
|
|
261
|
+
--mast-shadow:drop-shadow(0 26px 30px color-mix(in srgb,var(--ink) 20%,transparent));
|
|
249
262
|
/* the footer's measured height per width — the sky is 100vh minus the bar and
|
|
250
263
|
this, so the map fits the viewport with no scrollbar (T2's rule); the
|
|
251
264
|
toolbar row that used to be in that sum is gone (task 1003300) */
|
|
@@ -255,8 +268,13 @@
|
|
|
255
268
|
@media (max-width:900px){
|
|
256
269
|
:root{--top-h:60px;--foot-h:108px;}
|
|
257
270
|
}
|
|
258
|
-
|
|
259
|
-
|
|
271
|
+
/* with About + Docs in the row (task 1003332) the six links wrap to a second
|
|
272
|
+
row under ~420px, and the sentence takes a third line under ~340px — measured */
|
|
273
|
+
@media (max-width:420px){
|
|
274
|
+
:root{--foot-h:136px;}
|
|
275
|
+
}
|
|
276
|
+
@media (max-width:340px){
|
|
277
|
+
:root{--foot-h:154px;}
|
|
260
278
|
}
|
|
261
279
|
|
|
262
280
|
*{box-sizing:border-box;margin:0;padding:0;}
|
|
@@ -413,7 +431,7 @@ a.orb{cursor:pointer;}
|
|
|
413
431
|
.foot a:hover{text-decoration:underline;}
|
|
414
432
|
/* the footer doors (task 1003251): privacy · terms · contact on one row under the
|
|
415
433
|
line, on every landing surface — the same link ink, the current page underlined */
|
|
416
|
-
.foot .footNav{display:flex;justify-content:center;gap:16px;margin-top:8px;}
|
|
434
|
+
.foot .footNav{display:flex;flex-wrap:wrap;justify-content:center;gap:4px 16px;margin-top:8px;}
|
|
417
435
|
.foot .footNav a[aria-current="page"]{text-decoration:underline;}
|
|
418
436
|
|
|
419
437
|
/* ── progress strips: one visual, per-flow vocabularies (direction §4).
|
|
@@ -611,13 +629,17 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
|
|
|
611
629
|
.switch:has(input:checked){color:var(--ink);}
|
|
612
630
|
|
|
613
631
|
/* ── THE BANDS: a menu is not a floating card. It unfolds under the bar's edge,
|
|
614
|
-
full width on the card ground, closed by one hairline,
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
.
|
|
632
|
+
full width on the card ground, closed by one hairline, as a LAYER OVER the
|
|
633
|
+
page: the page does not reflow (the owner's correction, task 1003332 — the
|
|
634
|
+
shipped bands pushed the page down). Absolute against the document, top at
|
|
635
|
+
the bar's height, so the sky, the table and the footer keep their place; the
|
|
636
|
+
bar (50) stays above it, the card scrim (60) above both. Cells in a
|
|
637
|
+
hairline-separated row, each a lowercase display title over one clause; the
|
|
638
|
+
whole cell is the target. The current view carries a 2px accent hairline on
|
|
639
|
+
its top edge — the rail-step-lit grammar from DESIGN.md, moved onto a menu.
|
|
640
|
+
One authored move, a 6px rise + fade on the world's exponential ease-out,
|
|
641
|
+
dead under the kill switch at the end of this file. ── */
|
|
642
|
+
.menuBand{position:absolute;left:0;right:0;top:var(--top-h);z-index:49;background:var(--bg-card);border-bottom:1px solid var(--rule);
|
|
621
643
|
animation:bandIn .22s cubic-bezier(.16,1,.3,1) both;}
|
|
622
644
|
@keyframes bandIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
|
|
623
645
|
.bandIn{padding:20px var(--gutter) 28px;}
|
|
@@ -642,9 +664,6 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
|
|
|
642
664
|
/* the deferred Settings slot: a place it would go, rendering nothing at all —
|
|
643
665
|
not even the hairline that declares a list item in this band */
|
|
644
666
|
.bandSlot{border:0;}
|
|
645
|
-
/* the row under the hairline: About and Docs, a rung smaller than the views */
|
|
646
|
-
.bandMore{margin-top:18px;}
|
|
647
|
-
.bandMore .bandT{font-size:17px;font-weight:400;min-height:24px;display:inline-flex;align-items:center;}
|
|
648
667
|
|
|
649
668
|
@media (max-width:900px){
|
|
650
669
|
.bar{gap:10px;padding:0 12px;}
|
|
@@ -766,35 +785,63 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
|
|
|
766
785
|
.hintbar kbd{font-family:var(--font-mono);background:color-mix(in srgb,var(--accent) 24%,transparent);
|
|
767
786
|
border-radius:5px;padding:1px 6px;font-size:11px;color:var(--chrome-accent);}
|
|
768
787
|
|
|
769
|
-
/* ──
|
|
770
|
-
|
|
771
|
-
.
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
788
|
+
/* ── THE TABLE IN THE WORLD (task 1003332; owner's review of the shipped chrome).
|
|
789
|
+
The table is a VIEW of the same world as the sky, not a panel beside it: a
|
|
790
|
+
masthead in the world's material, then LEDGER ROWS (DESIGN.md "Ledger rows")
|
|
791
|
+
— hairlines, no ground, no radius, no shadow; mono labels on the columns;
|
|
792
|
+
the figure voice on the numbers; the accent only on what is pressable (the
|
|
793
|
+
open link) or live (the status chip); the display voice on the view title.
|
|
794
|
+
The relationship pill states a fact and is not pressable, so it lost the
|
|
795
|
+
accent (the One Warm Thing Rule); a row's hover is the hairline taking ink,
|
|
796
|
+
the bands' grammar. The masthead is the owner's pick from three rendered
|
|
797
|
+
treatments (docs/design/projects-hub-direction-v2.md §9): "the ledger" —
|
|
798
|
+
the view title in the display voice at the left, one chrome object at the
|
|
799
|
+
right, nothing else. ── */
|
|
800
|
+
.tblMast{display:grid;grid-template-columns:1fr auto;position:relative;align-items:end;gap:26px;padding:clamp(26px,3.6vw,44px) 0 30px;}
|
|
801
|
+
.tblTitle{font-family:var(--font-display);font-weight:300;font-size:clamp(30px,3.6vw,48px);line-height:1;
|
|
802
|
+
letter-spacing:-.035em;text-transform:lowercase;color:var(--ink);text-shadow:var(--type-halo);margin:0;}
|
|
803
|
+
/* the object, on the world's crop maths (DESIGN.md "The crop maths"): one
|
|
804
|
+
rectangle of a plate, expressed against the object's own width so it scales
|
|
805
|
+
with the row — the set's small bead, r2-chrome-blobs-set u[.810,.955] v[.556,.840] */
|
|
806
|
+
.mastObj{display:block;--dia:clamp(96px,10vw,132px);width:var(--dia);aspect-ratio:.91476;background-image:var(--plate-set-cut);
|
|
807
|
+
background-repeat:no-repeat;background-size:calc(var(--dia) * 6.89655) auto;
|
|
808
|
+
background-position:calc(var(--dia) * -5.58621) calc(var(--dia) * -2.14014);filter:var(--mast-shadow);}
|
|
809
|
+
|
|
810
|
+
.tbl{width:100%;border-collapse:collapse;background:none;}
|
|
811
|
+
.tbl th{text-align:left;font-family:var(--label-face);font-size:var(--label-size);font-weight:400;
|
|
812
|
+
letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);padding:0 14px 12px;
|
|
813
|
+
border-bottom:1px solid var(--rule);white-space:nowrap;}
|
|
814
|
+
.tbl th:first-child,.tbl td:first-child{padding-left:0;}
|
|
815
|
+
.tbl th:last-child,.tbl td:last-child{padding-right:0;}
|
|
776
816
|
/* the sort control is a real button so the keyboard can reach it; it must look
|
|
777
817
|
like the header it replaced, so it inherits everything the th declares. */
|
|
778
818
|
.tbl th button{all:unset;cursor:pointer;}
|
|
779
819
|
.tbl th button:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
|
|
780
|
-
.tbl td{padding:
|
|
781
|
-
color:var(--ink-soft);vertical-align:middle;}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
/* the whole row opens the project card, so it must look like it does */
|
|
820
|
+
.tbl td{padding:17px 14px;border-bottom:1px solid var(--rule-soft);font-size:15px;font-weight:400;
|
|
821
|
+
color:var(--ink-soft);vertical-align:middle;transition:border-color .2s cubic-bezier(.2,.7,.3,1);}
|
|
822
|
+
/* the whole row opens the project card, so it must look like it does: the
|
|
823
|
+
hairline under it takes ink, as a band cell's does */
|
|
785
824
|
.tbl tbody tr{cursor:pointer;}
|
|
786
|
-
.tbl
|
|
787
|
-
.tbl .
|
|
788
|
-
|
|
789
|
-
.tbl .ptitle{font-family:var(--font-display);font-weight:
|
|
825
|
+
.tbl tbody tr:hover td{border-bottom-color:var(--ink-faint);}
|
|
826
|
+
.tbl .pname{display:flex;align-items:center;gap:12px;}
|
|
827
|
+
.tbl .pdot{width:10px;height:10px;border-radius:50%;background:var(--acc);flex:0 0 auto;}
|
|
828
|
+
.tbl .ptitle{font-family:var(--font-display);font-weight:500;font-size:17px;letter-spacing:-.015em;color:var(--ink);text-decoration:none;}
|
|
790
829
|
.tbl a.ptitle:hover{text-decoration:underline;}
|
|
791
|
-
.tbl .ptag{font-size:
|
|
792
|
-
.tbl .num{font-family:var(--font-
|
|
830
|
+
.tbl .ptag{font-size:13.5px;color:var(--ink-soft);font-weight:400;}
|
|
831
|
+
.tbl .num{font-family:var(--font-display);font-weight:300;font-size:22px;letter-spacing:-.02em;color:var(--ink);
|
|
832
|
+
font-variant-numeric:tabular-nums;}
|
|
793
833
|
.tbl .tags{display:flex;gap:6px;flex-wrap:wrap;}
|
|
794
834
|
.tbl .tags span{font-family:var(--font-mono);font-size:10.5px;padding:2px 8px;border-radius:999px;
|
|
795
|
-
border:1px solid var(--
|
|
796
|
-
.tbl .pill{display:inline-block;font-family:var(--
|
|
797
|
-
border-radius:999px;
|
|
835
|
+
border:1px solid var(--rule);color:var(--ink-faint);white-space:nowrap;}
|
|
836
|
+
.tbl .pill{display:inline-block;font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);
|
|
837
|
+
text-transform:uppercase;padding:3px 9px;border-radius:999px;border:1px solid var(--rule);color:var(--ink-faint);}
|
|
838
|
+
/* the row's door: the accent on the one pressable thing in the row, as text
|
|
839
|
+
(the footer-link grammar), lowercase like every control in the world */
|
|
840
|
+
.rowGo{display:inline-flex;align-items:center;min-height:24px;padding:3px 0;font-family:var(--font-body);font-size:15px;
|
|
841
|
+
text-transform:lowercase;color:var(--accent-deep);text-decoration:underline;text-underline-offset:4px;
|
|
842
|
+
text-decoration-color:color-mix(in srgb,var(--accent) 55%,transparent);white-space:nowrap;
|
|
843
|
+
transition:text-decoration-color .2s cubic-bezier(.2,.7,.3,1);}
|
|
844
|
+
.rowGo:hover{text-decoration-color:var(--accent-deep);}
|
|
798
845
|
.tbl td.right{text-align:right;}
|
|
799
846
|
/* Nothing in an action or status cell may wrap: "Manage →" breaking after the
|
|
800
847
|
space and the chip's recency dropping to a second line both read as a broken
|
|
@@ -807,8 +854,14 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
|
|
|
807
854
|
.tbl .colType{width:1%;white-space:nowrap;}
|
|
808
855
|
/* the declared-type tag (task 1002772) — its own vocabulary: not the relationship
|
|
809
856
|
.pill, not the liveness .chip. Two different facts never wear the same chrome. */
|
|
810
|
-
.typeTag{font-family:var(--font-mono);font-size:10.5px;font-weight:500;color:var(--ink-soft);border:1px solid var(--
|
|
857
|
+
.typeTag{font-family:var(--font-mono);font-size:10.5px;font-weight:500;color:var(--ink-soft);border:1px solid var(--rule);border-radius:999px;padding:2px 9px;white-space:nowrap;}
|
|
811
858
|
@media (max-width:780px){.tbl .colTags,.tbl .colType{display:none;}}
|
|
859
|
+
@media (max-width:900px){
|
|
860
|
+
.tblMast{gap:16px;padding:22px 0 20px;}
|
|
861
|
+
.tblTitle{font-size:clamp(28px,7.4vw,34px);}
|
|
862
|
+
.mastObj{--dia:clamp(72px,18vw,96px);}
|
|
863
|
+
.tbl th,.tbl td{padding-left:10px;padding-right:10px;}
|
|
864
|
+
}
|
|
812
865
|
|
|
813
866
|
/* ── the living sky (task 1002762): camera, spotlight, hover card ──
|
|
814
867
|
The camera is ONE transform on .skyCam; orbs carry only their own physics
|
|
@@ -191,10 +191,11 @@ main:focus{outline:none;box-shadow:none}
|
|
|
191
191
|
@media (prefers-color-scheme:dark){:root:not([data-mode="light"]) .sun{display:block}
|
|
192
192
|
:root:not([data-mode="light"]) .moon{display:none}}
|
|
193
193
|
|
|
194
|
-
/* the menu bands (.menuBand — .band is this page's content sections): not floating cards. Full width on the card ground, closed by one hairline,
|
|
195
|
-
the page
|
|
196
|
-
|
|
197
|
-
.
|
|
194
|
+
/* the menu bands (.menuBand — .band is this page's content sections): not floating cards. Full width on the card ground, closed by one hairline, a LAYER
|
|
195
|
+
over the page under the bar — the page does not reflow (owner, 2026-08-28; task 1003332). Cells in a
|
|
196
|
+
hairline-separated row, a lowercase display title over one clause; the whole cell is the target.
|
|
197
|
+
One authored move, dead under world.css's kill switch. */
|
|
198
|
+
.menuBand{position:absolute;left:0;right:0;top:var(--top-h);z-index:49;background:var(--bg-card);border-bottom:1px solid var(--rule);
|
|
198
199
|
animation:bandIn .22s cubic-bezier(.16,1,.3,1) both}
|
|
199
200
|
@keyframes bandIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
|
|
200
201
|
.bandIn{padding:20px 26px 28px}
|
|
@@ -207,8 +208,6 @@ main:focus{outline:none;box-shadow:none}
|
|
|
207
208
|
.bandCell:hover .bandT{color:var(--ink)}
|
|
208
209
|
.bandCell:hover{border-top-color:var(--ink-faint)}
|
|
209
210
|
.bandC{display:block;margin-top:5px;font-size:13.5px;line-height:1.45;color:var(--ink-soft)}
|
|
210
|
-
.bandMore{margin-top:18px}
|
|
211
|
-
.bandMore .bandT{font-size:17px;font-weight:400;min-height:24px;display:inline-flex;align-items:center}
|
|
212
211
|
.bandProfile{display:flex;align-items:flex-end;justify-content:space-between;gap:34px;flex-wrap:wrap}
|
|
213
212
|
.bandWho{display:flex;align-items:center;gap:10px;padding-top:15px;border-top:1px solid var(--rule-soft);
|
|
214
213
|
flex:0 1 auto;font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);
|
|
@@ -843,9 +842,10 @@ composition A; landing composition v3, picked by the owner 2026-08-27. No roll,
|
|
|
843
842
|
</header>
|
|
844
843
|
|
|
845
844
|
<!-- the two bands: full-width, on the card ground, closed by one hairline; they unfold under the
|
|
846
|
-
bar's edge
|
|
847
|
-
foot of the page): Escape closes and returns focus
|
|
848
|
-
Tab out closes, a click outside closes, opening one
|
|
845
|
+
bar's edge as a layer over the page, which does not reflow (task 1003332). One disclosure
|
|
846
|
+
component, two instances (the script at the foot of the page): Escape closes and returns focus
|
|
847
|
+
to the trigger, the arrows walk the items, Tab out closes, a click outside closes, opening one
|
|
848
|
+
closes the other. -->
|
|
849
849
|
<div class="menuBand" id="menuProjects" data-menu="projects" hidden>
|
|
850
850
|
<div class="bandIn">
|
|
851
851
|
<ul class="bandRow">
|
|
@@ -854,12 +854,8 @@ composition A; landing composition v3, picked by the owner 2026-08-27. No roll,
|
|
|
854
854
|
<li class="bandCell" id="mineCell" hidden><a class="bandT" href="/projects?view=mine">Your projects</a><span class="bandC">the ones you own or build on</span></li>
|
|
855
855
|
<li class="bandCell"><a class="bandT" href="/projects?view=new">New project</a><span class="bandC">five questions and a home</span></li>
|
|
856
856
|
</ul>
|
|
857
|
-
<!--
|
|
858
|
-
|
|
859
|
-
<ul class="bandRow bandMore">
|
|
860
|
-
<li class="bandCell"><a class="bandT" href="#about">About</a></li>
|
|
861
|
-
<li class="bandCell"><a class="bandT" href="/docs">Docs</a></li>
|
|
862
|
-
</ul>
|
|
857
|
+
<!-- About and Docs are site pages, not project views: they live in the footer row with
|
|
858
|
+
Privacy / Terms / Contact (owner, 2026-08-28; task 1003332). -->
|
|
863
859
|
</div>
|
|
864
860
|
</div>
|
|
865
861
|
<div class="menuBand" id="menuProfile" data-menu="profile" hidden>
|
|
@@ -1096,6 +1092,8 @@ composition A; landing composition v3, picked by the owner 2026-08-27. No roll,
|
|
|
1096
1092
|
<footer>
|
|
1097
1093
|
<div class="footrow">
|
|
1098
1094
|
<p><!--apex-only:start-->A non-profit, capture-resistant commons. <!--apex-only:end-->Built by agents, on Cloud Bongos. <a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank" rel="noopener">Open source (AGPL-3.0)</a>.</p>
|
|
1095
|
+
<a href="#about">About</a>
|
|
1096
|
+
<a href="/docs">Docs</a>
|
|
1099
1097
|
<a href="/privacy">Privacy</a>
|
|
1100
1098
|
<a href="/terms">Terms</a>
|
|
1101
1099
|
<a href="/contact">Contact</a>
|
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
"page": "/",
|
|
4
4
|
"surface": "public-landing",
|
|
5
5
|
"probes": [
|
|
6
|
-
{ "name": "landing:
|
|
6
|
+
{ "name": "landing closed: the main content starts under the bar", "auth": true, "width": 1440,
|
|
7
|
+
"steps": [],
|
|
8
|
+
"expect": { "expanded": false, "top": [["#main", 72]] } },
|
|
9
|
+
{ "name": "landing: Enter opens Projects on the first item; the band overlays and the hero does not move (task 1003332)", "continue": true,
|
|
7
10
|
"steps": [["focus", "#projTrig"], ["press", "Enter"], ["wait", 150]],
|
|
8
|
-
"expect": { "open": "#menuProjects", "activeText": "Sky" } },
|
|
11
|
+
"expect": { "open": "#menuProjects", "activeText": "Sky", "top": [["#main", 72]] } },
|
|
9
12
|
{ "name": "landing: arrows walk the visible items (Your projects shows signed in)", "continue": true,
|
|
10
13
|
"steps": [["press", "ArrowDown"], ["press", "ArrowDown"]],
|
|
11
14
|
"expect": { "activeText": "Your projects" } },
|
|
@@ -14,16 +17,16 @@
|
|
|
14
17
|
"expect": { "closed": "#menuProjects", "activeId": "projTrig" } },
|
|
15
18
|
{ "name": "landing: the profile band closes the Projects band", "continue": true,
|
|
16
19
|
"steps": [["click", "#projTrig"], ["wait", 120], ["click", "#who .trig"], ["wait", 120]],
|
|
17
|
-
"expect": { "open": "#menuProfile", "closed": "#menuProjects" } },
|
|
20
|
+
"expect": { "open": "#menuProfile", "closed": "#menuProjects", "top": [["#main", 72]] } },
|
|
18
21
|
{ "name": "landing: the profile band names the person; sign out keeps the honest href", "continue": true,
|
|
19
22
|
"steps": [],
|
|
20
23
|
"expect": { "href": [["#menuProfile a.signout", "/api/bongos/auth/logout"]], "text": [["#bandWho", "builder"]], "count": [["#bandWho img", 1]] } },
|
|
21
24
|
{ "name": "landing: a click outside closes", "continue": true,
|
|
22
25
|
"steps": [["clickAt", 700, 700], ["wait", 120]],
|
|
23
26
|
"expect": { "closed": "#menuProfile", "expanded": false } },
|
|
24
|
-
{ "name": "landing: the band deep-links the hub views
|
|
27
|
+
{ "name": "landing: the band deep-links the hub views; About and Docs are footer links (task 1003332)", "continue": true,
|
|
25
28
|
"steps": [["click", "#projTrig"], ["wait", 120]],
|
|
26
|
-
"expect": { "count": [["#menuProjects a",
|
|
29
|
+
"expect": { "count": [["#menuProjects a", 4], ["#menuProjects a[href=\"/docs\"]", 0]], "href": [["#menuProjects .bandCell:nth-child(1) a", "/projects?view=map"], ["#menuProjects .bandCell:nth-child(2) a", "/projects?view=map&sub=table"], ["footer a[href=\"#about\"]", "#about"], ["footer a[href=\"/docs\"]", "/docs"]] } },
|
|
27
30
|
{ "name": "landing: #about exists", "continue": true,
|
|
28
31
|
"steps": [["press", "Escape"]],
|
|
29
32
|
"expect": { "count": [["#about", 1]] } },
|
|
@@ -418,9 +418,10 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
418
418
|
</header>
|
|
419
419
|
|
|
420
420
|
<!-- ══ THE BANDS ══ The menus are not floating cards. Each is a full-width band
|
|
421
|
-
that unfolds under the bar's edge
|
|
422
|
-
|
|
423
|
-
|
|
421
|
+
that unfolds under the bar's edge as a layer OVER the page — the page does
|
|
422
|
+
not reflow (owner, 2026-08-28; task 1003332) — so a destination is a place
|
|
423
|
+
that opens under the bar rather than a list that hovers beside it. One
|
|
424
|
+
component, two instances (see the bands block in the script):
|
|
424
425
|
Escape closes and returns focus to the trigger, the arrows walk the items,
|
|
425
426
|
a click outside closes, opening one closes the other. Plain links in a
|
|
426
427
|
disclosure (aria-expanded + aria-controls, no menu role), so what is
|
|
@@ -435,12 +436,8 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
435
436
|
<li class="bandCell"><a class="bandT" href="?view=mine" data-nav="mine">Your projects</a><span class="bandC">the ones you own or build on</span></li>
|
|
436
437
|
<li class="bandCell"><a class="bandT" href="?view=new" data-nav="new">New project</a><span class="bandC">five questions and a home</span></li>
|
|
437
438
|
</ul>
|
|
438
|
-
<!--
|
|
439
|
-
|
|
440
|
-
<ul class="bandRow bandMore">
|
|
441
|
-
<li class="bandCell"><a class="bandT" href="/#about">About</a></li>
|
|
442
|
-
<li class="bandCell"><a class="bandT" href="/docs">Docs</a></li>
|
|
443
|
-
</ul>
|
|
439
|
+
<!-- About and Docs are site pages, not project views: they live in the
|
|
440
|
+
footer row with Privacy / Terms / Contact (owner, 2026-08-28; task 1003332). -->
|
|
444
441
|
</div>
|
|
445
442
|
</div>
|
|
446
443
|
<div class="menuBand" id="menuProfile" data-menu="profile" hidden>
|
|
@@ -508,6 +505,15 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
508
505
|
</div>
|
|
509
506
|
|
|
510
507
|
<div class="wrap viewWrap" id="sub-table-body" hidden>
|
|
508
|
+
<!-- ══ THE TABLE IN THE WORLD (task 1003332) ══ The table is a view of the same
|
|
509
|
+
world as the sky: a masthead in the world's material — the view title in
|
|
510
|
+
the display voice and one chrome object — then ledger rows. The owner's
|
|
511
|
+
pick from three rendered treatments (docs/design/projects-hub-direction-v2.md
|
|
512
|
+
§9): "the ledger", with the title cut to two words. -->
|
|
513
|
+
<div class="tblMast">
|
|
514
|
+
<h2 class="tblTitle">every project</h2>
|
|
515
|
+
<span class="mastObj" aria-hidden="true"></span>
|
|
516
|
+
</div>
|
|
511
517
|
<table class="tbl">
|
|
512
518
|
<thead>
|
|
513
519
|
<tr>
|
|
@@ -533,7 +539,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
533
539
|
<td class="right num" id="selfBuilders">—</td>
|
|
534
540
|
<td class="colTags" id="selfTags">—</td>
|
|
535
541
|
<td class="right colStatus"><span class="chip calm"><span class="cdot"></span>—</span></td>
|
|
536
|
-
<td class="colGo"><a class="
|
|
542
|
+
<td class="colGo"><a class="rowGo" href="/">Open →</a></td>
|
|
537
543
|
</tr>
|
|
538
544
|
<!--apex-only:end-->
|
|
539
545
|
</tbody>
|
|
@@ -1070,7 +1076,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1070
1076
|
|
|
1071
1077
|
</main>
|
|
1072
1078
|
|
|
1073
|
-
<footer class="foot"><!--apex-only:start--><span>A non-profit, capture-resistant commons. </span><!--apex-only:end-->Built by agents, on <span data-brand-product-inline>Cloud Bongos</span>. <a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank" rel="noopener">Open source (AGPL-3.0)</a>.<nav class="footNav" aria-label="Site"><a href="/privacy">Privacy</a><a href="/terms">Terms</a><a href="/contact">Contact</a><!--apex-only:start--><a data-link-hall href="{{buildersOrigin}}">Builders' hall</a><!--apex-only:end--></nav></footer>
|
|
1079
|
+
<footer class="foot"><!--apex-only:start--><span>A non-profit, capture-resistant commons. </span><!--apex-only:end-->Built by agents, on <span data-brand-product-inline>Cloud Bongos</span>. <a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank" rel="noopener">Open source (AGPL-3.0)</a>.<nav class="footNav" aria-label="Site"><a href="/#about">About</a><a href="/docs">Docs</a><a href="/privacy">Privacy</a><a href="/terms">Terms</a><a href="/contact">Contact</a><!--apex-only:start--><a data-link-hall href="{{buildersOrigin}}">Builders' hall</a><!--apex-only:end--></nav></footer>
|
|
1074
1080
|
|
|
1075
1081
|
<script>
|
|
1076
1082
|
/* Brand-pack fill (R57): the server injects window.__BRANDING__ ahead of this
|
|
@@ -1485,7 +1491,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1485
1491
|
'<td class="right colStatus">' + (p._inst ? chipFor(p._inst)
|
|
1486
1492
|
: '<span class="chip calm"><span class="cdot"></span>—</span>') + '</td>' +
|
|
1487
1493
|
'<td class="colGo">' + (safeHttpUrl(p.origin)
|
|
1488
|
-
? '<a class="
|
|
1494
|
+
? '<a class="rowGo" href="' + esc(safeHttpUrl(p.origin)) + '" target="_blank" rel="noopener">Open →</a>'
|
|
1489
1495
|
: '') + '</td>' +
|
|
1490
1496
|
'</tr>';
|
|
1491
1497
|
}).join(''));
|
|
@@ -5543,10 +5549,14 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5543
5549
|
/* Boot. The view is set FIRST, from the URL, so the page is navigable before
|
|
5544
5550
|
any request resolves — /projects?view=new must land on the create view even
|
|
5545
5551
|
if the identity call is slow or fails. */
|
|
5552
|
+
/* the boot query is read ONCE, before the view is set: setView rewrites the
|
|
5553
|
+
URL to ?view=<v> and would drop everything else (the Table deep link from
|
|
5554
|
+
the landing landed on the sky until task 1003332) */
|
|
5555
|
+
var bootQ = new URLSearchParams(location.search);
|
|
5546
5556
|
setView(viewFromUrl());
|
|
5547
5557
|
/* the Table item's deep link (and the landing's) names the sub-view; a view change
|
|
5548
5558
|
never writes it back, so a reload from the band returns to the sky as before */
|
|
5549
|
-
if (
|
|
5559
|
+
if (bootQ.get('sub') === 'table') setSub('table');
|
|
5550
5560
|
|
|
5551
5561
|
fetch(API + '/me', { credentials: 'same-origin' })
|
|
5552
5562
|
.then(function (res) { if (!res.ok) throw new Error(String(res.status)); return res.json(); })
|
|
@@ -3,26 +3,29 @@
|
|
|
3
3
|
"page": "/projects",
|
|
4
4
|
"surface": "public-landing",
|
|
5
5
|
"probes": [
|
|
6
|
-
{ "name": "
|
|
6
|
+
{ "name": "closed: the main content starts under the bar", "auth": true, "width": 1440,
|
|
7
|
+
"steps": [],
|
|
8
|
+
"expect": { "expanded": false, "top": [["#hubMain", 64]] } },
|
|
9
|
+
{ "name": "Enter opens Projects and lands on the first item; the band overlays and the content does not move (task 1003332)", "continue": true,
|
|
7
10
|
"steps": [["focus", "#projTrig"], ["press", "Enter"], ["wait", 150]],
|
|
8
|
-
"expect": { "open": "#menuProjects", "activeText": "Sky" } },
|
|
11
|
+
"expect": { "open": "#menuProjects", "activeText": "Sky", "top": [["#hubMain", 64]] } },
|
|
9
12
|
{ "name": "ArrowDown walks to Table", "continue": true,
|
|
10
13
|
"steps": [["press", "ArrowDown"]],
|
|
11
14
|
"expect": { "activeText": "Table" } },
|
|
12
|
-
{ "name": "ArrowUp wraps to the last item (
|
|
15
|
+
{ "name": "ArrowUp wraps to the last item (New project; About and Docs are footer links, task 1003332)", "continue": true,
|
|
13
16
|
"steps": [["press", "ArrowUp"], ["press", "ArrowUp"]],
|
|
14
|
-
"expect": { "activeText": "
|
|
17
|
+
"expect": { "activeText": "New project" } },
|
|
15
18
|
{ "name": "Escape closes and returns focus to the trigger", "continue": true,
|
|
16
19
|
"steps": [["press", "Escape"], ["wait", 100]],
|
|
17
20
|
"expect": { "closed": "#menuProjects", "activeId": "projTrig", "expanded": false } },
|
|
18
21
|
{ "name": "opening the profile band closes the Projects band", "continue": true,
|
|
19
22
|
"steps": [["click", "#projTrig"], ["wait", 120], ["click", "#who"], ["wait", 120]],
|
|
20
|
-
"expect": { "open": "#menuProfile", "closed": "#menuProjects", "expandedIds": ["who"] } },
|
|
23
|
+
"expect": { "open": "#menuProfile", "closed": "#menuProjects", "expandedIds": ["who"], "top": [["#hubMain", 64]] } },
|
|
21
24
|
{ "name": "a click outside closes", "continue": true,
|
|
22
25
|
"steps": [["clickAt", 700, 600], ["wait", 120]],
|
|
23
26
|
"expect": { "closed": "#menuProfile", "expanded": false } },
|
|
24
27
|
{ "name": "Tab out of the band closes it", "continue": true,
|
|
25
|
-
"steps": [["click", "#projTrig"], ["wait", 120], ["focus", "#menuProjects a[
|
|
28
|
+
"steps": [["click", "#projTrig"], ["wait", 120], ["focus", "#menuProjects a[data-nav=\"new\"]"], ["press", "Tab"], ["wait", 120]],
|
|
26
29
|
"expect": { "closed": "#menuProjects" } },
|
|
27
30
|
{ "name": "Table from the band: the table on stage, Table current, band closed", "continue": true,
|
|
28
31
|
"steps": [["click", "#projTrig"], ["wait", 120], ["click", "a[data-sub=\"table\"]"], ["wait", 300]],
|
|
@@ -54,12 +57,16 @@
|
|
|
54
57
|
{ "name": "the mode toggle: the label says what the press does, and the press does it", "continue": true,
|
|
55
58
|
"steps": [["clickAt", 700, 600], ["click", "#modeToggle"], ["wait", 100]],
|
|
56
59
|
"expect": { "attr": [["#modeToggle", "aria-label", "Switch to light mode"], ["html", "data-mode", "dark"]] } },
|
|
60
|
+
{ "name": "the Table deep link (the landing's band item) lands on the table, Table current (task 1003332)", "auth": true, "width": 1440, "url": "/projects?view=map&sub=table",
|
|
61
|
+
"steps": [["wait", 300]],
|
|
62
|
+
"expect": { "visible": ["#sub-table-body", ".tblMast"], "hidden": ["#sub-sky-body"], "text": [["[aria-current=\"page\"]", "Table"], [".tblTitle", "every project"]] } },
|
|
57
63
|
{ "name": "signed out: no chip, the door shows, no switch, the search stays", "auth": false, "width": 1440,
|
|
58
64
|
"steps": [],
|
|
59
65
|
"expect": { "hidden": ["#who", ".switch"], "visible": ["#signinTop", "#qWrap"] } },
|
|
60
|
-
{ "name": "signed out the Projects band is Sky / Table / New project
|
|
66
|
+
{ "name": "signed out the Projects band is Sky / Table / New project (no Your projects); About and Docs are in the footer row", "continue": true,
|
|
61
67
|
"steps": [["click", "#projTrig"], ["wait", 120]],
|
|
62
|
-
"expect": { "count": [["#menuProjects .bandCell:not([hidden])",
|
|
68
|
+
"expect": { "count": [["#menuProjects .bandCell:not([hidden])", 3], ["#menuProjects a[href=\"/docs\"]", 0]], "hidden": ["#menuProjects [data-nav=\"mine\"]"],
|
|
69
|
+
"href": [[".footNav a[href=\"/#about\"]", "/#about"], [".footNav a[href=\"/docs\"]", "/docs"]] } },
|
|
63
70
|
{ "name": "signed out: the card still closes on Escape (nothing throws with no session)", "continue": true,
|
|
64
71
|
"steps": [["press", "Escape"], ["wait", 100], ["dispatchClick", "#orbField a.worldOrb:not(#selfOrb)"], ["wait", 400], ["press", "Escape"], ["wait", 150]],
|
|
65
72
|
"expect": { "dialog": false, "closed": "#menuProjects" } },
|
|
@@ -69,9 +76,9 @@
|
|
|
69
76
|
{ "name": "390: Escape folds the row and returns focus to the magnifier", "continue": true,
|
|
70
77
|
"steps": [["press", "Escape"], ["wait", 100]],
|
|
71
78
|
"expect": { "activeId": "qToggle", "hasClass": [["#qWrap", "is-open", false]] } },
|
|
72
|
-
{ "name": "390: an opening band folds the search", "continue": true,
|
|
79
|
+
{ "name": "390: an opening band folds the search and overlays the sky (the content does not move)", "continue": true,
|
|
73
80
|
"steps": [["click", "#qToggle"], ["wait", 100], ["click", "#projTrig"], ["wait", 150]],
|
|
74
|
-
"expect": { "hasClass": [["#qWrap", "is-open", false]], "open": "#menuProjects" } },
|
|
81
|
+
"expect": { "hasClass": [["#qWrap", "is-open", false]], "open": "#menuProjects", "top": [["#hubMain", 60]] } },
|
|
75
82
|
{ "name": "390: a solo Shift tap opens the fold and focuses the field, without overflow", "continue": true,
|
|
76
83
|
"steps": [["press", "Escape"], ["wait", 100], ["press", "Shift"], ["wait", 150]],
|
|
77
84
|
"expect": { "hasClass": [["#qWrap", "is-open", true]], "activeId": "mapQ", "noOverflow": true } }
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"in-map-kbd": { "auth": true, "actions": [["focus", "#projTrig"], ["press", "Enter"], ["wait", 350], ["press", "ArrowDown"], ["wait", 120]], "expect": { "expanded": true, "activeText": "Table" } },
|
|
15
15
|
"in-map-search": { "auth": true, "actions": [["clickIfVisible", "#qToggle"], ["wait", 200], ["fill", "#mapQ", "emer"], ["wait", 300]], "expect": { "value": [["#mapQ", "emer"]] } },
|
|
16
16
|
"in-map-mine-on": { "auth": true, "actions": [["check", "#onlyMine"], ["wait", 300]], "expect": { "checked": "#onlyMine" } },
|
|
17
|
-
"in-table": { "auth": true, "actions": [["click", "#projTrig"], ["wait", 250], ["click", "a[data-sub=\"table\"]"], ["wait", 400]], "expect": { "visible": ["#sub-table-body"], "closed": "#menuProjects" } },
|
|
17
|
+
"in-table": { "auth": true, "actions": [["click", "#projTrig"], ["wait", 250], ["click", "a[data-sub=\"table\"]"], ["wait", 400]], "expect": { "visible": ["#sub-table-body", ".tblMast", ".mastObj"], "closed": "#menuProjects" } },
|
|
18
18
|
"in-mine": { "auth": true, "url": "/projects?view=mine", "expect": { "hidden": ["#qWrap"] } },
|
|
19
19
|
"in-new": { "auth": true, "url": "/projects?view=new", "expect": { "hidden": ["#qWrap"] } },
|
|
20
20
|
"out-new": { "auth": false, "url": "/projects?view=new", "expect": { "hidden": ["#qWrap"] } },
|