@bug-on/md3-tokens 3.0.0 → 3.0.3
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.
- package/.turbo/turbo-build.log +12 -14
- package/CHANGELOG.md +11 -0
- package/dist/colors.css.d.ts +2 -0
- package/dist/index.d.mts +448 -45
- package/dist/index.d.ts +448 -45
- package/dist/index.js +258 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +243 -9
- package/dist/index.mjs.map +1 -1
- package/dist/shape.css +9 -0
- package/dist/shape.css.d.ts +2 -0
- package/package.json +14 -10
- package/scripts/copy-css.js +1 -1
- package/src/index.ts +47 -1
- package/src/motion.ts +280 -9
- package/src/shape.css +9 -0
- package/src/shape.ts +162 -0
- package/tsup.config.ts +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/motion.ts"],"sourcesContent":["/**\n * MD3 Expressive Motion Tokens\n * Framework-agnostic JS objects.\n */\n\nexport const duration = {\n\tshort1: 50,\n\tshort2: 100,\n\tshort3: 150,\n\tshort4: 200,\n\tmedium1: 250,\n\tmedium2: 300,\n\tmedium3: 350,\n\tmedium4: 400,\n\tlong1: 450,\n\tlong2: 500,\n\tlong3: 550,\n\tlong4: 600,\n\textraLong1: 700,\n\textraLong2: 800,\n\textraLong3: 900,\n\textraLong4: 1000,\n} as const;\n\nexport const easing = {\n\tstandard: [0.2, 0, 0, 1] as [number, number, number, number],\n\tstandardAccelerate: [0.3, 0, 1, 1] as [number, number, number, number],\n\tstandardDecelerate: [0, 0, 0, 1] as [number, number, number, number],\n\temphasized: [0.2, 0, 0, 1] as [number, number, number, number],\n\temphasizedAccelerate: [0.3, 0, 0.8, 0.15] as [number, number, number, number],\n\temphasizedDecelerate: [0.05, 0.7, 0.1, 1.0] as [\n\t\tnumber,\n\t\tnumber,\n\t\tnumber,\n\t\tnumber,\n\t],\n} as const;\n\nexport const spring = {\n\tdefault: { type: \"spring\" as const, stiffness: 500, damping: 30, mass: 0.8 },\n\tsnappy: { type: \"spring\" as const, stiffness: 600, damping: 25 },\n\tgentle: { type: \"spring\" as const, stiffness: 300, damping: 20 },\n\tbouncy: { type: \"spring\" as const, stiffness: 400, damping: 15 },\n} as const;\n\nexport const motionTokens = { duration, easing, spring };\n"],"mappings":";AAKO,IAAM,WAAW;AAAA,EACvB,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AACb;AAEO,IAAM,SAAS;AAAA,EACrB,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC;AAAA,EACvB,oBAAoB,CAAC,KAAK,GAAG,GAAG,CAAC;AAAA,EACjC,oBAAoB,CAAC,GAAG,GAAG,GAAG,CAAC;AAAA,EAC/B,YAAY,CAAC,KAAK,GAAG,GAAG,CAAC;AAAA,EACzB,sBAAsB,CAAC,KAAK,GAAG,KAAK,IAAI;AAAA,EACxC,sBAAsB,CAAC,MAAM,KAAK,KAAK,CAAG;AAM3C;AAEO,IAAM,SAAS;AAAA,EACrB,SAAS,EAAE,MAAM,UAAmB,WAAW,KAAK,SAAS,IAAI,MAAM,IAAI;AAAA,EAC3E,QAAQ,EAAE,MAAM,UAAmB,WAAW,KAAK,SAAS,GAAG;AAAA,EAC/D,QAAQ,EAAE,MAAM,UAAmB,WAAW,KAAK,SAAS,GAAG;AAAA,EAC/D,QAAQ,EAAE,MAAM,UAAmB,WAAW,KAAK,SAAS,GAAG;AAChE;AAEO,IAAM,eAAe,EAAE,UAAU,QAAQ,OAAO;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/motion.ts","../src/shape.ts"],"sourcesContent":["/**\n * MD3 Expressive Motion Tokens\n *\n * Source of truth for all motion in the design system. Two layers:\n *\n * 1. **Physics-based system** (May 2025, primary) — Spring tokens per the MD3\n * motion physics system. Use these for Framer Motion / JS animations.\n * 2. **Legacy easing + duration** (still valid for CSS transitions) — Original\n * MD3 cubic-bezier tokens kept as a fallback.\n *\n * @see https://m3.material.io/styles/motion/overview/how-it-works\n * @see https://m3.material.io/styles/motion/overview/specs\n */\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Motion scheme — controls whether springs bounce (expressive) or not (standard). */\nexport type MotionScheme = \"expressive\" | \"standard\";\n\n/** Spring speed tier. */\nexport type SpringSpeed = \"fast\" | \"default\" | \"slow\";\n\n/** Spring type — spatial (position/size/shape) or effects (color/opacity). */\nexport type SpringType = \"spatial\" | \"effects\";\n\n/** Raw MD3 spring token — damping ratio + stiffness as specified in the design token. */\nexport interface MD3SpringToken {\n\t/** Damping ratio: 0 = no damping, 1 = critically damped (no bounce). */\n\tdampingRatio: number;\n\t/** Spring stiffness. Higher = faster animation. */\n\tstiffness: number;\n}\n\n/** A pre-converted spring ready for Framer Motion `Transition`. */\nexport interface FramerSpring {\n\ttype: \"spring\";\n\t/** Absolute damping coefficient (converted from dampingRatio). */\n\tdamping: number;\n\tstiffness: number;\n}\n\n/** Web CSS curve equivalent for a spring token (for CSS transitions). */\nexport interface WebCurveToken {\n\t/** CSS cubic-bezier(...) string. */\n\tcurve: string;\n\t/** Duration in milliseconds. */\n\tdurationMs: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// MD3 Expressive Spring Tokens (raw: dampingRatio + stiffness)\n// Source: md.sys.motion.spring.{speed}.{type}\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Raw MD3 spring tokens per the official specification.\n * Values are identical for both \"expressive\" and \"standard\" schemes —\n * the scheme is applied at the product level, not the token level.\n *\n * @see https://m3.material.io/styles/motion/easing-and-duration/tokens-specs\n */\nexport const md3SpringTokens = {\n\tfast: {\n\t\tspatial: { dampingRatio: 0.6, stiffness: 800 } satisfies MD3SpringToken,\n\t\teffects: { dampingRatio: 1.0, stiffness: 3800 } satisfies MD3SpringToken,\n\t},\n\tdefault: {\n\t\tspatial: { dampingRatio: 0.8, stiffness: 380 } satisfies MD3SpringToken,\n\t\teffects: { dampingRatio: 1.0, stiffness: 1600 } satisfies MD3SpringToken,\n\t},\n\tslow: {\n\t\tspatial: { dampingRatio: 0.8, stiffness: 200 } satisfies MD3SpringToken,\n\t\teffects: { dampingRatio: 1.0, stiffness: 800 } satisfies MD3SpringToken,\n\t},\n} as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Framer Motion Spring Presets\n// damping = 2 * dampingRatio * sqrt(stiffness * mass), mass = 1 (default)\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction toFramerSpring(token: MD3SpringToken): FramerSpring {\n\tconst damping = 2 * token.dampingRatio * Math.sqrt(token.stiffness);\n\treturn { type: \"spring\", stiffness: token.stiffness, damping };\n}\n\n/**\n * Ready-to-use Framer Motion spring configs, derived from MD3 spring tokens.\n *\n * Use **spatial** springs for: position, size, border-radius, rotation, scale.\n * Use **effects** springs for: color, opacity (no overshoot).\n *\n * @example\n * ```tsx\n * import { framerSprings } from \"@md3-expressive/tokens\";\n * <m.div transition={framerSprings.fast.spatial} />\n * ```\n */\nexport const framerSprings = {\n\tfast: {\n\t\tspatial: toFramerSpring(md3SpringTokens.fast.spatial),\n\t\teffects: toFramerSpring(md3SpringTokens.fast.effects),\n\t},\n\tdefault: {\n\t\tspatial: toFramerSpring(md3SpringTokens.default.spatial),\n\t\teffects: toFramerSpring(md3SpringTokens.default.effects),\n\t},\n\tslow: {\n\t\tspatial: toFramerSpring(md3SpringTokens.slow.spatial),\n\t\teffects: toFramerSpring(md3SpringTokens.slow.effects),\n\t},\n} as const;\n\n// Convenient named aliases (mirror menu-animations.ts naming convention)\nexport const FAST_SPATIAL_SPRING = framerSprings.fast.spatial;\nexport const FAST_EFFECTS_SPRING = framerSprings.fast.effects;\nexport const DEFAULT_SPATIAL_SPRING = framerSprings.default.spatial;\nexport const DEFAULT_EFFECTS_SPRING = framerSprings.default.effects;\nexport const SLOW_SPATIAL_SPRING = framerSprings.slow.spatial;\nexport const SLOW_EFFECTS_SPRING = framerSprings.slow.effects;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Web CSS Curve Conversions\n// Use these when Framer Motion is not available (pure CSS transitions).\n// Source: https://m3.material.io/styles/motion/overview/specs#web-convert\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * CSS cubic-bezier + duration equivalents of MD3 spring tokens.\n * For non-interruptible CSS transitions when JS springs are unavailable.\n *\n * @see https://m3.material.io/styles/motion/overview/specs\n */\nexport const webCurves = {\n\texpressive: {\n\t\tfast: {\n\t\t\tspatial: {\n\t\t\t\tcurve: \"cubic-bezier(0.42, 1.67, 0.21, 0.90)\",\n\t\t\t\tdurationMs: 350,\n\t\t\t} satisfies WebCurveToken,\n\t\t\teffects: {\n\t\t\t\tcurve: \"cubic-bezier(0.31, 0.94, 0.34, 1.00)\",\n\t\t\t\tdurationMs: 150,\n\t\t\t} satisfies WebCurveToken,\n\t\t},\n\t\tdefault: {\n\t\t\tspatial: {\n\t\t\t\tcurve: \"cubic-bezier(0.38, 1.21, 0.22, 1.00)\",\n\t\t\t\tdurationMs: 500,\n\t\t\t} satisfies WebCurveToken,\n\t\t\teffects: {\n\t\t\t\tcurve: \"cubic-bezier(0.34, 0.80, 0.34, 1.00)\",\n\t\t\t\tdurationMs: 200,\n\t\t\t} satisfies WebCurveToken,\n\t\t},\n\t\tslow: {\n\t\t\tspatial: {\n\t\t\t\tcurve: \"cubic-bezier(0.39, 1.29, 0.35, 0.98)\",\n\t\t\t\tdurationMs: 650,\n\t\t\t} satisfies WebCurveToken,\n\t\t\teffects: {\n\t\t\t\tcurve: \"cubic-bezier(0.34, 0.88, 0.34, 1.00)\",\n\t\t\t\tdurationMs: 300,\n\t\t\t} satisfies WebCurveToken,\n\t\t},\n\t},\n\tstandard: {\n\t\tfast: {\n\t\t\tspatial: {\n\t\t\t\tcurve: \"cubic-bezier(0.27, 1.06, 0.18, 1.00)\",\n\t\t\t\tdurationMs: 350,\n\t\t\t} satisfies WebCurveToken,\n\t\t\teffects: {\n\t\t\t\tcurve: \"cubic-bezier(0.31, 0.94, 0.34, 1.00)\",\n\t\t\t\tdurationMs: 150,\n\t\t\t} satisfies WebCurveToken,\n\t\t},\n\t\tdefault: {\n\t\t\tspatial: {\n\t\t\t\tcurve: \"cubic-bezier(0.27, 1.06, 0.18, 1.00)\",\n\t\t\t\tdurationMs: 500,\n\t\t\t} satisfies WebCurveToken,\n\t\t\teffects: {\n\t\t\t\tcurve: \"cubic-bezier(0.34, 0.80, 0.34, 1.00)\",\n\t\t\t\tdurationMs: 200,\n\t\t\t} satisfies WebCurveToken,\n\t\t},\n\t\tslow: {\n\t\t\tspatial: {\n\t\t\t\tcurve: \"cubic-bezier(0.27, 1.06, 0.18, 1.00)\",\n\t\t\t\tdurationMs: 750,\n\t\t\t} satisfies WebCurveToken,\n\t\t\teffects: {\n\t\t\t\tcurve: \"cubic-bezier(0.34, 0.88, 0.34, 1.00)\",\n\t\t\t\tdurationMs: 300,\n\t\t\t} satisfies WebCurveToken,\n\t\t},\n\t},\n} as const;\n\n/**\n * Get a Framer Motion spring config for the given scheme, speed, and type.\n *\n * @example\n * ```tsx\n * transition={getSpring(\"expressive\", \"fast\", \"spatial\")}\n * ```\n */\nexport function getSpring(\n\t_scheme: MotionScheme,\n\tspeed: SpringSpeed,\n\ttype: SpringType,\n): FramerSpring {\n\t// Spring token values are scheme-agnostic; scheme is applied at product level.\n\treturn framerSprings[speed][type];\n}\n\n/**\n * Get a CSS transition string for the given scheme, speed, and type.\n *\n * @example\n * ```ts\n * element.style.transition = `transform ${getCSSTransition(\"expressive\", \"fast\", \"spatial\")}`;\n * ```\n */\nexport function getCSSTransition(\n\tscheme: MotionScheme,\n\tspeed: SpringSpeed,\n\ttype: SpringType,\n): string {\n\tconst { curve, durationMs } = webCurves[scheme][speed][type];\n\treturn `${durationMs}ms ${curve}`;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Legacy: Duration tokens (ms) — md.sys.motion.duration.*\n// Still valid; used as CSS fallback and for easing-based animations.\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const duration = {\n\tshort1: 50,\n\tshort2: 100,\n\tshort3: 150,\n\tshort4: 200,\n\tmedium1: 250,\n\tmedium2: 300,\n\tmedium3: 350,\n\tmedium4: 400,\n\tlong1: 450,\n\tlong2: 500,\n\tlong3: 550,\n\tlong4: 600,\n\textraLong1: 700,\n\textraLong2: 800,\n\textraLong3: 900,\n\textraLong4: 1000,\n} as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Legacy: Easing tokens — md.sys.motion.easing.*\n// Cubic-bezier control points [x1, y1, x2, y2].\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const easing = {\n\t// Emphasized set — most common for M3 Expressive transitions\n\temphasized: [0.2, 0, 0, 1] as [number, number, number, number],\n\temphasizedAccelerate: [0.3, 0, 0.8, 0.15] as [number, number, number, number],\n\temphasizedDecelerate: [0.05, 0.7, 0.1, 1.0] as [\n\t\tnumber,\n\t\tnumber,\n\t\tnumber,\n\t\tnumber,\n\t],\n\n\t// Standard set — for simple/utility transitions and CSS fallback\n\tstandard: [0.2, 0, 0, 1] as [number, number, number, number],\n\tstandardAccelerate: [0.3, 0, 1, 1] as [number, number, number, number],\n\tstandardDecelerate: [0, 0, 0, 1] as [number, number, number, number],\n\n\t// Legacy set (M2 compat)\n\tlegacy: [0.4, 0, 0.2, 1] as [number, number, number, number],\n\tlegacyAccelerate: [0.4, 0, 1, 1] as [number, number, number, number],\n\tlegacyDecelerate: [0, 0, 0.2, 1] as [number, number, number, number],\n\n\t// Linear\n\tlinear: [0, 0, 1, 1] as [number, number, number, number],\n} as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// @deprecated Legacy spring presets — kept for backward compat only.\n// Migrate to framerSprings.* or the named FAST_SPATIAL_SPRING etc. exports.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** @deprecated Use `framerSprings.default.spatial` or `DEFAULT_SPATIAL_SPRING` instead. */\nexport const spring = {\n\tdefault: framerSprings.default.spatial,\n\tsnappy: framerSprings.fast.spatial,\n\tgentle: framerSprings.slow.spatial,\n\tbouncy: {\n\t\t...framerSprings.fast.spatial,\n\t\tdamping: framerSprings.fast.spatial.damping * 0.5,\n\t},\n} as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Aggregate export\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const motionTokens = {\n\tduration,\n\teasing,\n\tspring: md3SpringTokens,\n\tframerSprings,\n\twebCurves,\n} as const;\n","/**\n * MD3 Expressive Shape Tokens\n *\n * TypeScript counterpart to `shape.css`. Provides numeric corner radius values,\n * CSS custom property names, and asymmetric corner helpers.\n *\n * Updated for M3 Expressive (May 2025): 10-level corner radius scale.\n *\n * @see https://m3.material.io/styles/shape/corner-radius-scale\n */\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Corner radius scale — numeric values in pixels\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Numeric corner radius values (px) for all 10 shape scale levels.\n * Map directly to `--md-sys-shape-corner-*` CSS custom properties.\n *\n * @example\n * ```ts\n * element.style.borderRadius = `${cornerRadius.medium}px`; // 12px\n * ```\n */\nexport const cornerRadius = {\n\tnone: 0,\n\textraSmall: 4,\n\tsmall: 8,\n\tmedium: 12,\n\tlarge: 16,\n\t/** New in M3 Expressive (May 2025) */\n\tlargeIncreased: 20,\n\textraLarge: 28,\n\t/** New in M3 Expressive (May 2025) */\n\textraLargeIncreased: 32,\n\t/** New in M3 Expressive (May 2025) */\n\textraExtraLarge: 48,\n\tfull: 9999,\n} as const;\n\nexport type CornerRadiusKey = keyof typeof cornerRadius;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// CSS custom property names\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Maps each corner radius key to its CSS custom property name.\n *\n * @example\n * ```ts\n * const cssVar = cornerCssVar.medium; // \"--md-sys-shape-corner-medium\"\n * element.style.borderRadius = `var(${cssVar})`;\n * ```\n */\nexport const cornerCssVar: Record<CornerRadiusKey, string> = {\n\tnone: \"--md-sys-shape-corner-none\",\n\textraSmall: \"--md-sys-shape-corner-extra-small\",\n\tsmall: \"--md-sys-shape-corner-small\",\n\tmedium: \"--md-sys-shape-corner-medium\",\n\tlarge: \"--md-sys-shape-corner-large\",\n\tlargeIncreased: \"--md-sys-shape-corner-large-increased\",\n\textraLarge: \"--md-sys-shape-corner-extra-large\",\n\textraLargeIncreased: \"--md-sys-shape-corner-extra-large-increased\",\n\textraExtraLarge: \"--md-sys-shape-corner-extra-extra-large\",\n\tfull: \"--md-sys-shape-corner-full\",\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Asymmetric corner helpers\n// Used for inner-corner components (menus, split buttons, grouped items).\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Describes per-corner rounding for asymmetric shapes.\n * Follows CSS `border-radius` shorthand order:\n * top-left, top-right, bottom-right, bottom-left.\n */\nexport interface AsymmetricCorners {\n\ttopLeft: number;\n\ttopRight: number;\n\tbottomRight: number;\n\tbottomLeft: number;\n}\n\n/** Shorthand presets for common asymmetric corner patterns. */\nexport const asymmetricCorners = {\n\t/** Fully rounded top, square bottom — e.g. menu at top of screen. */\n\ttopFull: (r = cornerRadius.extraLarge): AsymmetricCorners => ({\n\t\ttopLeft: r,\n\t\ttopRight: r,\n\t\tbottomRight: 0,\n\t\tbottomLeft: 0,\n\t}),\n\t/** Square top, fully rounded bottom — e.g. menu at bottom of screen. */\n\tbottomFull: (r = cornerRadius.extraLarge): AsymmetricCorners => ({\n\t\ttopLeft: 0,\n\t\ttopRight: 0,\n\t\tbottomRight: r,\n\t\tbottomLeft: r,\n\t}),\n\t/** Rounded start edge only — e.g. left item in a grouped set. */\n\tstartFull: (r = cornerRadius.full): AsymmetricCorners => ({\n\t\ttopLeft: r,\n\t\ttopRight: 0,\n\t\tbottomRight: 0,\n\t\tbottomLeft: r,\n\t}),\n\t/** Rounded end edge only — e.g. right item in a grouped set. */\n\tendFull: (r = cornerRadius.full): AsymmetricCorners => ({\n\t\ttopLeft: 0,\n\t\ttopRight: r,\n\t\tbottomRight: r,\n\t\tbottomLeft: 0,\n\t}),\n} as const;\n\n/**\n * Converts an `AsymmetricCorners` object to a CSS `border-radius` string.\n *\n * @example\n * ```ts\n * element.style.borderRadius = toCSS(asymmetricCorners.topFull());\n * // \"28px 28px 0px 0px\"\n * ```\n */\nexport function asymmetricCornersToCSS(corners: AsymmetricCorners): string {\n\treturn `${corners.topLeft}px ${corners.topRight}px ${corners.bottomRight}px ${corners.bottomLeft}px`;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Optical roundness helper\n// When nesting rounded objects: inner radius = outer radius - padding\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Calculates the inner border-radius that maintains optical roundness\n * when nesting one rounded container inside another.\n *\n * Formula: `inner = outer - padding`\n *\n * @see https://m3.material.io/styles/shape/corner-radius-scale#adjust-for-optical-roundness\n *\n * @example\n * ```ts\n * // Container has extraExtraLarge (48px), padding is 14px\n * const inner = opticalRadius(cornerRadius.extraExtraLarge, 14); // 34\n * ```\n */\nexport function opticalRadius(outerRadius: number, padding: number): number {\n\treturn Math.max(0, outerRadius - padding);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Aggregate export\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const shapeTokens = {\n\tcornerRadius,\n\tcornerCssVar,\n\tasymmetricCorners,\n} as const;\n"],"mappings":"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","names":[]}
|
package/dist/shape.css
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
:root {
|
|
2
|
+
/* ── MD3 Expressive Corner Radius Scale (10 levels) ─────────────────────── */
|
|
3
|
+
/* Source: https://m3.material.io/styles/shape/corner-radius-scale */
|
|
4
|
+
|
|
2
5
|
--md-sys-shape-corner-none: 0px;
|
|
3
6
|
--md-sys-shape-corner-extra-small: 4px;
|
|
4
7
|
--md-sys-shape-corner-small: 8px;
|
|
5
8
|
--md-sys-shape-corner-medium: 12px;
|
|
6
9
|
--md-sys-shape-corner-large: 16px;
|
|
10
|
+
/* New in M3 Expressive (May 2025) */
|
|
11
|
+
--md-sys-shape-corner-large-increased: 20px;
|
|
7
12
|
--md-sys-shape-corner-extra-large: 28px;
|
|
13
|
+
/* New in M3 Expressive (May 2025) */
|
|
14
|
+
--md-sys-shape-corner-extra-large-increased: 32px;
|
|
15
|
+
/* New in M3 Expressive (May 2025) */
|
|
16
|
+
--md-sys-shape-corner-extra-extra-large: 48px;
|
|
8
17
|
--md-sys-shape-corner-full: 9999px;
|
|
9
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bug-on/md3-tokens",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Material Design 3 Expressive design tokens",
|
|
5
5
|
"author": "Bug Ổn",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,9 +23,14 @@
|
|
|
23
23
|
"types": "./dist/index.d.ts",
|
|
24
24
|
"exports": {
|
|
25
25
|
".": {
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
"import": {
|
|
27
|
+
"types": "./dist/index.d.mts",
|
|
28
|
+
"default": "./dist/index.mjs"
|
|
29
|
+
},
|
|
30
|
+
"require": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
}
|
|
29
34
|
},
|
|
30
35
|
"./colors.css": {
|
|
31
36
|
"types": "./dist/colors.css.d.ts",
|
|
@@ -36,20 +41,19 @@
|
|
|
36
41
|
"default": "./dist/shape.css"
|
|
37
42
|
}
|
|
38
43
|
},
|
|
39
|
-
"peerDependencies": {
|
|
40
|
-
"react": "^19.0.0",
|
|
41
|
-
"react-dom": "^19.0.0"
|
|
42
|
-
},
|
|
44
|
+
"peerDependencies": {},
|
|
43
45
|
"publishConfig": {
|
|
44
46
|
"access": "public"
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
|
49
|
+
"react": "^19.0.0",
|
|
50
|
+
"react-dom": "^19.0.0",
|
|
47
51
|
"tsup": "^8.4.0",
|
|
48
52
|
"typescript": "5.8.3"
|
|
49
53
|
},
|
|
50
54
|
"scripts": {
|
|
51
|
-
"build": "tsup",
|
|
52
|
-
"dev": "tsup --watch",
|
|
55
|
+
"build": "tsup && node scripts/copy-css.js",
|
|
56
|
+
"dev": "tsup --watch --onSuccess \"node scripts/copy-css.js\"",
|
|
53
57
|
"clean": "rm -rf dist"
|
|
54
58
|
}
|
|
55
59
|
}
|
package/scripts/copy-css.js
CHANGED
|
@@ -12,7 +12,7 @@ if (!fs.existsSync(distDir)) {
|
|
|
12
12
|
console.log("Copying CSS assets to dist...");
|
|
13
13
|
|
|
14
14
|
// CSS files to copy from src/ to dist/ (only files that exist in src/)
|
|
15
|
-
const cssFiles = ["colors.css", "shape.css"
|
|
15
|
+
const cssFiles = ["colors.css", "shape.css"];
|
|
16
16
|
|
|
17
17
|
for (const file of cssFiles) {
|
|
18
18
|
const srcPath = path.join(srcDir, file);
|
package/src/index.ts
CHANGED
|
@@ -1 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
// Motion tokens — MD3 Expressive physics-based system + legacy easing/duration
|
|
2
|
+
export {
|
|
3
|
+
DEFAULT_EFFECTS_SPRING,
|
|
4
|
+
DEFAULT_SPATIAL_SPRING,
|
|
5
|
+
// Legacy duration + easing (still valid, kept as fallback)
|
|
6
|
+
duration,
|
|
7
|
+
easing,
|
|
8
|
+
FAST_EFFECTS_SPRING,
|
|
9
|
+
FAST_SPATIAL_SPRING,
|
|
10
|
+
type FramerSpring,
|
|
11
|
+
// Framer Motion ready presets
|
|
12
|
+
framerSprings,
|
|
13
|
+
getCSSTransition,
|
|
14
|
+
// Helpers
|
|
15
|
+
getSpring,
|
|
16
|
+
type MD3SpringToken,
|
|
17
|
+
// Types
|
|
18
|
+
type MotionScheme,
|
|
19
|
+
// Raw MD3 spring tokens (dampingRatio + stiffness)
|
|
20
|
+
md3SpringTokens,
|
|
21
|
+
// Aggregate
|
|
22
|
+
motionTokens,
|
|
23
|
+
SLOW_EFFECTS_SPRING,
|
|
24
|
+
SLOW_SPATIAL_SPRING,
|
|
25
|
+
type SpringSpeed,
|
|
26
|
+
type SpringType,
|
|
27
|
+
// @deprecated legacy spring presets
|
|
28
|
+
spring,
|
|
29
|
+
type WebCurveToken,
|
|
30
|
+
// Web CSS curve equivalents
|
|
31
|
+
webCurves,
|
|
32
|
+
} from "./motion";
|
|
33
|
+
|
|
34
|
+
// Shape tokens — MD3 Expressive 10-level corner radius scale + helpers
|
|
35
|
+
export {
|
|
36
|
+
type AsymmetricCorners,
|
|
37
|
+
asymmetricCorners,
|
|
38
|
+
asymmetricCornersToCSS,
|
|
39
|
+
// Types
|
|
40
|
+
type CornerRadiusKey,
|
|
41
|
+
cornerCssVar,
|
|
42
|
+
// Corner radius values
|
|
43
|
+
cornerRadius,
|
|
44
|
+
opticalRadius,
|
|
45
|
+
// Aggregate
|
|
46
|
+
shapeTokens,
|
|
47
|
+
} from "./shape";
|
package/src/motion.ts
CHANGED
|
@@ -1,8 +1,244 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MD3 Expressive Motion Tokens
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Source of truth for all motion in the design system. Two layers:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Physics-based system** (May 2025, primary) — Spring tokens per the MD3
|
|
7
|
+
* motion physics system. Use these for Framer Motion / JS animations.
|
|
8
|
+
* 2. **Legacy easing + duration** (still valid for CSS transitions) — Original
|
|
9
|
+
* MD3 cubic-bezier tokens kept as a fallback.
|
|
10
|
+
*
|
|
11
|
+
* @see https://m3.material.io/styles/motion/overview/how-it-works
|
|
12
|
+
* @see https://m3.material.io/styles/motion/overview/specs
|
|
4
13
|
*/
|
|
5
14
|
|
|
15
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
16
|
+
// Types
|
|
17
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
/** Motion scheme — controls whether springs bounce (expressive) or not (standard). */
|
|
20
|
+
export type MotionScheme = "expressive" | "standard";
|
|
21
|
+
|
|
22
|
+
/** Spring speed tier. */
|
|
23
|
+
export type SpringSpeed = "fast" | "default" | "slow";
|
|
24
|
+
|
|
25
|
+
/** Spring type — spatial (position/size/shape) or effects (color/opacity). */
|
|
26
|
+
export type SpringType = "spatial" | "effects";
|
|
27
|
+
|
|
28
|
+
/** Raw MD3 spring token — damping ratio + stiffness as specified in the design token. */
|
|
29
|
+
export interface MD3SpringToken {
|
|
30
|
+
/** Damping ratio: 0 = no damping, 1 = critically damped (no bounce). */
|
|
31
|
+
dampingRatio: number;
|
|
32
|
+
/** Spring stiffness. Higher = faster animation. */
|
|
33
|
+
stiffness: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** A pre-converted spring ready for Framer Motion `Transition`. */
|
|
37
|
+
export interface FramerSpring {
|
|
38
|
+
type: "spring";
|
|
39
|
+
/** Absolute damping coefficient (converted from dampingRatio). */
|
|
40
|
+
damping: number;
|
|
41
|
+
stiffness: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Web CSS curve equivalent for a spring token (for CSS transitions). */
|
|
45
|
+
export interface WebCurveToken {
|
|
46
|
+
/** CSS cubic-bezier(...) string. */
|
|
47
|
+
curve: string;
|
|
48
|
+
/** Duration in milliseconds. */
|
|
49
|
+
durationMs: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
53
|
+
// MD3 Expressive Spring Tokens (raw: dampingRatio + stiffness)
|
|
54
|
+
// Source: md.sys.motion.spring.{speed}.{type}
|
|
55
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Raw MD3 spring tokens per the official specification.
|
|
59
|
+
* Values are identical for both "expressive" and "standard" schemes —
|
|
60
|
+
* the scheme is applied at the product level, not the token level.
|
|
61
|
+
*
|
|
62
|
+
* @see https://m3.material.io/styles/motion/easing-and-duration/tokens-specs
|
|
63
|
+
*/
|
|
64
|
+
export const md3SpringTokens = {
|
|
65
|
+
fast: {
|
|
66
|
+
spatial: { dampingRatio: 0.6, stiffness: 800 } satisfies MD3SpringToken,
|
|
67
|
+
effects: { dampingRatio: 1.0, stiffness: 3800 } satisfies MD3SpringToken,
|
|
68
|
+
},
|
|
69
|
+
default: {
|
|
70
|
+
spatial: { dampingRatio: 0.8, stiffness: 380 } satisfies MD3SpringToken,
|
|
71
|
+
effects: { dampingRatio: 1.0, stiffness: 1600 } satisfies MD3SpringToken,
|
|
72
|
+
},
|
|
73
|
+
slow: {
|
|
74
|
+
spatial: { dampingRatio: 0.8, stiffness: 200 } satisfies MD3SpringToken,
|
|
75
|
+
effects: { dampingRatio: 1.0, stiffness: 800 } satisfies MD3SpringToken,
|
|
76
|
+
},
|
|
77
|
+
} as const;
|
|
78
|
+
|
|
79
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
80
|
+
// Framer Motion Spring Presets
|
|
81
|
+
// damping = 2 * dampingRatio * sqrt(stiffness * mass), mass = 1 (default)
|
|
82
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
function toFramerSpring(token: MD3SpringToken): FramerSpring {
|
|
85
|
+
const damping = 2 * token.dampingRatio * Math.sqrt(token.stiffness);
|
|
86
|
+
return { type: "spring", stiffness: token.stiffness, damping };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Ready-to-use Framer Motion spring configs, derived from MD3 spring tokens.
|
|
91
|
+
*
|
|
92
|
+
* Use **spatial** springs for: position, size, border-radius, rotation, scale.
|
|
93
|
+
* Use **effects** springs for: color, opacity (no overshoot).
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```tsx
|
|
97
|
+
* import { framerSprings } from "@md3-expressive/tokens";
|
|
98
|
+
* <m.div transition={framerSprings.fast.spatial} />
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export const framerSprings = {
|
|
102
|
+
fast: {
|
|
103
|
+
spatial: toFramerSpring(md3SpringTokens.fast.spatial),
|
|
104
|
+
effects: toFramerSpring(md3SpringTokens.fast.effects),
|
|
105
|
+
},
|
|
106
|
+
default: {
|
|
107
|
+
spatial: toFramerSpring(md3SpringTokens.default.spatial),
|
|
108
|
+
effects: toFramerSpring(md3SpringTokens.default.effects),
|
|
109
|
+
},
|
|
110
|
+
slow: {
|
|
111
|
+
spatial: toFramerSpring(md3SpringTokens.slow.spatial),
|
|
112
|
+
effects: toFramerSpring(md3SpringTokens.slow.effects),
|
|
113
|
+
},
|
|
114
|
+
} as const;
|
|
115
|
+
|
|
116
|
+
// Convenient named aliases (mirror menu-animations.ts naming convention)
|
|
117
|
+
export const FAST_SPATIAL_SPRING = framerSprings.fast.spatial;
|
|
118
|
+
export const FAST_EFFECTS_SPRING = framerSprings.fast.effects;
|
|
119
|
+
export const DEFAULT_SPATIAL_SPRING = framerSprings.default.spatial;
|
|
120
|
+
export const DEFAULT_EFFECTS_SPRING = framerSprings.default.effects;
|
|
121
|
+
export const SLOW_SPATIAL_SPRING = framerSprings.slow.spatial;
|
|
122
|
+
export const SLOW_EFFECTS_SPRING = framerSprings.slow.effects;
|
|
123
|
+
|
|
124
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
125
|
+
// Web CSS Curve Conversions
|
|
126
|
+
// Use these when Framer Motion is not available (pure CSS transitions).
|
|
127
|
+
// Source: https://m3.material.io/styles/motion/overview/specs#web-convert
|
|
128
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* CSS cubic-bezier + duration equivalents of MD3 spring tokens.
|
|
132
|
+
* For non-interruptible CSS transitions when JS springs are unavailable.
|
|
133
|
+
*
|
|
134
|
+
* @see https://m3.material.io/styles/motion/overview/specs
|
|
135
|
+
*/
|
|
136
|
+
export const webCurves = {
|
|
137
|
+
expressive: {
|
|
138
|
+
fast: {
|
|
139
|
+
spatial: {
|
|
140
|
+
curve: "cubic-bezier(0.42, 1.67, 0.21, 0.90)",
|
|
141
|
+
durationMs: 350,
|
|
142
|
+
} satisfies WebCurveToken,
|
|
143
|
+
effects: {
|
|
144
|
+
curve: "cubic-bezier(0.31, 0.94, 0.34, 1.00)",
|
|
145
|
+
durationMs: 150,
|
|
146
|
+
} satisfies WebCurveToken,
|
|
147
|
+
},
|
|
148
|
+
default: {
|
|
149
|
+
spatial: {
|
|
150
|
+
curve: "cubic-bezier(0.38, 1.21, 0.22, 1.00)",
|
|
151
|
+
durationMs: 500,
|
|
152
|
+
} satisfies WebCurveToken,
|
|
153
|
+
effects: {
|
|
154
|
+
curve: "cubic-bezier(0.34, 0.80, 0.34, 1.00)",
|
|
155
|
+
durationMs: 200,
|
|
156
|
+
} satisfies WebCurveToken,
|
|
157
|
+
},
|
|
158
|
+
slow: {
|
|
159
|
+
spatial: {
|
|
160
|
+
curve: "cubic-bezier(0.39, 1.29, 0.35, 0.98)",
|
|
161
|
+
durationMs: 650,
|
|
162
|
+
} satisfies WebCurveToken,
|
|
163
|
+
effects: {
|
|
164
|
+
curve: "cubic-bezier(0.34, 0.88, 0.34, 1.00)",
|
|
165
|
+
durationMs: 300,
|
|
166
|
+
} satisfies WebCurveToken,
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
standard: {
|
|
170
|
+
fast: {
|
|
171
|
+
spatial: {
|
|
172
|
+
curve: "cubic-bezier(0.27, 1.06, 0.18, 1.00)",
|
|
173
|
+
durationMs: 350,
|
|
174
|
+
} satisfies WebCurveToken,
|
|
175
|
+
effects: {
|
|
176
|
+
curve: "cubic-bezier(0.31, 0.94, 0.34, 1.00)",
|
|
177
|
+
durationMs: 150,
|
|
178
|
+
} satisfies WebCurveToken,
|
|
179
|
+
},
|
|
180
|
+
default: {
|
|
181
|
+
spatial: {
|
|
182
|
+
curve: "cubic-bezier(0.27, 1.06, 0.18, 1.00)",
|
|
183
|
+
durationMs: 500,
|
|
184
|
+
} satisfies WebCurveToken,
|
|
185
|
+
effects: {
|
|
186
|
+
curve: "cubic-bezier(0.34, 0.80, 0.34, 1.00)",
|
|
187
|
+
durationMs: 200,
|
|
188
|
+
} satisfies WebCurveToken,
|
|
189
|
+
},
|
|
190
|
+
slow: {
|
|
191
|
+
spatial: {
|
|
192
|
+
curve: "cubic-bezier(0.27, 1.06, 0.18, 1.00)",
|
|
193
|
+
durationMs: 750,
|
|
194
|
+
} satisfies WebCurveToken,
|
|
195
|
+
effects: {
|
|
196
|
+
curve: "cubic-bezier(0.34, 0.88, 0.34, 1.00)",
|
|
197
|
+
durationMs: 300,
|
|
198
|
+
} satisfies WebCurveToken,
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
} as const;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get a Framer Motion spring config for the given scheme, speed, and type.
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```tsx
|
|
208
|
+
* transition={getSpring("expressive", "fast", "spatial")}
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
export function getSpring(
|
|
212
|
+
_scheme: MotionScheme,
|
|
213
|
+
speed: SpringSpeed,
|
|
214
|
+
type: SpringType,
|
|
215
|
+
): FramerSpring {
|
|
216
|
+
// Spring token values are scheme-agnostic; scheme is applied at product level.
|
|
217
|
+
return framerSprings[speed][type];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Get a CSS transition string for the given scheme, speed, and type.
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```ts
|
|
225
|
+
* element.style.transition = `transform ${getCSSTransition("expressive", "fast", "spatial")}`;
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
export function getCSSTransition(
|
|
229
|
+
scheme: MotionScheme,
|
|
230
|
+
speed: SpringSpeed,
|
|
231
|
+
type: SpringType,
|
|
232
|
+
): string {
|
|
233
|
+
const { curve, durationMs } = webCurves[scheme][speed][type];
|
|
234
|
+
return `${durationMs}ms ${curve}`;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
238
|
+
// Legacy: Duration tokens (ms) — md.sys.motion.duration.*
|
|
239
|
+
// Still valid; used as CSS fallback and for easing-based animations.
|
|
240
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
241
|
+
|
|
6
242
|
export const duration = {
|
|
7
243
|
short1: 50,
|
|
8
244
|
short2: 100,
|
|
@@ -22,10 +258,13 @@ export const duration = {
|
|
|
22
258
|
extraLong4: 1000,
|
|
23
259
|
} as const;
|
|
24
260
|
|
|
261
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
262
|
+
// Legacy: Easing tokens — md.sys.motion.easing.*
|
|
263
|
+
// Cubic-bezier control points [x1, y1, x2, y2].
|
|
264
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
265
|
+
|
|
25
266
|
export const easing = {
|
|
26
|
-
|
|
27
|
-
standardAccelerate: [0.3, 0, 1, 1] as [number, number, number, number],
|
|
28
|
-
standardDecelerate: [0, 0, 0, 1] as [number, number, number, number],
|
|
267
|
+
// Emphasized set — most common for M3 Expressive transitions
|
|
29
268
|
emphasized: [0.2, 0, 0, 1] as [number, number, number, number],
|
|
30
269
|
emphasizedAccelerate: [0.3, 0, 0.8, 0.15] as [number, number, number, number],
|
|
31
270
|
emphasizedDecelerate: [0.05, 0.7, 0.1, 1.0] as [
|
|
@@ -34,13 +273,45 @@ export const easing = {
|
|
|
34
273
|
number,
|
|
35
274
|
number,
|
|
36
275
|
],
|
|
276
|
+
|
|
277
|
+
// Standard set — for simple/utility transitions and CSS fallback
|
|
278
|
+
standard: [0.2, 0, 0, 1] as [number, number, number, number],
|
|
279
|
+
standardAccelerate: [0.3, 0, 1, 1] as [number, number, number, number],
|
|
280
|
+
standardDecelerate: [0, 0, 0, 1] as [number, number, number, number],
|
|
281
|
+
|
|
282
|
+
// Legacy set (M2 compat)
|
|
283
|
+
legacy: [0.4, 0, 0.2, 1] as [number, number, number, number],
|
|
284
|
+
legacyAccelerate: [0.4, 0, 1, 1] as [number, number, number, number],
|
|
285
|
+
legacyDecelerate: [0, 0, 0.2, 1] as [number, number, number, number],
|
|
286
|
+
|
|
287
|
+
// Linear
|
|
288
|
+
linear: [0, 0, 1, 1] as [number, number, number, number],
|
|
37
289
|
} as const;
|
|
38
290
|
|
|
291
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
292
|
+
// @deprecated Legacy spring presets — kept for backward compat only.
|
|
293
|
+
// Migrate to framerSprings.* or the named FAST_SPATIAL_SPRING etc. exports.
|
|
294
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
295
|
+
|
|
296
|
+
/** @deprecated Use `framerSprings.default.spatial` or `DEFAULT_SPATIAL_SPRING` instead. */
|
|
39
297
|
export const spring = {
|
|
40
|
-
default:
|
|
41
|
-
snappy:
|
|
42
|
-
gentle:
|
|
43
|
-
bouncy: {
|
|
298
|
+
default: framerSprings.default.spatial,
|
|
299
|
+
snappy: framerSprings.fast.spatial,
|
|
300
|
+
gentle: framerSprings.slow.spatial,
|
|
301
|
+
bouncy: {
|
|
302
|
+
...framerSprings.fast.spatial,
|
|
303
|
+
damping: framerSprings.fast.spatial.damping * 0.5,
|
|
304
|
+
},
|
|
44
305
|
} as const;
|
|
45
306
|
|
|
46
|
-
|
|
307
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
308
|
+
// Aggregate export
|
|
309
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
310
|
+
|
|
311
|
+
export const motionTokens = {
|
|
312
|
+
duration,
|
|
313
|
+
easing,
|
|
314
|
+
spring: md3SpringTokens,
|
|
315
|
+
framerSprings,
|
|
316
|
+
webCurves,
|
|
317
|
+
} as const;
|
package/src/shape.css
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
:root {
|
|
2
|
+
/* ── MD3 Expressive Corner Radius Scale (10 levels) ─────────────────────── */
|
|
3
|
+
/* Source: https://m3.material.io/styles/shape/corner-radius-scale */
|
|
4
|
+
|
|
2
5
|
--md-sys-shape-corner-none: 0px;
|
|
3
6
|
--md-sys-shape-corner-extra-small: 4px;
|
|
4
7
|
--md-sys-shape-corner-small: 8px;
|
|
5
8
|
--md-sys-shape-corner-medium: 12px;
|
|
6
9
|
--md-sys-shape-corner-large: 16px;
|
|
10
|
+
/* New in M3 Expressive (May 2025) */
|
|
11
|
+
--md-sys-shape-corner-large-increased: 20px;
|
|
7
12
|
--md-sys-shape-corner-extra-large: 28px;
|
|
13
|
+
/* New in M3 Expressive (May 2025) */
|
|
14
|
+
--md-sys-shape-corner-extra-large-increased: 32px;
|
|
15
|
+
/* New in M3 Expressive (May 2025) */
|
|
16
|
+
--md-sys-shape-corner-extra-extra-large: 48px;
|
|
8
17
|
--md-sys-shape-corner-full: 9999px;
|
|
9
18
|
}
|