@carbon/motion 11.49.0 → 11.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,99 @@
1
+ // Code generated by @carbon/motion. DO NOT EDIT.
2
+ //
3
+ // Copyright IBM Corp. 2018, 2026
4
+ //
5
+ // This source code is licensed under the Apache-2.0 license found in the
6
+ // LICENSE file in the root directory of this source tree.
7
+ //
8
+
9
+ /// Common component easings
10
+ /// @type Map
11
+ /// @access public
12
+ /// @group @carbon/motion
13
+ $easings: (
14
+ standard: (
15
+ productive: cubic-bezier(0.2, 0, 0.38, 0.9),
16
+ expressive: cubic-bezier(0.4, 0.14, 0.3, 1),
17
+ ),
18
+ entrance: (
19
+ productive: cubic-bezier(0, 0, 0.38, 0.9),
20
+ expressive: cubic-bezier(0, 0, 0.3, 1),
21
+ ),
22
+ exit: (
23
+ productive: cubic-bezier(0.2, 0, 1, 0.9),
24
+ expressive: cubic-bezier(0.4, 0.14, 1, 1),
25
+ ),
26
+ ) !default;
27
+
28
+ /// Micro-interactions such as button and toggle. Instant response to user action.
29
+ /// @access public
30
+ /// @type Duration
31
+ /// @group @carbon/motion
32
+ $duration-fast-01: 70ms !default;
33
+
34
+ /// Micro-interactions such as fade in. Subtle entrance or exit of small UI elements.
35
+ /// @access public
36
+ /// @type Duration
37
+ /// @group @carbon/motion
38
+ $duration-fast-02: 110ms !default;
39
+
40
+ /// Micro-interactions, small expansion, short distance movements. Default transition speed.
41
+ /// @access public
42
+ /// @type Duration
43
+ /// @group @carbon/motion
44
+ $duration-moderate-01: 150ms !default;
45
+
46
+ /// Expansion, system communication, toast. Slightly longer interactions with more visual weight.
47
+ /// @access public
48
+ /// @type Duration
49
+ /// @group @carbon/motion
50
+ $duration-moderate-02: 240ms !default;
51
+
52
+ /// Large expansion, important system notifications. Deliberate, prominent transitions.
53
+ /// @access public
54
+ /// @type Duration
55
+ /// @group @carbon/motion
56
+ $duration-slow-01: 400ms !default;
57
+
58
+ /// Background dimming, large hero transitions. Slow, immersive motion for maximum emphasis.
59
+ /// @access public
60
+ /// @type Duration
61
+ /// @group @carbon/motion
62
+ $duration-slow-02: 700ms !default;
63
+
64
+ /// V10 backwards compatibility tokens
65
+ /// @access public
66
+ /// @deprecated
67
+ /// @type Duration
68
+ /// @group @carbon/motion
69
+ $fast-01: $duration-fast-01 !default;
70
+
71
+ /// @access public
72
+ /// @deprecated
73
+ /// @type Duration
74
+ /// @group @carbon/motion
75
+ $fast-02: $duration-fast-02 !default;
76
+
77
+ /// @access public
78
+ /// @deprecated
79
+ /// @type Duration
80
+ /// @group @carbon/motion
81
+ $moderate-01: $duration-moderate-01 !default;
82
+
83
+ /// @access public
84
+ /// @deprecated
85
+ /// @type Duration
86
+ /// @group @carbon/motion
87
+ $moderate-02: $duration-moderate-02 !default;
88
+
89
+ /// @access public
90
+ /// @deprecated
91
+ /// @type Duration
92
+ /// @group @carbon/motion
93
+ $slow-01: $duration-slow-01 !default;
94
+
95
+ /// @access public
96
+ /// @deprecated
97
+ /// @type Duration
98
+ /// @group @carbon/motion
99
+ $slow-02: $duration-slow-02 !default;
@@ -0,0 +1,80 @@
1
+ {
2
+ "$schema": "https://tr.designtokens.org/format/",
3
+ "$description": "Motion tokens for the Carbon Design System — durations and easing curves",
4
+ "duration": {
5
+ "fast": {
6
+ "01": {
7
+ "$type": "duration",
8
+ "$value": { "value": 70, "unit": "ms" },
9
+ "$description": "Micro-interactions such as button and toggle. Instant response to user action."
10
+ },
11
+ "02": {
12
+ "$type": "duration",
13
+ "$value": { "value": 110, "unit": "ms" },
14
+ "$description": "Micro-interactions such as fade in. Subtle entrance or exit of small UI elements."
15
+ }
16
+ },
17
+ "moderate": {
18
+ "01": {
19
+ "$type": "duration",
20
+ "$value": { "value": 150, "unit": "ms" },
21
+ "$description": "Micro-interactions, small expansion, short distance movements. Default transition speed."
22
+ },
23
+ "02": {
24
+ "$type": "duration",
25
+ "$value": { "value": 240, "unit": "ms" },
26
+ "$description": "Expansion, system communication, toast. Slightly longer interactions with more visual weight."
27
+ }
28
+ },
29
+ "slow": {
30
+ "01": {
31
+ "$type": "duration",
32
+ "$value": { "value": 400, "unit": "ms" },
33
+ "$description": "Large expansion, important system notifications. Deliberate, prominent transitions."
34
+ },
35
+ "02": {
36
+ "$type": "duration",
37
+ "$value": { "value": 700, "unit": "ms" },
38
+ "$description": "Background dimming, large hero transitions. Slow, immersive motion for maximum emphasis."
39
+ }
40
+ }
41
+ },
42
+ "easing": {
43
+ "standard": {
44
+ "productive": {
45
+ "$type": "cubicBezier",
46
+ "$value": [0.2, 0, 0.38, 0.9],
47
+ "$description": "Standard easing for productive motion. Used for UI elements that move within the viewport."
48
+ },
49
+ "expressive": {
50
+ "$type": "cubicBezier",
51
+ "$value": [0.4, 0.14, 0.3, 1],
52
+ "$description": "Standard easing for expressive motion. Used for elements with more prominent, fluid movement."
53
+ }
54
+ },
55
+ "entrance": {
56
+ "productive": {
57
+ "$type": "cubicBezier",
58
+ "$value": [0, 0, 0.38, 0.9],
59
+ "$description": "Entrance easing for productive motion. Used when elements enter the screen."
60
+ },
61
+ "expressive": {
62
+ "$type": "cubicBezier",
63
+ "$value": [0, 0, 0.3, 1],
64
+ "$description": "Entrance easing for expressive motion. Used for prominent element entrances."
65
+ }
66
+ },
67
+ "exit": {
68
+ "productive": {
69
+ "$type": "cubicBezier",
70
+ "$value": [0.2, 0, 1, 0.9],
71
+ "$description": "Exit easing for productive motion. Used when elements leave the screen."
72
+ },
73
+ "expressive": {
74
+ "$type": "cubicBezier",
75
+ "$value": [0.4, 0.14, 1, 1],
76
+ "$description": "Exit easing for expressive motion. Used for prominent element exits."
77
+ }
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,100 @@
1
+ {
2
+ "$schema": "https://tr.designtokens.org/format/",
3
+ "$description": "Motion surface recipes for Carbon — composite transition intents built from primitive duration and easing tokens.",
4
+ "surface": {
5
+ "disclosure": {
6
+ "$type": "transition",
7
+ "$value": {
8
+ "duration": "{duration.moderate.01}",
9
+ "delay": { "value": 0, "unit": "ms" },
10
+ "timingFunction": "{easing.entrance.productive}"
11
+ },
12
+ "$description": "Accordion, table-row expand — reveal in place.",
13
+ "$extensions": {
14
+ "carbon.motion": {
15
+ "kind": "reveal",
16
+ "duration": "moderate-01",
17
+ "enter": { "blockSize": "auto", "opacity": 1 },
18
+ "exit": { "blockSize": 0, "opacity": 0 },
19
+ "enterEasing": ["entrance", "productive"],
20
+ "exitEasing": ["exit", "productive"]
21
+ }
22
+ }
23
+ },
24
+ "contextual": {
25
+ "$type": "transition",
26
+ "$value": {
27
+ "duration": "{duration.fast.02}",
28
+ "delay": { "value": 0, "unit": "ms" },
29
+ "timingFunction": "{easing.entrance.expressive}"
30
+ },
31
+ "$description": "Icon → tooltip/popover — fade and scale reveal.",
32
+ "$extensions": {
33
+ "carbon.motion": {
34
+ "kind": "reveal",
35
+ "duration": "fast-02",
36
+ "enter": { "opacity": 1, "transform": "scale(1)" },
37
+ "exit": { "opacity": 0, "transform": "scale(0.96)" },
38
+ "enterEasing": ["entrance", "expressive"],
39
+ "exitEasing": ["exit", "expressive"]
40
+ }
41
+ }
42
+ },
43
+ "stretch": {
44
+ "$type": "transition",
45
+ "$value": {
46
+ "duration": "{duration.slow.01}",
47
+ "delay": { "value": 0, "unit": "ms" },
48
+ "timingFunction": "{easing.entrance.expressive}"
49
+ },
50
+ "$description": "Component reveal stretching from the vertical axis.",
51
+ "$extensions": {
52
+ "carbon.motion": {
53
+ "kind": "reveal",
54
+ "duration": "slow-01",
55
+ "enter": { "opacity": 1, "clipPath": "inset(0 0 0 0)" },
56
+ "exit": { "opacity": 0, "clipPath": "inset(50% 0 50% 0)" },
57
+ "enterEasing": ["entrance", "expressive"],
58
+ "exitEasing": ["exit", "expressive"]
59
+ }
60
+ }
61
+ },
62
+ "expand": {
63
+ "$type": "transition",
64
+ "$value": {
65
+ "duration": "{duration.moderate.02}",
66
+ "delay": { "value": 0, "unit": "ms" },
67
+ "timingFunction": "{easing.standard.productive}"
68
+ },
69
+ "$description": "Card/tile → side-panel/tearsheet — shared-element morph.",
70
+ "$extensions": {
71
+ "carbon.motion": {
72
+ "kind": "shared-element",
73
+ "duration": "moderate-02",
74
+ "enter": { "opacity": 1, "transform": "scale(1)" },
75
+ "exit": { "opacity": 0, "transform": "scale(0.96)" },
76
+ "enterEasing": ["standard", "productive"],
77
+ "exitEasing": ["standard", "productive"]
78
+ }
79
+ }
80
+ },
81
+ "invoke": {
82
+ "$type": "transition",
83
+ "$value": {
84
+ "duration": "{duration.moderate.02}",
85
+ "delay": { "value": 0, "unit": "ms" },
86
+ "timingFunction": "{easing.standard.expressive}"
87
+ },
88
+ "$description": "Button → modal/menu/popover — shared-element morph from the trigger.",
89
+ "$extensions": {
90
+ "carbon.motion": {
91
+ "kind": "shared-element",
92
+ "origin": "trigger",
93
+ "duration": "moderate-02",
94
+ "enterEasing": ["standard", "expressive"],
95
+ "exitEasing": ["standard", "expressive"]
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
package/src/surfaces.ts CHANGED
@@ -5,15 +5,23 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import type { DurationName, EasingMode, EasingName } from './tokens';
8
+ // Surface definitions are generated from src/dtcg/surfaces.json by
9
+ // `yarn build:tokens` (tasks/build.js) and written to
10
+ // js/generated/surfaces.js before this file is bundled.
11
+ // Run `yarn build` to regenerate them.
12
+ export { surfaces, getMotionSurface } from '../js/generated/surfaces.js';
13
+
14
+ // ── TypeScript types ─────────────────────────────────────────────────────────
15
+ // These are hand-authored here rather than generated because they describe the
16
+ // Carbon-specific structure of a surface recipe and are referenced by consumers
17
+ // who need to type-check against the surface API.
18
+
19
+ import type { DurationName, EasingName, EasingMode } from './tokens';
9
20
 
10
21
  type MotionEasing = readonly [EasingName, EasingMode];
11
22
 
12
- /**
13
- * from/to styles for reveal surface - plain CSS property/value pairs
14
- * keep values engine-neutral so CSS, WAAPI, and Motion can all consume
15
- * them
16
- */
23
+ // from/to styles for reveal surface - plain CSS property/value pairs
24
+ // keep values engine-neutral so CSS, WAAPI, and Motion can all consume them
17
25
  type RevealKeyframe = Record<string, string | number>;
18
26
 
19
27
  interface MotionSurfaceBase {
@@ -43,74 +51,9 @@ interface SharedElementSurface extends MotionSurfaceBase {
43
51
  }
44
52
 
45
53
  export type MotionSurfaceDefinition = SharedElementSurface | RevealSurface;
46
-
47
- /**
48
- * Named motion intents. These definitions are engine and framework agnostic.
49
- *
50
- * `prefers-reduced-motion` is intentionally not represented here: surfaces
51
- * never animate when the users request reduced motion. Framework adapters
52
- * bail before running, and the Sass output is wrapped in a
53
- * `prefers-reduced-motion: no-preference` media query
54
- */
55
- export const surfaces = {
56
- // Accordion, table-row expand - reveal in place
57
- disclosure: {
58
- kind: 'reveal',
59
- duration: 'moderate-01',
60
- enter: { blockSize: 'auto', opacity: 1 },
61
- exit: { blockSize: 0, opacity: 0 },
62
- enterEasing: ['entrance', 'productive'],
63
- exitEasing: ['exit', 'productive'],
64
- },
65
- // Icon > tooltip/popover
66
- contextual: {
67
- kind: 'reveal',
68
- duration: 'fast-02',
69
- enter: { opacity: 1, transform: 'scale(1)' },
70
- exit: { opacity: 0, transform: 'scale(0.96)' },
71
- enterEasing: ['entrance', 'expressive'],
72
- exitEasing: ['exit', 'expressive'],
73
- },
74
- // Component reveal, "stretching" from vertical axis
75
- stretch: {
76
- kind: 'reveal',
77
- duration: 'slow-01',
78
- enter: { opacity: 1, clipPath: 'inset(0 0 0 0)' },
79
- exit: { opacity: 0, clipPath: 'inset(50% 0 50% 0)' },
80
- enterEasing: ['entrance', 'expressive'],
81
- exitEasing: ['exit', 'expressive'],
82
- },
83
- // Card/tile > side-panel/tearsheet
84
- expand: {
85
- kind: 'shared-element',
86
- duration: 'moderate-02',
87
- enter: { opacity: 1, transform: 'scale(1)' },
88
- exit: { opacity: 0, transform: 'scale(0.96)' },
89
- enterEasing: ['standard', 'productive'],
90
- exitEasing: ['standard', 'productive'],
91
- },
92
- // Button > modal/menu/popover - morphs from the trigger
93
- invoke: {
94
- kind: 'shared-element',
95
- origin: 'trigger',
96
- duration: 'moderate-02',
97
- enterEasing: ['standard', 'expressive'],
98
- exitEasing: ['standard', 'expressive'],
99
- },
100
- } as const satisfies Record<string, MotionSurfaceDefinition>;
101
-
102
- export type MotionSurfaceName = keyof typeof surfaces;
103
-
104
- // Give JavaScript consumers a clear error for an unknown surface name.
105
- export const getMotionSurface = (name: MotionSurfaceName) => {
106
- const surface = surfaces[name];
107
-
108
- if (!surface) {
109
- throw new Error(
110
- `Unable to find motion surface \`${name}\`. Expected one of: ` +
111
- Object.keys(surfaces).join(', ')
112
- );
113
- }
114
-
115
- return surface;
116
- };
54
+ export type MotionSurfaceName =
55
+ | 'disclosure'
56
+ | 'contextual'
57
+ | 'stretch'
58
+ | 'expand'
59
+ | 'invoke';
package/src/tokens.ts CHANGED
@@ -5,35 +5,35 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- export const fast01 = '70ms';
9
- export const fast02 = '110ms';
10
- export const moderate01 = '150ms';
11
- export const moderate02 = '240ms';
12
- export const slow01 = '400ms';
13
- export const slow02 = '700ms';
14
-
15
- // V11 Tokens
16
- export const durationFast01 = fast01;
17
- export const durationFast02 = fast02;
18
- export const durationModerate01 = moderate01;
19
- export const durationModerate02 = moderate02;
20
- export const durationSlow01 = slow01;
21
- export const durationSlow02 = slow02;
22
-
23
- export const unstable_tokens = [
24
- 'fast01',
25
- 'fast02',
26
- 'moderate01',
27
- 'moderate02',
28
- 'slow01',
29
- 'slow02',
30
- 'durationFast01',
31
- 'durationFast02',
32
- 'durationModerate01',
33
- 'durationModerate02',
34
- 'durationSlow01',
35
- 'durationSlow02',
36
- ] as const;
8
+ // Token values are generated from src/dtcg/motion.json by `yarn build:tokens`
9
+ // (tasks/build.js) and written to js/generated/tokens.js before this file is
10
+ // bundled. Run `yarn build` to regenerate them.
11
+ import {
12
+ durationFast01,
13
+ durationFast02,
14
+ durationModerate01,
15
+ durationModerate02,
16
+ durationSlow01,
17
+ durationSlow02,
18
+ easings,
19
+ } from '../js/generated/tokens.js';
20
+
21
+ export {
22
+ durationFast01,
23
+ durationFast02,
24
+ durationModerate01,
25
+ durationModerate02,
26
+ durationSlow01,
27
+ durationSlow02,
28
+ fast01,
29
+ fast02,
30
+ moderate01,
31
+ moderate02,
32
+ slow01,
33
+ slow02,
34
+ easings,
35
+ unstable_tokens,
36
+ } from '../js/generated/tokens.js';
37
37
 
38
38
  export type DurationName =
39
39
  | 'fast-01'
@@ -43,6 +43,11 @@ export type DurationName =
43
43
  | 'slow-01'
44
44
  | 'slow-02';
45
45
 
46
+ export type EasingName = 'standard' | 'entrance' | 'exit';
47
+ export type EasingMode = 'productive' | 'expressive';
48
+ export type CubicBezier = readonly [number, number, number, number];
49
+ export type EasingMap = Record<EasingName, Record<EasingMode, string>>;
50
+
46
51
  // Map the surface names to the existing Carbon duration tokens.
47
52
  const durations: Record<DurationName, string> = {
48
53
  'fast-01': durationFast01,
@@ -53,13 +58,10 @@ const durations: Record<DurationName, string> = {
53
58
  'slow-02': durationSlow02,
54
59
  };
55
60
 
56
- export type EasingName = 'standard' | 'entrance' | 'exit';
57
- export type EasingMode = 'productive' | 'expressive';
58
- export type CubicBezier = readonly [number, number, number, number];
59
- export type EasingMap = Record<EasingName, Record<EasingMode, string>>;
60
61
  type EasingCurveMap = Record<EasingName, Record<EasingMode, CubicBezier>>;
61
62
 
62
63
  // Keep one numeric source for every Carbon easing curve.
64
+ // Used by resolveEasing() — surfaces need raw numeric arrays, not CSS strings.
63
65
  const easingCurves: EasingCurveMap = {
64
66
  standard: {
65
67
  productive: [0.2, 0, 0.38, 0.9],
@@ -75,40 +77,20 @@ const easingCurves: EasingCurveMap = {
75
77
  },
76
78
  };
77
79
 
78
- const formatEasing = (curve: CubicBezier) =>
79
- `cubic-bezier(${curve.join(', ')})`;
80
-
81
- export const easings: EasingMap = {
82
- standard: {
83
- productive: formatEasing(easingCurves.standard.productive),
84
- expressive: formatEasing(easingCurves.standard.expressive),
85
- },
86
- entrance: {
87
- productive: formatEasing(easingCurves.entrance.productive),
88
- expressive: formatEasing(easingCurves.entrance.expressive),
89
- },
90
- exit: {
91
- productive: formatEasing(easingCurves.exit.productive),
92
- expressive: formatEasing(easingCurves.exit.expressive),
93
- },
94
- };
95
-
96
80
  export const motion = (name: EasingName, mode: EasingMode) => {
97
- if (!easings[name]) {
81
+ const easing = easings[name];
82
+ if (!easing) {
98
83
  throw new Error(
99
84
  `Unable to find easing \`${name}\` in our supported easings. Expected ` +
100
85
  `one of: ${Object.keys(easings).join(', ')}`
101
86
  );
102
87
  }
103
-
104
- const easing = easings[name];
105
88
  if (!easing[mode]) {
106
89
  throw new Error(
107
90
  `Unable to find a mode for the easing \`${name}\` called: \`${mode}\`. ` +
108
91
  `Expected one of: ${Object.keys(easing).join(', ')}`
109
92
  );
110
93
  }
111
-
112
94
  return easing[mode];
113
95
  };
114
96