Split motion packs from accessibility overrides

This commit is contained in:
2026-03-20 12:03:46 +08:00
parent 010638503f
commit e5434bada9
8 changed files with 320 additions and 64 deletions
+61 -4
View File
@@ -18,10 +18,50 @@ export const themeDetails = {
}
} as const satisfies Record<ThemeName, { label: string; note: string }>;
export const motionModeNames = ["system", "reduced"] as const;
export type MotionModeName = (typeof motionModeNames)[number];
export const motionPackNames = ["calm", "snappy", "spring"] as const;
export type MotionPackName = (typeof motionPackNames)[number];
export const defaultMotionMode: MotionModeName = "system";
export const defaultMotionPack: MotionPackName = "calm";
export const motionPackDetails = {
calm: {
label: "Calm",
note: "Editorial default with restrained lift and steady transitions"
},
snappy: {
label: "Snappy",
note: "Shorter durations, tighter distances, and more direct response"
},
spring: {
label: "Spring",
note: "More elastic easing, wider movement, and livelier feedback"
}
} as const satisfies Record<MotionPackName, { label: string; note: string }>;
export const motionAccessibilityNames = ["system", "full", "reduced"] as const;
export type MotionAccessibilityName = (typeof motionAccessibilityNames)[number];
export const defaultMotionAccessibility: MotionAccessibilityName = "system";
export const motionAccessibilityDetails = {
system: {
label: "System",
note: "Follow the operating system reduced-motion preference"
},
full: {
label: "Full",
note: "Always show the selected motion pack, even if the OS prefers reduced motion"
},
reduced: {
label: "Reduced",
note: "Always collapse durations, distances, and animated feedback"
}
} as const satisfies Record<MotionAccessibilityName, { label: string; note: string }>;
export const motionModeNames = motionAccessibilityNames;
export type MotionModeName = MotionAccessibilityName;
export const defaultMotionMode: MotionModeName = defaultMotionAccessibility;
export const motionScale = {
instant: "var(--dur-instant)",
@@ -150,6 +190,16 @@ function getTargetElement(root?: HTMLElement) {
return document.documentElement;
}
export function setMotionPack(pack: MotionPackName, root?: HTMLElement) {
const target = getTargetElement(root);
if (!target) {
return;
}
target.dataset.motionPack = pack;
}
export function setTheme(theme: ThemeName, root?: HTMLElement) {
const target = getTargetElement(root);
@@ -160,7 +210,10 @@ export function setTheme(theme: ThemeName, root?: HTMLElement) {
target.dataset.theme = theme;
}
export function setMotionMode(mode: MotionModeName, root?: HTMLElement) {
export function setMotionAccessibility(
mode: MotionAccessibilityName,
root?: HTMLElement
) {
const target = getTargetElement(root);
if (!target) {
@@ -174,3 +227,7 @@ export function setMotionMode(mode: MotionModeName, root?: HTMLElement) {
target.dataset.motion = mode;
}
export function setMotionMode(mode: MotionModeName, root?: HTMLElement) {
setMotionAccessibility(mode, root);
}
+46 -1
View File
@@ -1,4 +1,5 @@
:root {
:root,
[data-motion-pack="calm"] {
--dur-instant: 1ms;
--dur-fast: 120ms;
--dur-base: 200ms;
@@ -19,6 +20,50 @@
--scale-pop: 1.02;
}
:root[data-motion-pack="snappy"],
[data-motion-pack="snappy"] {
--dur-instant: 1ms;
--dur-fast: 90ms;
--dur-base: 150ms;
--dur-slow: 220ms;
--dur-deliberate: 300ms;
--ease-standard: cubic-bezier(0.18, 1, 0.32, 1);
--ease-emphasized: cubic-bezier(0.2, 1.08, 0.28, 1);
--ease-exit: cubic-bezier(0.4, 0, 1, 1);
--distance-xs: 2px;
--distance-sm: 4px;
--distance-md: 10px;
--distance-lg: 16px;
--scale-press: 0.985;
--scale-hover: 1.006;
--scale-pop: 1.012;
}
:root[data-motion-pack="spring"],
[data-motion-pack="spring"] {
--dur-instant: 1ms;
--dur-fast: 140ms;
--dur-base: 220ms;
--dur-slow: 360ms;
--dur-deliberate: 520ms;
--ease-standard: cubic-bezier(0.2, 1.08, 0.28, 1);
--ease-emphasized: cubic-bezier(0.34, 1.56, 0.64, 1);
--ease-exit: cubic-bezier(0.42, 0, 1, 1);
--distance-xs: 6px;
--distance-sm: 12px;
--distance-md: 20px;
--distance-lg: 32px;
--scale-press: 0.96;
--scale-hover: 1.018;
--scale-pop: 1.035;
}
:root[data-motion="reduced"],
[data-motion="reduced"] {
--dur-instant: 1ms;