openvibers/openvibe.space Commits

openvibe-shared v4.228.0 (was v4.227.0) (#308)

OP OpenVibers committed 16 h ago · 95aa084fa9 · 6 files, +28 −33

* openvibe-shared v4.228.0 (was v4.227.0)

Opened by scripts/pin-bump.js in OpenVibers/OpenVibe.Shared after the v4.228.0 release.

* Home: the pick block is Shared's showcase.pick(), tabs on a phone; the old chips only jumped, so every pane showed

Changes

ddiff --git a/README.md b/README.md
iindex 70174a8..50d40fc 100644
---- a/README.md
++++ b/README.md
@@@ -154,5 +154,5 @@ AGPL-3.0-only. See [LICENSE](LICENSE).
<!-- versions:start -->
- openvibe-contracts: v0.417.0
- openvibe-sdk: v0.161.0
--- openvibe-shared: v4.227.0
++- openvibe-shared: v4.228.0
<!-- versions:end -->
ddiff --git a/STATUS.json b/STATUS.json
iindex 75c4d05..31d9b66 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -8,7 +8,7 @@
"domain": "openvibe.space",
"contracts": "openvibe-contracts v0.417.0",
"sdk": "openvibe-sdk v0.161.0",
-- "shared": "openvibe-shared v4.227.0",
++ "shared": "openvibe-shared v4.228.0",
"capabilities": [
"space.site.manage",
"space.site.config",
@@@ -44,7 +44,7 @@
"packages": [
"openvibe-contracts v0.417.0",
"openvibe-sdk v0.161.0",
-- "openvibe-shared v4.227.0"
++ "openvibe-shared v4.228.0"
],
"updated": "2026-11-12"
}
ddiff --git a/package-lock.json b/package-lock.json
iindex 856fb57..aa05d35 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -17,7 +17,7 @@
"helmet": "^8.1.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.417.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.161.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.227.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.228.0",
"pg": "^8.23.0",
"quickjs-emscripten": "0.32.0"
},
@@@ -1247,9 +1247,9 @@
}
},
"node_modules/openvibe-shared": {
-- "version": "4.227.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.227.0",
-- "integrity": "sha512-/PqSqCC/vw/iwvkhDipLyixPyrtTcMpPhZ8UQ35fGDfAEJt43du2MYmZetu/TUysz+iJ9/Z7+VCFsFI1XzuF3Q==",
++ "version": "4.228.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.228.0",
++ "integrity": "sha512-HR0Hac/K+qKmwMf2QZWCFxW+uVja36nyAtxVbNFgPGUDFdmWhmb6RMoP/CkU0+GSCPsC50k6aTS+oPx2czDgGg==",
"license": "MIT",
"dependencies": {
"clean-css": "^5.3.3",
ddiff --git a/package.json b/package.json
iindex 3875db9..59f021d 100644
---- a/package.json
++++ b/package.json
@@@ -29,7 +29,7 @@
"helmet": "^8.1.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.417.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.161.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.227.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.228.0",
"pg": "^8.23.0",
"quickjs-emscripten": "0.32.0"
},
ddiff --git a/server/render/short.js b/server/render/short.js
iindex e18e17c..72890b0 100644
---- a/server/render/short.js
++++ b/server/render/short.js
@@@ -2,9 +2,9 @@
/**
* The home on a phone (the owner's short-pages rule, 2026-10-30): one or two screens, app-like.
*
-- * pickBlock() several blocks of the same kind, one at a time on a phone, picked with a row of chips. Radio
-- * inputs and :has(), no script: every block stays in the page for crawlers, and a wider screen (or a
-- * browser without :has()) shows them all and no chips.
++ * pickBlock() several blocks of the same kind, one at a time on a phone as tabs (showcase.parts): radios and
++ * :has(), no script; every block stays in the page for crawlers, and a wider screen (or a browser
++ * without :has()) shows them all.
* foldBlock() a part a reader rarely needs, closed on a phone and open where there is room. The page's own markup
* keeps it open, so a browser without the script shows it as before; the script closes it on a narrow
* screen and remembers the reader's choice.
@@@ -12,21 +12,19 @@
* The CSS for both lives in public/css/space.css; the rule that shows the picked block is written for the page,
* because there is one per block.
*/
++const { pick } = require('openvibe-shared/showcase');
const esc = (s) => String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
/**
-- * A pick block. The panes are the page's own blocks; each one keeps its heading on a wide screen, and on a phone the
-- * heading gives way to the chip that names it.
++ * A pick block: the page's own blocks, one at a time as tabs on a phone (openvibe-shared showcase.parts, the same tabs
++ * as every OpenVibe page; the owner, 2026-11-11: "self-contained tabs, so the page isn't so freaking huge … at least on
++ * mobile"). Every pane stays in the page for crawlers, a wider screen stacks them, and a link to a pane's id (an
++ * anchor in the hero) opens its tab. The old chips only jumped to a pane, so a phone still showed all of them.
*
* pickBlock({ key, label, head, panes }) panes: [{ id, label, html }]
*/
function pickBlock({ key, label, head = '', panes }) {
-- if (!panes.length) return '';
-- const chips = panes.map((p) => `<a class="pick-chip" href="#${esc(p.id)}">${esc(p.label)}</a>`).join('');
-- // The pane carries the id the page already links to (an anchor in the hero, for instance), so a link to it still
-- // opens that pane on a phone (the CSS shows the pane a link points at).
-- const body = panes.map((p) => `<div class="pick-pane" id="${esc(p.id)}">${p.html}</div>`).join('');
-- return `<div class="pick" id="pick-${esc(key)}"><div class="pick-bar"><div class="pick-head"><h2>${esc(head || label)}</h2></div><nav class="pick-row" data-ovk-scroll aria-label="${esc(label)}">${chips}</nav></div><div class="pick-body">${body}</div></div>`;
++ return pick({ key, label, head, panes });
}
ddiff --git a/test/home-short.test.js b/test/home-short.test.js
iindex ebb436e..57e59b5 100644
---- a/test/home-short.test.js
++++ b/test/home-short.test.js
@@@ -12,31 +12,28 @@ const { boot, check, done } = require('./helpers/app');
(async () => {
const t = await boot();
try {
-- await check('the home is one pick block: a chip per part, the first picked, every part in the page', async () => {
++ await check('the home is one pick block: on a phone its parts are tabs, the first open, every part in the page', async () => {
const r = await t.get('/');
assert.strictEqual(r.status, 200, r.text);
const page = r.text;
// From the block to the end of the page: its panes grew past a fixed window when section heads gained an icon (Shared 4.160.0).
const block = page.slice(page.indexOf('<div class="pick" id="pick-parts">'));
assert.ok(block.startsWith('<div class="pick" id="pick-parts">'), 'the pick block is on the home');
-- assert.match(block, /<nav class="pick-row" data-ovk-scroll aria-label="What Space does">/);
-- const chips = [...block.matchAll(/<a class="pick-chip" href="#(?:pp-parts-)?([a-z]+)">()([^<]+)<\/a>/g)];
-- assert.ok(chips.length >= 5, `a chip per part (${chips.length})`);
-- assert.ok(!/type="radio"/.test(block), 'no chip is a radio: nothing is picked, every pane shows');
-- // Every part stays in the page, with the id its chip picks.
++ // The owner, 11-11: "self-contained tabs, so the page isn't so freaking huge … at least on mobile" (Shared's
++ // showcase.parts, a front page: tabs at 600 px and under; the old chips only jumped, so every pane showed).
++ assert.match(block, /<div class="ov-parts ov-parts--front" data-parts="\d">/);
++ const tabs = [...block.matchAll(/<label for="ovp-parts-([a-z]+)">([^<]+)<\/label>/g)];
++ assert.ok(tabs.length >= 5, `a tab per part (${tabs.length})`);
++ assert.ok(block.includes(`id="ovp-parts-${tabs[0][1]}" value="${tabs[0][1]}" checked>`), 'the first part is open');
++ assert.ok(!block.includes('class="pick-chip"'), 'no jump chips beside the tabs');
++ // Every part stays in the page, with the id a link opens it by.
const panes = [...block.matchAll(/<div class="pick-pane" id="([a-z]+)">/g)].map((m) => m[1]);
-- assert.deepStrictEqual(panes, chips.map((m) => m[1]), 'every part is in the page, one per chip');
++ assert.deepStrictEqual(panes, tabs.map((m) => m[1]), 'every part is in the page, one per tab');
// The parts themselves are all there: nothing was removed.
for (const title of ['Start from a template', 'How a space comes together', 'How a deploy works', 'What works now', 'The same over the API', 'Quotas per project']) {
assert.ok(page.includes(title), `${title} is on the page`);
}
-- });
--
-- await check('the CSS guard: the chips are hidden and the parts all show until 640 px and where :has() is understood', async () => {
-- const r = await t.get('/');
-- const page = r.text;
-- const css = fs.readFileSync(path.join(__dirname, '..', 'public', 'css', 'space.css'), 'utf8');
-- assert.match(css, /\.pick-row \{ display: none; \}/, 'the chips are hidden by default');
++ assert.match(page, /<link rel="stylesheet" href="\/shared\/ov-parts\.css[^"]*">/, 'the tabs\' look is linked before the page draws');
});
await check('the parts a reader rarely needs are folds, open in the page and closed on a phone', async () => {