openvibers/openvibe.work Commits

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

OP OpenVibers committed 12 days ago · 2f434dc315 · 4 files, +21 −5

* Phone tables: a wide table shows each row as a labelled card

* Budget: 2026-11-01: phone table cards (+1.3 KB raw)

Changes

ddiff --git a/public/css/app.css b/public/css/app.css
iindex bbbee8b..4e0ae3e 100644
---- a/public/css/app.css
++++ b/public/css/app.css
@@@ -112,3 +112,18 @@ button.sc-btn.sc-primary { border: 0; }
.page p > a:only-child { position: relative; }
.page p > a:only-child::after { content: ''; position: absolute; left: 0; right: 0; top: -13px; bottom: -13px; }
}
++
++/* 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/http/pages.js b/server/http/pages.js
iindex e9a83f2..0a827e0 100644
---- a/server/http/pages.js
++++ b/server/http/pages.js
@@@ -740,7 +740,7 @@ ${sources.SOURCES.map((src) => {
</ul>
${table(['Route', 'Who', 'What it does'], [
[html`<code>GET /api/v1/jobs</code>`, 'public', html`Search: <code>?q=</code>, <code>?remote=true|false</code>, <code>?type=</code>, <code>?location=</code>, <code>?limit=</code> (to ${store.MAX_PAGE}), <code>?cursor=</code> (the <code>next</code> the previous page returned). Newest first, ${store.PAGE_SIZE} a page, with facets for remote and job type.`],
-- [html`<code>GET /api/v1/jobs/:id</code>`, 'public', 'One listing: the board\'s fields, the excerpt, the source, and <code>url</code> — the original listing to apply on.'],
++ [html`<code>GET /api/v1/jobs/:id</code>`, 'public', html`One listing: the board's fields, the excerpt, the source, and <code>url</code>, the original listing to apply on.`],
[html`<code>GET /api/v1/sources</code>`, 'public', 'The boards, each one\'s terms as applied, its listing count and when it was last read.'],
[html`<code>GET /api/v1/saved-searches</code>`, 'person', 'Your saved searches, each with <code>new_count</code> — listings that appeared since you last looked.'],
[html`<code>POST /api/v1/saved-searches</code>`, 'person', html`Save one: <code>{ q?, remote?, type?, location? }</code>. At least one filter. 201 with the saved search.`],
ddiff --git a/server/render/html.js b/server/render/html.js
iindex c0f69d9..1dfe9ed 100644
---- a/server/render/html.js
++++ b/server/render/html.js
@@@ -24,10 +24,11 @@ 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>`;
-- return html`<div class="table-wrap"><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"><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 2f550e1..5ddbb9e 100644
---- a/test/perf-budget.test.js
++++ b/test/perf-budget.test.js
@@@ -23,8 +23,8 @@ const BUDGETS = {
jsRawKB: 331, // 328.2 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 324.8 with openvibe-shared 4.66.0: the mark with depth and motion, ov-fx loaded on request (2026-10-31); 323.2 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face (2026-10-31); 321.1 with openvibe-shared 4.53.0: the footer's columns fold on phones (2026-10-30); 318.1 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 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; 264.3 with Shared 4.13.0 (2026-10-26: account links); 239.8
jsBrotliKB: 80.8, // 80.2 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 79.5 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face (2026-10-31); 78.2 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 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; 56.5
cssFiles: 3, // 3 (app.css, the cached /shared/showcase.css and css/home.css, the curated home's counts, fields, cities, companies and questions, 2026-10-22)
-- cssRawKB: 46, // 45.6 with the listings' salary line and the fetch date under the link out (2026-10-31); 45.3 with the home's pick block and folds (the sections below the search are picked one at a time on a phone, 2026-10-30); 41.7 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); 39.5 the home's phone rows, limits and fold (2026-10-29); 34.8 openvibe-shared 4.26.1 (hero visual); 29.3 with Shared 4.13.0 (2026-10-26: account links); 23.1 with css/home.css (2026-10-22); 15.0 before the listings; 18.2 after (the search form, the listing list, the source blocks)
-- cssBrotliKB: 10.2, // raised from 10 on 2026-10-31, with the measured page: 45.6 KB raw / 10.1 KB brotli (the listings' salary line, the gone line and the fetch date under the link out); 10.0 with the home's pick block and folds (the sections below the search are picked one at a time on a phone, 2026-10-30); 9.1 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); 8.6 the home's phone rows, limits and fold (2026-10-29); 6.6–6.7 with Shared 4.13.0; raised from 8 for openvibe-shared v4.39.0 (+1.5 KB raw of kit/room/showcase CSS); measured 8.3
++ cssRawKB: 48, // 47.0 with 2026-11-01: phone table cards (+1.3 KB raw) (2026-11-01); 45.6 with the listings' salary line and the fetch date under the link out (2026-10-31); 45.3 with the home's pick block and folds (the sections below the search are picked one at a time on a phone, 2026-10-30); 41.7 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); 39.5 the home's phone rows, limits and fold (2026-10-29); 34.8 openvibe-shared 4.26.1 (hero visual); 29.3 with Shared 4.13.0 (2026-10-26: account links); 23.1 with css/home.css (2026-10-22); 15.0 before the listings; 18.2 after (the search form, the listing list, the source blocks)
++ cssBrotliKB: 11, // 10.4 with 2026-11-01: phone table cards (+1.3 KB raw) (2026-11-01); raised from 10 on 2026-10-31, with the measured page: 45.6 KB raw / 10.1 KB brotli (the listings' salary line, the gone line and the fetch date under the link out); 10.0 with the home's pick block and folds (the sections below the search are picked one at a time on a phone, 2026-10-30); 9.1 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); 8.6 the home's phone rows, limits and fold (2026-10-29); 6.6–6.7 with Shared 4.13.0; raised from 8 for openvibe-shared v4.39.0 (+1.5 KB raw of kit/room/showcase CSS); measured 8.3
externalFiles: 0, // 0
};