openvibers/openvibe.shared Commits
Add production motion tokens (#194)
Changes
@@@ -6,6 +6,10 @@ A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).## Unreleased++## 4.49.0 — 2026-10-30++++- **Shared motion tokens for production patterns.** Adds standard and back easing curves plus fast, base, slow, and reduced durations (180, 260, 360, and 0 ms).++## 4.48.0 — 2026-10-30- **The OpenVibe mark opens a site switcher.** The owner: "clicking the icon … its own drop-down … all the sites, so@@@ -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.48.0 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed++**Status:** alpha, v4.49.0 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployedconsumer 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` namesthe tag it pins.@@@ -4,7 +4,7 @@"code": true,"wave": "W2","package": "openvibe-shared",-- "version": "4.48.0",++ "version": "4.49.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)",@@@ -38,8 +38,9 @@ The kit's scales are the same on every theme:- `type.family.base` · `mono`- `type.size.caption` … `display`- `type.weight.*`--- `motion.duration.fast` · `base` · `slow`--- `motion.easing.standard`++- `motion.duration.fast` · `base` · `slow` (180 / 260 / 360 ms) · `reduced` (0 ms)++- `motion.easing.standard` (`cubic-bezier(.2,.7,.2,1)`) · `back` (`cubic-bezier(.34,1.56,.64,1)`)++- Native and web components also respect the system reduced-motion preference; the `reduced` duration is the token fallback.## Targets@@@ -1,6 +1,6 @@{"name": "openvibe-shared",-- "version": "4.48.0",++ "version": "4.49.0","description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site","main": "index.js","bin": {@@@ -18,7 +18,7 @@ for (const theme of BUILTIN_THEMES) {for (const [css] of tokens.SHADOW_MAP) if (theme.variables[css] && tokens.parseShadow(theme.variables[css])) assert.ok(back.variables[css], `${theme.slug} ${css} survives`);assert.strictEqual(back.mode, theme.mode === 'light' ? 'light' : 'dark');assert.strictEqual(doc['color'].bg.base.$type, 'color');-- assert.ok(doc.radius.md.$value === '14px' && doc.motion.duration.fast.$value === '150ms' && doc.size.tap.$value === '44px', 'the kit scales ride along');++ assert.ok(doc.radius.md.$value === '14px' && doc.motion.duration.fast.$value === '180ms' && doc.motion.duration.base.$value === '260ms' && doc.motion.duration.slow.$value === '360ms' && doc.motion.duration.reduced.$value === '0ms' && doc.motion.easing.back.$value.join(',') === '0.34,1.56,0.64,1' && doc.size.tap.$value === '44px', 'the kit scales ride along');}console.log(`✓ ${BUILTIN_THEMES.length} built-in themes round-trip`);@@@ -51,7 +51,7 @@ assert.match(swift, /^import SwiftUI$/m);assert.match(swift, /public enum VibeTokens \{/);assert.match(swift, /public static let colorScheme: ColorScheme = \.dark/);assert.match(swift, /public static let colorAccentBase = Color\(\.sRGB, red: 0\.231, green: 0\.51, blue: 0\.965, opacity: 1\)/);--assert.match(swift, /public enum OvScale \{[\s\S]*public static let motionDurationFast: Double = 0\.15/);++assert.match(swift, /public enum OvScale \{[\s\S]*public static let motionDurationFast: Double = 0\.18/);const dart = tokens.compile(vibe, 'flutter');assert.match(dart, /static const colorBgBase = Color\(0xFF0A0F1C\);/);assert.match(dart, /const vibeDarkScheme = ColorScheme\(\n {2}brightness: Brightness\.dark,/);@@@ -83,8 +83,12 @@weight: { $type: 'fontWeight', regular: 400, medium: 600, bold: 700, heavy: 800 },},motion: {-- duration: { $type: 'duration', fast: 150, base: 250, slow: 400 },-- easing: { $type: 'cubicBezier', standard: [0.2, 0.7, 0.2, 1] },++ duration: { $type: 'duration', fast: 180, base: 260, slow: 360, reduced: 0 },++ easing: {++ $type: 'cubicBezier',++ standard: [0.2, 0.7, 0.2, 1],++ back: [0.34, 1.56, 0.64, 1],++ },},};
@@ -6,6 +6,10 @@ A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
@@ -6,6 +6,10 @@ A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
## Unreleased
## Unreleased
+## 4.49.0 — 2026-10-30
+
+- **Shared motion tokens for production patterns.** Adds standard and back easing curves plus fast, base, slow, and reduced durations (180, 260, 360, and 0 ms).
+
## 4.48.0 — 2026-10-30
## 4.48.0 — 2026-10-30
- **The OpenVibe mark opens a site switcher.** The owner: "clicking the icon … its own drop-down … all the sites, so
- **The OpenVibe mark opens a site switcher.** The owner: "clicking the icon … its own drop-down … all the sites, so
@@ -2,7 +2,7 @@
@@ -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.
> 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.48.0 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed
+**Status:** alpha, v4.49.0 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed
consumer installs a tagged release and none keeps a vendored copy
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
([docs/migration-plan.md](docs/migration-plan.md) is done); each repository's `package.json` names
the tag it pins.
the tag it pins.
@@ -4,7 +4,7 @@
@@ -4,7 +4,7 @@
"code": true,
"code": true,
"wave": "W2",
"wave": "W2",
"package": "openvibe-shared",
"package": "openvibe-shared",
- "version": "4.48.0",
+ "version": "4.49.0",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"deployed": false,
"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)",
"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)",
@@ -38,8 +38,9 @@ The kit's scales are the same on every theme:
@@ -38,8 +38,9 @@ The kit's scales are the same on every theme:
- `type.family.base` · `mono`
- `type.family.base` · `mono`
- `type.size.caption` … `display`
- `type.size.caption` … `display`
- `type.weight.*`
- `type.weight.*`
-- `motion.duration.fast` · `base` · `slow`
-- `motion.easing.standard`
+- `motion.duration.fast` · `base` · `slow` (180 / 260 / 360 ms) · `reduced` (0 ms)
+- `motion.easing.standard` (`cubic-bezier(.2,.7,.2,1)`) · `back` (`cubic-bezier(.34,1.56,.64,1)`)
+- Native and web components also respect the system reduced-motion preference; the `reduced` duration is the token fallback.
## Targets
## Targets
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-shared",
"name": "openvibe-shared",
- "version": "4.48.0",
+ "version": "4.49.0",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"main": "index.js",
"main": "index.js",
"bin": {
"bin": {
@@ -18,7 +18,7 @@ for (const theme of BUILTIN_THEMES) {
@@ -18,7 +18,7 @@ for (const theme of BUILTIN_THEMES) {
for (const [css] of tokens.SHADOW_MAP) if (theme.variables[css] && tokens.parseShadow(theme.variables[css])) assert.ok(back.variables[css], `${theme.slug} ${css} survives`);
for (const [css] of tokens.SHADOW_MAP) if (theme.variables[css] && tokens.parseShadow(theme.variables[css])) assert.ok(back.variables[css], `${theme.slug} ${css} survives`);
assert.strictEqual(back.mode, theme.mode === 'light' ? 'light' : 'dark');
assert.strictEqual(back.mode, theme.mode === 'light' ? 'light' : 'dark');
assert.strictEqual(doc['color'].bg.base.$type, 'color');
assert.strictEqual(doc['color'].bg.base.$type, 'color');
- assert.ok(doc.radius.md.$value === '14px' && doc.motion.duration.fast.$value === '150ms' && doc.size.tap.$value === '44px', 'the kit scales ride along');
+ assert.ok(doc.radius.md.$value === '14px' && doc.motion.duration.fast.$value === '180ms' && doc.motion.duration.base.$value === '260ms' && doc.motion.duration.slow.$value === '360ms' && doc.motion.duration.reduced.$value === '0ms' && doc.motion.easing.back.$value.join(',') === '0.34,1.56,0.64,1' && doc.size.tap.$value === '44px', 'the kit scales ride along');
}
}
console.log(`✓ ${BUILTIN_THEMES.length} built-in themes round-trip`);
console.log(`✓ ${BUILTIN_THEMES.length} built-in themes round-trip`);
@@ -51,7 +51,7 @@ assert.match(swift, /^import SwiftUI$/m);
@@ -51,7 +51,7 @@ assert.match(swift, /^import SwiftUI$/m);
assert.match(swift, /public enum VibeTokens \{/);
assert.match(swift, /public enum VibeTokens \{/);
assert.match(swift, /public static let colorScheme: ColorScheme = \.dark/);
assert.match(swift, /public static let colorScheme: ColorScheme = \.dark/);
assert.match(swift, /public static let colorAccentBase = Color\(\.sRGB, red: 0\.231, green: 0\.51, blue: 0\.965, opacity: 1\)/);
assert.match(swift, /public static let colorAccentBase = Color\(\.sRGB, red: 0\.231, green: 0\.51, blue: 0\.965, opacity: 1\)/);
-assert.match(swift, /public enum OvScale \{[\s\S]*public static let motionDurationFast: Double = 0\.15/);
+assert.match(swift, /public enum OvScale \{[\s\S]*public static let motionDurationFast: Double = 0\.18/);
const dart = tokens.compile(vibe, 'flutter');
const dart = tokens.compile(vibe, 'flutter');
assert.match(dart, /static const colorBgBase = Color\(0xFF0A0F1C\);/);
assert.match(dart, /static const colorBgBase = Color\(0xFF0A0F1C\);/);
assert.match(dart, /const vibeDarkScheme = ColorScheme\(\n {2}brightness: Brightness\.dark,/);
assert.match(dart, /const vibeDarkScheme = ColorScheme\(\n {2}brightness: Brightness\.dark,/);
@@ -83,8 +83,12 @@
@@ -83,8 +83,12 @@
weight: { $type: 'fontWeight', regular: 400, medium: 600, bold: 700, heavy: 800 },
weight: { $type: 'fontWeight', regular: 400, medium: 600, bold: 700, heavy: 800 },
},
},
motion: {
motion: {
- duration: { $type: 'duration', fast: 150, base: 250, slow: 400 },
- easing: { $type: 'cubicBezier', standard: [0.2, 0.7, 0.2, 1] },
+ duration: { $type: 'duration', fast: 180, base: 260, slow: 360, reduced: 0 },
+ easing: {
+ $type: 'cubicBezier',
+ standard: [0.2, 0.7, 0.2, 1],
+ back: [0.34, 1.56, 0.64, 1],
+ },
},
},
};
};