@bongos/core 1.24.82 → 1.24.83
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 +58 -58
- package/docs/adr/0402-helm-is-the-halls-look-and-the-hall-is-dark-only.md +4 -0
- package/docs/copy-inventory.md +2 -2
- package/docs/copy-registry.json +4 -4
- package/docs/module-api-changelog.md +2 -0
- package/docs/page-readings.json +42 -42
- package/modules/hall-ui/public/ai-studio.html +1 -1
- package/modules/hall-ui/public/atlas.html +1 -1
- package/modules/hall-ui/public/blockers.html +1 -1
- package/modules/hall-ui/public/board-room.html +1 -1
- package/modules/hall-ui/public/city.html +2 -2
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/commands.html +1 -1
- package/modules/hall-ui/public/controls.css +10 -2
- package/modules/hall-ui/public/copy-desk.html +1 -1
- package/modules/hall-ui/public/deploy.html +1 -1
- package/modules/hall-ui/public/goal-map.html +2 -2
- package/modules/hall-ui/public/goals.html +1 -1
- package/modules/hall-ui/public/government.html +1 -1
- package/modules/hall-ui/public/idea.html +1 -1
- package/modules/hall-ui/public/ideas.html +1 -1
- package/modules/hall-ui/public/index.html +2 -2
- package/modules/hall-ui/public/market-watch-item.html +1 -1
- package/modules/hall-ui/public/market-watch-rules.html +1 -1
- package/modules/hall-ui/public/market-watch.html +1 -1
- package/modules/hall-ui/public/modules.html +1 -1
- package/modules/hall-ui/public/money.html +1 -1
- package/modules/hall-ui/public/my-agents.html +1 -1
- package/modules/hall-ui/public/options-menu.js +20 -0
- package/modules/hall-ui/public/primer.html +1 -1
- package/modules/hall-ui/public/profile.html +1 -1
- package/modules/hall-ui/public/project-settings.html +1 -1
- package/modules/hall-ui/public/roster.html +1 -1
- package/modules/hall-ui/public/settings.css +113 -46
- package/modules/hall-ui/public/settings.html +3 -3
- package/modules/hall-ui/public/street.html +1 -1
- package/modules/hall-ui/public/studio.html +1 -1
- package/modules/hall-ui/public/style.css +147 -61
- package/modules/hall-ui/public/task.html +1 -1
- package/modules/hall-ui/public/thinking.html +2 -2
- package/modules/hall-ui/public/tweak-editor.html +1 -1
- package/modules/hall-ui/public/visor.css +2 -2
- package/modules/hall-ui/public/watch.html +1 -1
- package/modules/hall-ui/public/work.html +1 -1
- package/modules/hall-ui/records/craft-mode.md +9 -0
- package/modules/hall-ui/records/options-menu.md +11 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +6 -0
- package/src/module-api.js +1 -1
- package/tests/design_tokens_shared.mjs +5 -1
- package/tests/hall_controls.mjs +1 -1
- package/tests/hall_helm.mjs +103 -1
- package/tests/hall_topbar_320.mjs +7 -4
package/tests/hall_helm.mjs
CHANGED
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
// cannot see because the link is built at serve time;
|
|
15
15
|
// * no hall script writes a theme choice, and the shell offers no switch;
|
|
16
16
|
// * the Helm neutrals: the two dark twins carry the night, the ice and no black;
|
|
17
|
-
// * the kit's recipes exist once, as hall-tier tokens and shared rules
|
|
17
|
+
// * the kit's recipes exist once, as hall-tier tokens and shared rules;
|
|
18
|
+
// * Helm look 2 (task 1005194): the hall has no pill, and the options menu and
|
|
19
|
+
// character select are Helm screens written from the tokens alone.
|
|
18
20
|
//
|
|
19
21
|
// Run: node --test tests/hall_helm.mjs
|
|
20
22
|
import { test } from 'node:test';
|
|
@@ -185,3 +187,103 @@ test('the kit\'s recipes are named once: the name voice, the cut, the segment, t
|
|
|
185
187
|
assert.match(controls, /\n\.seg--done \{ background: var\(--ink-soft\);/, 'a finished step is information, so it is ice, not the accent');
|
|
186
188
|
assert.match(controls, /\n\.seg--now \{ background: var\(--accent\);/, 'the accent is the step you can act on');
|
|
187
189
|
});
|
|
190
|
+
|
|
191
|
+
// ── Helm look 2 (task 1005194): the square corner, the options menu, character select ──
|
|
192
|
+
|
|
193
|
+
// one rule's body, by its exact selector line, from a decommented sheet
|
|
194
|
+
const ruleOf = (css, sel) => {
|
|
195
|
+
const at = css.indexOf('\n' + sel + ' {');
|
|
196
|
+
assert.notEqual(at, -1, `no rule ${sel}`);
|
|
197
|
+
const open = css.indexOf('{', at);
|
|
198
|
+
return css.slice(open + 1, css.indexOf('}', open));
|
|
199
|
+
};
|
|
200
|
+
const NO_COLOUR_LITERAL = /#[0-9a-fA-F]{3,8}\b|\brgba?\(|\bhsla?\(/;
|
|
201
|
+
|
|
202
|
+
test('the hall has no pill: --radius-pill is a square corner in the hall tier, and only there', () => {
|
|
203
|
+
assert.equal(root['--radius-pill'], '0px', 'Helm draws no pill');
|
|
204
|
+
// the panel and the tile keep their corners until each page's own task (DESIGN.md "The hall")
|
|
205
|
+
assert.equal(root['--radius'], 'var(--ds-radius-panel)');
|
|
206
|
+
assert.equal(root['--radius-sm'], 'var(--ds-radius-tile)');
|
|
207
|
+
// the shared scale is untouched, so the landing and the status page keep their pill
|
|
208
|
+
assert.match(read('modules', 'ui-design', 'public', 'tokens.css'), /--ds-radius-pill:\s*999px;/);
|
|
209
|
+
const controls = decomment(read('modules', 'hall-ui', 'public', 'controls.css'));
|
|
210
|
+
// the field and the status tag spend the name, so they are square in the hall with no rule of their own
|
|
211
|
+
assert.match(controls, /\.input \{[^}]*border-radius: var\(--radius-pill\);/);
|
|
212
|
+
assert.match(controls, /\ntextarea \{[^}]*border-radius: var\(--press-radius, var\(--radius-sm\)\);/, 'a textarea is square too, the tile where the tier is not loaded');
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('what is pressed in the top bar, and a filter chip, take the small cut and the inset focus ring', () => {
|
|
216
|
+
const css = decomment(STYLE.replace(/\r\n/g, '\n'));
|
|
217
|
+
for (const sel of ['.upd-pill', '.chip', 'html[data-fullscreen="on"] .fullscreen-toggle']) {
|
|
218
|
+
const body = ruleOf(css, sel);
|
|
219
|
+
assert.match(body, /clip-path: var\(--cut-path-sm\);/, `${sel} is cut`);
|
|
220
|
+
assert.match(body, /--focus-ring: var\(--press-focus\);/, `${sel}: a cut clips an outline, so the ring is inside`);
|
|
221
|
+
assert.match(body, /border-radius: var\(--press-radius\);/, `${sel} has no round corner`);
|
|
222
|
+
}
|
|
223
|
+
// an outer shadow would be clipped away with the corner, and would outrank the focus ring
|
|
224
|
+
assert.doesNotMatch(ruleOf(css, 'html[data-fullscreen="on"] .upd-pill'), /box-shadow/);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test('the options menu is a Helm screen: a night panel, name-voice rows, the open one the accent bar', () => {
|
|
228
|
+
const sheet = decomment(read('modules', 'hall-ui', 'public', 'settings.css').replace(/\r\n/g, '\n'));
|
|
229
|
+
const menu = sheet.slice(0, sheet.indexOf('.cli-result'));
|
|
230
|
+
assert.ok(menu.includes('.opt-rail') && menu.includes('.opt-screen'), 'the menu and the open screen are the first part of the sheet');
|
|
231
|
+
assert.doesNotMatch(menu, NO_COLOUR_LITERAL, 'no colour is typed in');
|
|
232
|
+
assert.doesNotMatch(menu, /border-radius:\s*\d/, 'no corner is typed in');
|
|
233
|
+
const rail = ruleOf(menu, '.opt-rail');
|
|
234
|
+
assert.match(rail, /background: var\(--night-glass\);/);
|
|
235
|
+
assert.match(rail, /border-left-width: var\(--line-strong\); border-right-width: var\(--line-strong\);/, 'closed left and right by the strong hairline');
|
|
236
|
+
const link = ruleOf(menu, '.opt-link');
|
|
237
|
+
assert.match(link, /font-family: var\(--name-face\);/);
|
|
238
|
+
assert.match(link, /text-transform: var\(--name-case\);/);
|
|
239
|
+
assert.match(link, /min-height: var\(--ds-space-xl\);/, 'a row clears the 24px floor many times over');
|
|
240
|
+
assert.match(link, /border-bottom: var\(--line\) solid var\(--rule-soft\);/, 'rows on hairlines, not boxes');
|
|
241
|
+
assert.match(ruleOf(menu, '.opt-link--active, .opt-link--active:hover'), /color: var\(--accent-on\); background: var\(--accent\);/);
|
|
242
|
+
assert.match(ruleOf(menu, '.opt-link:focus-visible'), /box-shadow: var\(--press-focus\);/, 'the ring is inside the row, so it reads on the accent bar');
|
|
243
|
+
const screen = ruleOf(menu, '.opt-screen');
|
|
244
|
+
assert.match(screen, /font-family: var\(--name-face\);/);
|
|
245
|
+
assert.match(screen, /border-bottom: var\(--line-strong\) solid var\(--rule\);/);
|
|
246
|
+
const section = ruleOf(menu, '.settings-groups .scroll');
|
|
247
|
+
assert.match(section, /background: none;/, 'a section is a row on a hairline, not a card');
|
|
248
|
+
assert.match(section, /border-bottom: var\(--line\) solid var\(--rule-soft\);/);
|
|
249
|
+
// the search is the hall's one field: the sheet draws no edge, corner or focus of its own for it
|
|
250
|
+
assert.doesNotMatch(ruleOf(menu, '.opt-search input'), /border|outline/);
|
|
251
|
+
assert.doesNotMatch(menu, /\.opt-search input:focus/);
|
|
252
|
+
// the two names are words the menu already had: its own label, and the open entry's
|
|
253
|
+
const js = read('modules', 'hall-ui', 'public', 'options-menu.js');
|
|
254
|
+
assert.match(js, /<p class="opt-title" aria-hidden="true">Options<\/p>/);
|
|
255
|
+
assert.match(js, /h\.setAttribute\('aria-hidden', 'true'\);/);
|
|
256
|
+
assert.match(js, /h\.textContent = e\.label;/);
|
|
257
|
+
assert.match(js, /<nav|opt-search/, 'the search is still drawn');
|
|
258
|
+
assert.match(read('modules', 'hall-ui', 'public', 'settings.html'), /<nav class="opt-rail" id="settings-rail" aria-label="Options"><\/nav>/);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test('character select is a Helm screen: the night, cut doors, the suggested door lit, the ring inside the cut', () => {
|
|
262
|
+
const css = decomment(STYLE.replace(/\r\n/g, '\n'));
|
|
263
|
+
const picker = css.slice(css.indexOf('\n.craft-picker {'), css.indexOf('\n.craft-art {'));
|
|
264
|
+
assert.doesNotMatch(picker, NO_COLOUR_LITERAL, 'no colour is typed in');
|
|
265
|
+
assert.doesNotMatch(picker, /border-radius:\s*\d|font-size:\s*\d/, 'no corner or size is typed in');
|
|
266
|
+
assert.match(ruleOf(css, '.craft-picker--create'), /background: var\(--bg\);/, 'a screen on the night, not a box on a scrim');
|
|
267
|
+
assert.match(ruleOf(css, '.craft-picker__panel--create'), /background: none;/);
|
|
268
|
+
const title = ruleOf(css, '.craft-picker__title');
|
|
269
|
+
assert.match(title, /font-family: var\(--name-face\);/);
|
|
270
|
+
assert.match(title, /text-transform: var\(--name-case\);/);
|
|
271
|
+
const door = ruleOf(css, '.craft-door');
|
|
272
|
+
assert.match(door, /clip-path: var\(--cut-path\);/, 'a door is pressed, so it is cut');
|
|
273
|
+
assert.match(door, /background: var\(--night-glass\);/);
|
|
274
|
+
assert.match(ruleOf(css, '.craft-door:focus-visible'), /outline: 0;[^}]*box-shadow: var\(--press-focus\);/);
|
|
275
|
+
assert.match(ruleOf(css, '.craft-door--pre, .craft-door--pre:hover'), /box-shadow: inset 0 0 0 2px var\(--accent\);/);
|
|
276
|
+
assert.match(ruleOf(css, '.craft-door::after'), /box-shadow: inherit;/, 'the edge is drawn over the portrait as well as under it');
|
|
277
|
+
assert.match(ruleOf(css, '.craft-door__name'), /font-family: var\(--name-face\);/);
|
|
278
|
+
// the real sprites, and the words where they were
|
|
279
|
+
const js = read('modules', 'hall-ui', 'public', 'craft-mode.js');
|
|
280
|
+
for (const id of ['artisan', 'artist', 'patron']) assert.ok(fs.existsSync(path.join(HALL, 'characters', id + '.png')), `${id}.png`);
|
|
281
|
+
assert.match(js, /id="craft-picker-title">Choose your character<\/h2>/);
|
|
282
|
+
assert.match(js, /aria-describedby="craft-picker-lede"/);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test('the visor reads in the Helm night: no hover falls back to the pack\'s dark accent', () => {
|
|
286
|
+
const visor = decomment(read('modules', 'hall-ui', 'public', 'visor.css'));
|
|
287
|
+
assert.doesNotMatch(visor, /--accent-deep/, 'the deep accent is a light-ground colour; on the night it is under 4.5:1');
|
|
288
|
+
assert.match(visor, /\.visor__row:hover \{ color: var\(--accent-ink\); \}/);
|
|
289
|
+
});
|
|
@@ -99,7 +99,9 @@ for (const scheme of ['light', 'dark']) {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
// Helm (task 1005194): the hall has no pill, so the one shape the two share is the hall's
|
|
103
|
+
// square corner (--radius-pill is 0px in the hall tier) inside the same hairline.
|
|
104
|
+
test('the top bar search and the mode switch are one shape: the square corner of the hall with the same hairline', { skip }, async () => {
|
|
103
105
|
const ctx = await context(1440, 'dark');
|
|
104
106
|
const page = await ctx.newPage();
|
|
105
107
|
await page.goto(ORIGIN + '/work');
|
|
@@ -115,11 +117,12 @@ test('the top bar search and the mode switch are one shape: a pill with the same
|
|
|
115
117
|
switchRadius: css(sw).borderTopLeftRadius,
|
|
116
118
|
jumpEdge: css(jump).borderTopColor,
|
|
117
119
|
switchShadow: css(sw).boxShadow,
|
|
118
|
-
pill: root.getPropertyValue('--
|
|
120
|
+
pill: root.getPropertyValue('--radius-pill').trim(),
|
|
119
121
|
};
|
|
120
122
|
}).finally(() => ctx.close());
|
|
121
|
-
assert.equal(s.
|
|
122
|
-
assert.equal(s.
|
|
123
|
+
assert.equal(s.pill, '0px', 'the hall tier squares the pill');
|
|
124
|
+
assert.equal(s.jumpRadius, s.pill, 'the search takes the corner of the hall');
|
|
125
|
+
assert.equal(s.switchRadius, s.pill, 'the mode switch takes the same corner');
|
|
123
126
|
assert.ok(s.switchShadow.startsWith(s.jumpEdge), `the two share one hairline colour (${s.jumpEdge} vs ${s.switchShadow})`);
|
|
124
127
|
});
|
|
125
128
|
|