openvibers/openvibe.codes Commits

On a phone, a wide table shows each row as a labelled card (#234)

OP OpenVibers committed 12 days ago · 54241b27e1 · 3 files, +19 −3

* On a phone, a wide table shows each row as a labelled card

* Budget: 2026-11-01: phone table cards

Changes

ddiff --git a/public/css/codes.css b/public/css/codes.css
iindex 73e09f0..4f4ce53 100644
---- a/public/css/codes.css
++++ b/public/css/codes.css
@@@ -118,3 +118,18 @@ meter.headroom { width: 8rem; max-width: 100%; vertical-align: middle; }
/* Touch targets on phones (fleet audit 2026-10-29): the touch-only hit area for this group. Nothing moves with a mouse. */
@media (pointer: coarse) { .codes-faq details > summary { min-height: 44px; } }
++
++/* Tables on a phone (phone sweep, 2026-11-01): a table of three columns or more shows each row as a card, the first
++ cell its title and every other cell named by its column (html.js gives each cell its data-label). Narrower tables
++ stay tables. Nothing is left out and nothing scrolls sideways. */
++@media (max-width: 640px) {
++ .table-wrap:has(> table thead th:nth-child(3)) { overflow: visible; }
++ .table-wrap > table:has(thead th:nth-child(3)) { display: block; }
++ .table-wrap > table:has(thead th:nth-child(3)) thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
++ .table-wrap > table:has(thead th:nth-child(3)) tbody { display: grid; gap: 10px; }
++ .table-wrap > table:has(thead th:nth-child(3)) tr { display: grid; gap: 8px; padding: 12px 14px; border: 1px solid var(--border, #1f2d47); border-radius: 14px; background: var(--bg-card, var(--bg-secondary, #101828)); }
++ .table-wrap > table:has(thead th:nth-child(3)) td { display: block; min-width: 0; padding: 0; border: 0; overflow-wrap: anywhere; }
++ .table-wrap > table:has(thead th:nth-child(3)) td:first-child { font-weight: 700; color: var(--text-primary, #e6edf7); }
++ .table-wrap > table:has(thead th:nth-child(3)) td[data-label]:not(:first-child)::before { content: attr(data-label); display: block; margin-bottom: 2px; font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted, #7386a3); }
++ .table-wrap > table:has(thead th:nth-child(3)) td:empty { display: none; }
++}
ddiff --git a/server/render/html.js b/server/render/html.js
iindex a0e2a36..4ddf22b 100644
---- a/server/render/html.js
++++ b/server/render/html.js
@@@ -24,11 +24,12 @@ function render(v) {
const code = (s) => html`<code>${s}</code>`;
const time = (iso) => (iso ? html`<time datetime="${iso}">${String(iso).replace('T', ' ').replace(/\.\d+Z$/, ' UTC').replace(/Z$/, ' UTC')}</time>` : '—');
--/** A <table> from headers and rows of cells (cells are already html or plain values). */
++/** A <table> from headers and rows of cells (cells are already html or plain values). Each cell names its column
++ * (data-label), so on a phone a wide table can show each row as a card (the site's stylesheet). */
function table(headers, rows, { cls = '', empty = 'Nothing here yet.' } = {}) {
if (!rows.length) return html`<p class="muted">${empty}</p>`;
// The wrapper scrolls sideways on a phone, so it is a focusable, named region (axe scrollable-region-focusable).
-- return html`<div class="table-wrap" tabindex="0" role="region" aria-label="Table: ${headers.join(', ')}"><table class="${cls}"><thead><tr>${headers.map((h) => html`<th scope="col">${h}</th>`)}</tr></thead><tbody>${rows.map((r) => html`<tr>${r.map((c) => html`<td>${c}</td>`)}</tr>`)}</tbody></table></div>`;
++ return html`<div class="table-wrap" tabindex="0" role="region" aria-label="Table: ${headers.join(', ')}"><table class="${cls}"><thead><tr>${headers.map((h) => html`<th scope="col">${h}</th>`)}</tr></thead><tbody>${rows.map((r) => html`<tr>${r.map((c, i) => (typeof headers[i] === 'string' && headers[i] ? html`<td data-label="${headers[i]}">${c}</td>` : html`<td>${c}</td>`))}</tr>`)}</tbody></table></div>`;
}
/** A problem as returned by Network, Events or Media — shown as it came, never softened. */
ddiff --git a/test/perf-budget.test.js b/test/perf-budget.test.js
iindex 4ea39b1..ed54ed4 100644
---- a/test/perf-budget.test.js
++++ b/test/perf-budget.test.js
@@@ -18,7 +18,7 @@ const BUDGETS = {
jsRawKB: 348, // 345.6 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 342.2 with openvibe-shared 4.66.0: the mark with depth and motion, ov-fx loaded on request (2026-10-31); 341.4 with openvibe-shared 4.64.0: the look travels between sites, the Look panel in the menu (2026-10-31); 340.6 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face (2026-10-31); 330.9 after C9b: the conductor's message box with its images and its live turn (2.6 KB in js/c4.js); 326.2 after C4b: the home page loads the workspace script for its repository search (10.9 KB of its own); 315.6 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 307.8 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); 300.5 openvibe-shared 4.25.0: the menu's orb beside the brand, both balances on phones, messages, the account sheet on phones and the bar stepping away on phones; 293 openvibe-shared 4.22.0: the navbar's magnifier search button and More dropdown (search.js and loading.js load only when used); 287.2 Shared 4.17.0: OpenCoins and Vibes chips (wallet: true) in the navbar; 273.2 openvibe-shared 4.15 footer: the compact footer opens into the whole one, and the pulse line; 263.4 with shared 4.11.0's seasonal navbar; 254.1 with openvibe-shared 4.9.0 (status text twins in every theme, 2026-10-23); 246.2 with openvibe-shared 4.2.x (Ask Actor in the navbar, 2026-10-15); 239.1 (212.2 before openvibe-shared/shell's web-runtime.js)
jsBrotliKB: 85.2, // 84.6 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 82.9 after C9b's conductor script; 80.6 after C4b's repository search on the home page; 77.6 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 76.1 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); 74.2 openvibe-shared 4.25.0: the menu's orb beside the brand, both balances on phones, messages, the account sheet on phones and the bar stepping away on phones; 70.5 Shared 4.17.0: OpenCoins and Vibes chips (wallet: true) in the navbar; 67.9 openvibe-shared 4.15 footer: the compact footer opens into the whole one, and the pulse line; 65.3 Shared 4.12.0: the light/dark switch, the seasonal mark and the theme pairs; 61.7 with shared 4.11.0's seasonal navbar; 59.1 with openvibe-shared 4.4.0 (every site in the launcher, 2026-10-17); 56.3 (49.9 before web-runtime.js)
cssFiles: 3, // C4 adds its responsive workspace stylesheet alongside codes.css and run.css.
-- cssRawKB: 72, // 70.7 after the front door: a visitor's example conversation, its hand-over line and result row (public/css/c4.css, 1.4 KB, 2026-10-31); 69.3 after the Memory M2b review: the quiet Remove link, the phone sources fold, the in-place note menu and the danger buttons (public/css/c4.css, 2.2 KB); 67.1 after Memory M2b: the Memory page's sources, notes, note menus, conflicts and tabs (public/css/c4.css, 2.4 KB); 63.0 after C9c: the fleet's rows and its meters on the Agents page (public/css/c4.css, 1.2 KB); 62.4 after C9b: the conductor's turns, approvals inbox and composer (public/css/c4.css); 58.4 after C4b: the proof rows, the fold-out panels, the shots, the forms that remember choices and their light/dark styles; 46 KB after adding the C4 phone-first workspace, cards, task timeline and light/dark styles.
++ cssRawKB: 73, // 72.2 with 2026-11-01: phone table cards (2026-11-01); 70.7 after the front door: a visitor's example conversation, its hand-over line and result row (public/css/c4.css, 1.4 KB, 2026-10-31); 69.3 after the Memory M2b review: the quiet Remove link, the phone sources fold, the in-place note menu and the danger buttons (public/css/c4.css, 2.2 KB); 67.1 after Memory M2b: the Memory page's sources, notes, note menus, conflicts and tabs (public/css/c4.css, 2.4 KB); 63.0 after C9c: the fleet's rows and its meters on the Agents page (public/css/c4.css, 1.2 KB); 62.4 after C9b: the conductor's turns, approvals inbox and composer (public/css/c4.css); 58.4 after C4b: the proof rows, the fold-out panels, the shots, the forms that remember choices and their light/dark styles; 46 KB after adding the C4 phone-first workspace, cards, task timeline and light/dark styles.
cssBrotliKB: 15, // 14.2 after the Memory M2b review (the same quiet link, sources fold, in-place menu and danger buttons); 13.0 after C9b's conductor styles; 12.1 after C4b's rows, panels and forms; 9.9 KB after adding the C4 workspace styles.
externalFiles: 2, // 0
};