openvibers/openvibe.design Commits

Your look: comfort settings on top of any theme; openvibe-shared v4.45.0 (#21)

OP OpenVibers committed 14 days ago · 2dc3be3bb5 · 5 files, +31 −8

Four switches under the display settings: more contrast, a readable font,
colour-blind-safe colours and true black. Each is a display preference of
theme-loader 4.45.0, applied at once here and saved to the account, so every
OpenVibe site follows. A sample under them (quieter text, a link in a sentence,
the three status colours) shows what each one changes.

Changes

ddiff --git a/package-lock.json b/package-lock.json
iindex e61657b..f368556 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -16,7 +16,7 @@
"helmet": "^8.1.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.236.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.70.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.43.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.45.0",
"pg": "^8.23.1"
},
"devDependencies": {
@@@ -1114,9 +1114,9 @@
}
},
"node_modules/openvibe-shared": {
-- "version": "4.43.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.43.0",
-- "integrity": "sha512-OANEzCEB2QPgbkb9Yt0O67k6DxcK2pHMO1nhKYCjTI7OhUF8LW8EpLf6FJmpHmDTmpFTUq4pJ3lr3u2hPXMDYQ==",
++ "version": "4.45.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.45.0",
++ "integrity": "sha512-/ceTZV1Nz5z5hRK1lMO0fBwDMAzeJ+ajvPa+5gZCSMjdeMR3s1qg1noiC4yOnJ14+7lfNcfVULX+ZHjieXDgmA==",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0",
ddiff --git a/package.json b/package.json
iindex 555af3a..25b3346 100644
---- a/package.json
++++ b/package.json
@@@ -22,7 +22,7 @@
"helmet": "^8.1.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.236.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.70.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.43.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.45.0",
"pg": "^8.23.1"
},
"engines": {
ddiff --git a/public/css/design.css b/public/css/design.css
iindex 43fa194..f7b0457 100644
---- a/public/css/design.css
++++ b/public/css/design.css
@@@ -476,3 +476,9 @@ html.ar-fit .ar-shot--desktop .ar-shot-frame, html.ar-fit .ar-shot--desktop::bef
.lk-site-form label { display: grid; gap: 4px; font-size: .86rem; font-weight: 700; color: var(--ovk-muted); }
.lk-site-form select { min-height: 44px; max-width: 70vw; padding: 0 10px; border: 1px solid var(--ovk-line); border-radius: 12px; background: var(--ovk-input); color: var(--ovk-text); font: inherit; }
.lk-site-form .ovk-btn { min-height: 44px; }
++
++/* /look Comfort (2026-10-29): the sample reads like any page, so each switch shows what it changes. */
++.lk-sample { margin: 14px 0 0; padding: 14px 16px; border: 1px solid var(--border, #1f2d47); border-radius: 12px; background: var(--bg-secondary, #101828); }
++.lk-sample p { margin: 0; }
++.lk-sample-muted { color: var(--text-muted, #7386a3); }
++.lk-sample-badges { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px !important; }
ddiff --git a/public/js/look.js b/public/js/look.js
iindex fb6c60a..2db23ab 100644
---- a/public/js/look.js
++++ b/public/js/look.js
@@@ -29,6 +29,8 @@
const code = $('#lk-code');
if (code) code.href = `/tokens?theme=${encodeURIComponent(id)}`;
}
++ // Comfort switches: [on, off] values of each display setting (openvibe-shared 4.45.0).
++ const COMFORT = { contrast: ['more', 'normal'], font: ['readable', 'default'], colors: ['cb-safe', 'default'], oled: ['on', 'off'] };
function check(name, value) {
root.querySelectorAll(`input[name="${name}"]`).forEach((i) => { if (i.type === 'radio') i.checked = i.value === value; });
}
@@@ -39,6 +41,7 @@
check('motion', d.motion);
const s = root.querySelector('input[name="seasonal"]');
if (s) s.checked = d.seasonal !== 'off';
++ for (const k of Object.keys(COMFORT)) { const c = root.querySelector(`input[name="${k}"]`); if (c) c.checked = d[k] === COMFORT[k][0]; }
}
root.addEventListener('change', (e) => {
const i = e.target;
@@@ -46,6 +49,7 @@
if (i.name === 'scheme') L.scheme.set(i.value);
else if (i.name === 'seasonal') L.display.set({ seasonal: i.checked ? 'on' : 'off' });
else if (i.name === 'text' || i.name === 'motion') L.display.set({ [i.name]: i.value });
++ else if (COMFORT[i.name]) L.display.set({ [i.name]: COMFORT[i.name][i.checked ? 0 : 1] });
showTheme();
showSettings();
say(root.getAttribute('data-signed-in') === '1' ? 'Saved. Every OpenVibe site follows.' : 'Saved on this device.');
ddiff --git a/server/views/look.js b/server/views/look.js
iindex 1d16804..8fdd476 100644
---- a/server/views/look.js
++++ b/server/views/look.js
@@@ -1,7 +1,8 @@
'use strict';
/**
* /look: your look on every OpenVibe site, in one place. The theme you wear (and the way to change it), Light / Dark /
-- * Auto, text size, motion and the season's themes. The settings belong to theme-loader.js (openvibe-shared), which
++ * Auto, text size, motion, the season's themes and the comfort settings (more contrast, a readable font, colour-blind-safe
++ * colours, true black). The settings belong to theme-loader.js (openvibe-shared), which
* applies them at once on this device and saves them to the account when the person is signed in, so every OpenVibe
* site follows. public/js/look.js only wires these controls to it. Without JavaScript the page says so.
*
@@@ -28,6 +29,18 @@ function lookPage({ themes = [], me = {} } = {}) {
+ kit.seg({ name: 'motion', label: 'Motion', options: [['auto', 'Full'], ['reduced', 'Reduced']], value: 'auto' })
+ kit.switchRow({ name: 'seasonal', label: 'The season\'s themes', hint: 'Halloween and winter stand in for the default theme while they last', on: true }),
});
++ // Comfort (openvibe-shared 4.45.0): how any theme reads for this person. The sample under the switches is ordinary page
++ // markup, so it changes as each switch does: quieter text, a link in running text, the three status colours.
++ const comfort = kit.section({
++ id: 'lk-comfort',
++ title: 'Comfort',
++ note: 'On top of any theme, on every OpenVibe site.',
++ body: kit.switchRow({ name: 'contrast', label: 'More contrast', hint: 'Quieter text and borders stand out more; links in text are underlined', on: false })
++ + kit.switchRow({ name: 'font', label: 'Readable font', hint: 'A typeface made for legibility, with more space between letters, words and lines', on: false })
++ + kit.switchRow({ name: 'colors', label: 'Colour-blind-safe colours', hint: 'Success, warning and danger in blue, yellow and orange, never red against green', on: false })
++ + kit.switchRow({ name: 'oled', label: 'True black', hint: 'Black backgrounds on dark themes, for OLED screens', on: false })
++ + `<div class="lk-sample" aria-label="A sample of how text and status colours read"><p>Body text, <span class="lk-sample-muted">quieter text</span> and <a href="/look#lk-comfort">a link in a sentence</a>.</p><p class="lk-sample-badges">${kit.badge('Working', 'ok')} ${kit.badge('Ends soon', 'warn')} ${kit.badge('Expired', 'bad')}</p></div>`,
++ });
const themeOpts = list.map((t) => `<option value="${esc(t.id)}">${esc(t.name)}</option>`).join('');
const sites = signedIn ? kit.section({
id: 'lk-sites',
@@@ -40,11 +53,11 @@ function lookPage({ themes = [], me = {} } = {}) {
const body = `<header class="ds-page-h"><p class="ds-kicker">Your look</p><h1>Your look, everywhere</h1>
<p class="ds-lede">One theme and one set of comfort settings for every OpenVibe site: Live, Chat, Games, the shops and the rest.</p></header>
<noscript>${kit.notice({ kind: 'info', text: 'These settings need JavaScript in this browser. Your theme still follows your account.' })}</noscript>
--<div class="lk" data-signed-in="${signedIn ? '1' : '0'}">${current}${settings}${sites}
++<div class="lk" data-signed-in="${signedIn ? '1' : '0'}">${current}${settings}${comfort}${sites}
<p class="lk-status" id="lk-status" role="status"></p>
${signedIn ? `<p class="ds-fine">Every change keeps the look it replaced: <a href="/studio#ds-history">your history</a> brings any of the last fifty back.</p>` : `<p>${kit.button({ href: '/auth/login?next=%2Flook', label: 'Sign in so it follows you', kind: 'quiet', small: true })}</p>`}</div>
<script type="application/json" id="lk-themes">${JSON.stringify(list).replace(/</g, '\\u003c')}</script>`;
-- return layout({ title: 'Your look', description: 'Your theme, light or dark, text size, motion and seasonal themes for every OpenVibe site, in one place.', path: '/look', body: `<div class="ds-wrap tk">${body}</div>`, active: '/look', scripts: ['js/look.js'] });
++ return layout({ title: 'Your look', description: 'Your theme, light or dark, text size, motion, seasonal themes and comfort settings (contrast, a readable font, colour-blind-safe colours, true black) for every OpenVibe site, in one place.', path: '/look', body: `<div class="ds-wrap tk">${body}</div>`, active: '/look', scripts: ['js/look.js'] });
}
module.exports = { lookPage, esc, SITES };