openvibers/openvibe.shared Commits

The motion tokens on every page; Reduced motion reaches every token-timed transition (4.82.0) (#235)

OP OpenVibers committed 12 days ago · 3cb1234892 · 7 files, +54 −4

--ov-dur-1..4 and the three curves were set only by ov-fx.js, which loads on pages with effects, so elsewhere a
site's var(--ov-dur-2, .2s) got its fallback and the person's Reduced setting could not reach it. kit.css (and
room.css) now set the same tokens and feels; html[data-ov-motion=reduced] and a device that asks for less set
every duration to 0.

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex d1be49f..6d2929a 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -4,6 +4,20 @@ All notable changes to `openvibe-shared`. Versions follow [semver](https://semve
breaking change to any exported module, browser global or served file name is a new major.
A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
++## 4.82.0 — 2026-11-01
++
++- **The motion tokens are on every page, and Reduced motion reaches every token-timed transition** (plan L45).
++ - Before this release, `--ov-dur-1..4` and `--ov-ease-out`/`-spring`/`-in-out` were set only by `ov-fx.js`, which
++ loads on pages with effects. Everywhere else a site's `var(--ov-dur-2, .2s)` got its fallback, so the person's
++ Reduced setting could not reach it.
++ - `kit.css` now sets the same tokens, with the same values, and the same feels: calm looks are slower and never
++ overshoot, loud ones are quicker.
++ - `html[data-ov-motion=reduced]` sets every duration to 0, and so does a device that asks for reduced motion
++ (`:root:root`, above `ov-fx.js`'s own `:root`).
++ - A site that writes its transitions with the tokens now follows the look and the person's choice. The design lint
++ (openvibe.report/design) counts hand-set timings.
++ - `room.css` carries the same tokens.
++
## 4.81.0 — 2026-11-01
- **Shape and elevation are tokens, and a look has a shape** (plan L45 step 2: "Paper is quiet and square, Neon glows
ddiff --git a/README.md b/README.md
iindex 6a03f53..382c241 100644
---- a/README.md
++++ b/README.md
@@@ -2,7 +2,7 @@
> Versioned UI, the OpenVibe Frame (the navbar, footer and "shipped" views every site sits in), SEO, legal and release-client packages every OpenVibe site renders.
--**Status:** alpha, v4.81.0 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed
++**Status:** alpha, v4.82.0 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed
consumer installs a tagged release and none keeps a vendored copy
([docs/migration-plan.md](docs/migration-plan.md) is done); each repository's `package.json` names
the tag it pins.
ddiff --git a/STATUS.json b/STATUS.json
iindex e9426ef..3df93b3 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -4,7 +4,7 @@
"code": true,
"wave": "W2",
"package": "openvibe-shared",
-- "version": "4.81.0",
++ "version": "4.82.0",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"deployed": false,
"deployment": "none of its own: a package released as git tags; OpenVibe.Network serves /shared/* from its pinned tag, and a site can serve its own pinned copy (openvibe-shared/serve)",
ddiff --git a/kit.css b/kit.css
iindex 99c63dc..c1cda01 100644
---- a/kit.css
++++ b/kit.css
@@@ -33,6 +33,15 @@
--ov-elev-1: 0 1px 3px rgba(0, 0, 0, .35); /* a knob, a chip that sits on its surface */
--ov-elev-2: 0 10px 24px -18px rgba(0, 0, 0, .7); /* a bar that has scrolled content under it */
--ov-elev-3: 0 14px 32px rgba(0, 0, 0, .4); /* a menu or popover above the page */
++ /* Motion (4.82.0): the same tokens ov-fx.js has always set, here so every page's var(--ov-dur-*) resolves and the
++ * person's Reduced motion reaches every transition that uses them, not only pages with effects. */
++ --ov-dur-1: .12s;
++ --ov-dur-2: .2s;
++ --ov-dur-3: .32s;
++ --ov-dur-4: .52s;
++ --ov-ease-out: cubic-bezier(.2, .8, .2, 1);
++ --ov-ease-spring: cubic-bezier(.34, 1.56, .64, 1);
++ --ov-ease-in-out: cubic-bezier(.65, 0, .35, 1);
--ovk-radius: var(--ov-radius-2);
--ovk-radius-sm: var(--ov-radius-1);
--ovk-tap: 44px;
@@@ -41,6 +50,17 @@
--ovk-font: var(--ov-font, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif);
}
++/* Motion feels, as ov-fx.js sets them: the calm looks are slower and never overshoot, the loud ones quicker; the
++ * person's Reduced motion, or a device that asks for less, stops every token-timed transition. */
++:is([data-theme=paper], [data-theme=daylight], [data-theme=cloud], [data-theme=snow], [data-theme=sand], [data-theme=rose], [data-theme=meadow], [data-theme=peach], [data-theme=lavender], [data-theme=dawn], [data-theme=solarized-light], [data-theme=catppuccin-latte], [data-theme=nord], [data-theme=nord-light]) {
++ --ov-dur-1: .15s; --ov-dur-2: .25s; --ov-dur-3: .4s; --ov-dur-4: .62s; --ov-ease-spring: var(--ov-ease-out);
++}
++:is([data-theme=neon-tokyo], [data-theme=vapor], [data-theme=matrix], [data-theme=hacker], [data-theme=high-contrast], [data-theme=dracula], [data-theme=monokai], [data-theme=abyss]) {
++ --ov-dur-1: .09s; --ov-dur-2: .15s; --ov-dur-3: .24s; --ov-dur-4: .42s; --ov-ease-spring: cubic-bezier(.3, 1.8, .6, 1);
++}
++html[data-ov-motion=reduced] { --ov-dur-1: 0s; --ov-dur-2: 0s; --ov-dur-3: 0s; --ov-dur-4: 0s; }
++/* :root:root outranks ov-fx.js's own :root and theme feels, which load later. */
++@media (prefers-reduced-motion: reduce) { :root:root { --ov-dur-1: 0s; --ov-dur-2: 0s; --ov-dur-3: 0s; --ov-dur-4: 0s; } }
/* Shape personalities (plan L45: "Paper is quiet and square, Neon glows and bounces"). A quiet look has square corners
* and lies flat, with a hairline where a shadow would be; a loud one is round and its raised things glow in its accent.
* The ids are Network's theme catalog (as ov-fx.js's motion feels); any other look keeps the defaults above. */
ddiff --git a/package.json b/package.json
iindex 7bdcec6..e42d828 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-shared",
-- "version": "4.81.0",
++ "version": "4.82.0",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"main": "index.js",
"bin": {
ddiff --git a/room.css b/room.css
iindex 3e733aa..802f5a4 100644
---- a/room.css
++++ b/room.css
@@@ -30,6 +30,15 @@
--ov-elev-1: 0 1px 3px rgba(0, 0, 0, .35); /* a knob, a chip that sits on its surface */
--ov-elev-2: 0 10px 24px -18px rgba(0, 0, 0, .7); /* a bar that has scrolled content under it */
--ov-elev-3: 0 14px 32px rgba(0, 0, 0, .4); /* a menu or popover above the page */
++ /* Motion (4.82.0): the same tokens ov-fx.js has always set, here so every page's var(--ov-dur-*) resolves and the
++ * person's Reduced motion reaches every transition that uses them, not only pages with effects. */
++ --ov-dur-1: .12s;
++ --ov-dur-2: .2s;
++ --ov-dur-3: .32s;
++ --ov-dur-4: .52s;
++ --ov-ease-out: cubic-bezier(.2, .8, .2, 1);
++ --ov-ease-spring: cubic-bezier(.34, 1.56, .64, 1);
++ --ov-ease-in-out: cubic-bezier(.65, 0, .35, 1);
--ovk-radius: var(--ov-radius-2);
--ovk-radius-sm: var(--ov-radius-1);
--ovk-tap: 44px;
ddiff --git a/test/kit-shape.test.js b/test/kit-shape.test.js
iindex 0f32d26..866bc91 100644
---- a/test/kit-shape.test.js
++++ b/test/kit-shape.test.js
@@@ -26,4 +26,11 @@ assert.match(kit, /:is\(\[data-theme=neon-tokyo\][^{]*\) \{\s*--ov-radius-1: 14p
assert.match(kit, /--ov-elev-3: 0 0 0 1px color-mix\(in srgb, var\(--ovk-accent\)/, 'and Neon\'s raised things glow in its accent');
assert.match(room, /:where\(\[data-theme=paper\][^{]*\) \{\s*--ov-radius-1: 4px;/, 'room.css: the same personalities at zero specificity');
assert.match(room, /:where\(\[data-theme=neon-tokyo\][^{]*\) \{\s*--ov-radius-1: 14px;/);
--console.log('kit-shape: tokens, the kit on them, and the personalities');
++// Motion (4.82.0): ov-fx.js's tokens, in kit.css too, so var(--ov-dur-*) resolves on every page and Reduced reaches it.
++assert.ok(kit.includes('--ov-dur-1: .12s;') && kit.includes('--ov-dur-4: .52s;') && kit.includes('--ov-ease-out: cubic-bezier(.2, .8, .2, 1);'), 'the motion tokens, as ov-fx.js sets them');
++assert.match(kit, /html\[data-ov-motion=reduced\] \{ --ov-dur-1: 0s;/, 'Reduced motion stops them');
++assert.match(kit, /@media \(prefers-reduced-motion: reduce\) \{ :root:root \{ --ov-dur-1: 0s;/, 'and so does a device that asks for less, over ov-fx.js\'s own :root');
++assert.match(kit, /:is\(\[data-theme=paper\][^{]*\) \{\s*--ov-dur-1: \.15s;/, 'Paper is calm');
++const fx = fs.readFileSync(path.join(__dirname, '..', 'ov-fx.js'), 'utf8');
++assert.ok(fx.includes('--ov-dur-1:.12s;--ov-dur-2:.2s;--ov-dur-3:.32s;--ov-dur-4:.52s'), 'the same values as ov-fx.js');
++console.log('kit-shape: tokens, the kit on them, the personalities and the motion');