astralkit 0.3.8 → 0.5.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ All notable changes to the `astralkit` SDK package.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.0] — 2026-06-12
9
+
10
+ ### Added (Material 3 role grammar)
11
+ - **45 new color-role tokens across both the v4 `@theme` and the v3 Tailwind plugin** (full v3/v4 parity). These complete the M3 role grammar that a large set of components now depend on:
12
+ - **Surface containers** — `surface-3`, `surface-4`, `surface-container`, `surface-container-low`/`-lowest`/`-high`/`-highest`.
13
+ - **Inverse** — `inverse-surface`, `inverse-on-surface` (dark cards on light themes and vice-versa).
14
+ - **Secondary / tertiary / accent / error roles** — `secondary`(+`-container`), `on-secondary`(+`-container`), `tertiary`(+`-container`), `on-tertiary`(+`-container`), `accent`, `accent-soft`, `on-accent`, `error`, `error-container`, `on-error`, `on-error-container`, plus `primary-container`/`on-primary-container`.
15
+ - **Surface / outline** — `on-surface`, `on-surface-variant`, `outline`, `outline-variant`, `scrim`.
16
+ - **Per-theme controls** — `slider-fill`, `slider-ring` (themed Radix slider fill/ring).
17
+ - **Status badges** — `status-{new,beta,stable,deprecated}-{bg,border,text}`.
18
+
19
+ ### Fixed
20
+ - **`ak-skeleton` shimmer now respects `prefers-reduced-motion`.** Added a `@media (prefers-reduced-motion: reduce)` guard that stops the looping shimmer on `.ak-skeleton::after`.
21
+
22
+ ## [0.4.0] — 2026-06-06
23
+
24
+ ### Added
25
+ - **`astralkit/motion`** — accessible Framer Motion presets tuned to the AstralKit motion tokens (`fadeInUp`, `fadeIn`, `scaleIn`, `staggerContainer`/`staggerItem`, `revealOnScroll`, `hoverLift`/`pressable`, `akTransition`, and `withReducedMotion`). Plain variant/transition objects — importing adds **no dependency**; bring your own `motion` (MIT). All presets are `prefers-reduced-motion`-safe via `withReducedMotion`.
26
+
27
+ ### Changed
28
+ - **Motion policy reversed: Framer Motion is now allowed.** The previous "no Framer Motion" rule was based on a licensing misunderstanding — the `motion` package is MIT. `ai-rules.md` now permits Framer Motion + CSS + Lenis and points to the `astralkit/motion` presets; **GSAP** is the disallowed one (its license restricts sold products/templates).
29
+ - `ai-rules.md`: motion guidance updated accordingly; premium-effect toolkit (`ak-card-glow`, `ak-mesh-*`, `ak-float`, `ak-scroll-fade`, etc.) emphasized for richer output.
30
+
8
31
  ## [0.3.8] — 2026-06-06
9
32
 
10
33
  ### Fixed
package/ai-rules.md CHANGED
@@ -19,7 +19,7 @@ These constraints prevent generic "AI slop" output. Follow them strictly.
19
19
 
20
20
  **Never use `text-white` or `text-black`.** Use `text-ak-on-primary` for text on primary-colored backgrounds, `text-ak-text-inverse` for text on dark/ink surfaces, and `text-ak-text` for standard text. Raw black/white breaks when palettes change — a theme with a dark primary and white on-primary text would get white-on-white if you hardcode `text-white`.
21
21
 
22
- **Never use Framer Motion.** CSS animations only. Use `ak-*` animation tokens (`duration-ak-base`, `ease-ak-default`) or effect primitives (`.ak-press`, `.ak-card-glow`).
22
+ **Motion: Framer Motion + CSS + Lenis are allowed; GSAP is not.** Framer Motion (the MIT `motion` package) is fine — prefer the `astralkit/motion` presets (tuned to the motion tokens, reduced-motion-safe). CSS animations via `ak-*` tokens (`duration-ak-base`, `ease-ak-spring`) and effect primitives (`.ak-press`, `.ak-card-glow`, `.ak-float`, `.ak-scroll-fade`) are also encouraged. Lenis for smooth scroll. Always honor `prefers-reduced-motion`. **Do not use GSAP** (its license disallows sold products/templates).
23
23
 
24
24
  **Never use shadows on containment surfaces.** No `shadow-md` on cards, panels, or dropdowns. Use `border border-ak-border` instead. Shadows are reserved for modals and floating elements only.
25
25
 
@@ -47,6 +47,8 @@
47
47
  --color-ak-bg: #ffffff;
48
48
  --color-ak-surface: #fafafa;
49
49
  --color-ak-surface-2: #f5f5f5;
50
+ --color-ak-surface-3: #efefef;
51
+ --color-ak-surface-4: #e9e9e9;
50
52
  --color-ak-hover: #f7f7f7;
51
53
  --color-ak-active: #f0f0f0;
52
54
  --color-ak-elevated: #ffffff;
@@ -54,6 +56,40 @@
54
56
  --color-ak-surface-raised-soft: rgba(255, 255, 255, 0.78);
55
57
  --color-ak-surface-glass: rgba(255, 255, 255, 0.72);
56
58
  --color-ak-surface-glass-strong: rgba(255, 255, 255, 0.84);
59
+
60
+ /* == M3 role layer (additive - old names remain working aliases forever) == */
61
+ --color-ak-inverse-surface: #171717;
62
+ --color-ak-inverse-on-surface: #fafafa;
63
+ --color-ak-on-error: #ffffff;
64
+ --color-ak-on-tertiary: #ffffff;
65
+ /* Selection accent: defaults to brand primary; palettes may split it
66
+ (e.g. Pulse: ink CTAs via primary, volt-lime selection via accent). */
67
+ --color-ak-accent: var(--color-ak-primary);
68
+ --color-ak-on-accent: var(--color-ak-on-primary);
69
+ --color-ak-accent-soft: var(--color-ak-surface-2);
70
+ /* M3 names as alias vars (follow their targets in dark automatically) */
71
+ --color-ak-surface-container-lowest: var(--color-ak-bg);
72
+ --color-ak-surface-container-low: var(--color-ak-surface);
73
+ --color-ak-surface-container: var(--color-ak-surface-2);
74
+ --color-ak-surface-container-high: var(--color-ak-surface-3);
75
+ --color-ak-surface-container-highest: var(--color-ak-surface-4);
76
+ --color-ak-on-surface: var(--color-ak-text);
77
+ --color-ak-on-surface-variant: var(--color-ak-text-secondary);
78
+ --color-ak-outline: var(--color-ak-border);
79
+ --color-ak-outline-variant: var(--color-ak-border-subtle);
80
+ --color-ak-primary-container: var(--color-ak-primary-subtle);
81
+ --color-ak-on-primary-container: var(--color-ak-primary-900);
82
+ --color-ak-secondary: var(--color-ak-accent);
83
+ --color-ak-on-secondary: var(--color-ak-on-accent);
84
+ --color-ak-secondary-container: var(--color-ak-accent-soft);
85
+ --color-ak-on-secondary-container: var(--color-ak-text);
86
+ --color-ak-tertiary: var(--color-ak-info);
87
+ --color-ak-tertiary-container: var(--color-ak-info-subtle);
88
+ --color-ak-on-tertiary-container: var(--color-ak-info-text);
89
+ --color-ak-error: var(--color-ak-danger);
90
+ --color-ak-error-container: var(--color-ak-danger-subtle);
91
+ --color-ak-on-error-container: var(--color-ak-danger-text);
92
+ --color-ak-scrim: var(--color-ak-overlay);
57
93
  --color-ak-highlight-soft: rgba(255, 255, 255, 0.45);
58
94
  --color-ak-highlight-strong: rgba(255, 255, 255, 0.72);
59
95
  --color-ak-skeleton-base: #ededed;
@@ -564,6 +600,12 @@
564
600
  --color-ak-bg: #111113;
565
601
  --color-ak-surface: #18191b;
566
602
  --color-ak-surface-2: #1e1f21;
603
+ --color-ak-surface-3: #252628;
604
+ --color-ak-surface-4: #2c2d30;
605
+ --color-ak-inverse-surface: #f4f4f5;
606
+ --color-ak-inverse-on-surface: #111113;
607
+ --color-ak-on-error: #111113;
608
+ --color-ak-on-tertiary: #111113;
567
609
  --color-ak-hover: rgba(255,255,255,0.04);
568
610
  --color-ak-active: rgba(255,255,255,0.08);
569
611
  --color-ak-elevated: #252628;
@@ -49,6 +49,8 @@
49
49
  --color-ak-bg: #ffffff;
50
50
  --color-ak-surface: #fafafa;
51
51
  --color-ak-surface-2: #f5f5f5;
52
+ --color-ak-surface-3: #efefef;
53
+ --color-ak-surface-4: #e9e9e9;
52
54
  --color-ak-hover: #f7f7f7;
53
55
  --color-ak-active: #f0f0f0;
54
56
  --color-ak-elevated: #ffffff;
@@ -56,6 +58,40 @@
56
58
  --color-ak-surface-raised-soft: rgba(255, 255, 255, 0.78);
57
59
  --color-ak-surface-glass: rgba(255, 255, 255, 0.72);
58
60
  --color-ak-surface-glass-strong: rgba(255, 255, 255, 0.84);
61
+
62
+ /* == M3 role layer (additive - old names remain working aliases forever) == */
63
+ --color-ak-inverse-surface: #171717;
64
+ --color-ak-inverse-on-surface: #fafafa;
65
+ --color-ak-on-error: #ffffff;
66
+ --color-ak-on-tertiary: #ffffff;
67
+ /* Selection accent: defaults to brand primary; palettes may split it
68
+ (e.g. Pulse: ink CTAs via primary, volt-lime selection via accent). */
69
+ --color-ak-accent: var(--color-ak-primary);
70
+ --color-ak-on-accent: var(--color-ak-on-primary);
71
+ --color-ak-accent-soft: var(--color-ak-surface-2);
72
+ /* M3 names as alias vars (follow their targets in dark automatically) */
73
+ --color-ak-surface-container-lowest: var(--color-ak-bg);
74
+ --color-ak-surface-container-low: var(--color-ak-surface);
75
+ --color-ak-surface-container: var(--color-ak-surface-2);
76
+ --color-ak-surface-container-high: var(--color-ak-surface-3);
77
+ --color-ak-surface-container-highest: var(--color-ak-surface-4);
78
+ --color-ak-on-surface: var(--color-ak-text);
79
+ --color-ak-on-surface-variant: var(--color-ak-text-secondary);
80
+ --color-ak-outline: var(--color-ak-border);
81
+ --color-ak-outline-variant: var(--color-ak-border-subtle);
82
+ --color-ak-primary-container: var(--color-ak-primary-subtle);
83
+ --color-ak-on-primary-container: var(--color-ak-primary-900);
84
+ --color-ak-secondary: var(--color-ak-accent);
85
+ --color-ak-on-secondary: var(--color-ak-on-accent);
86
+ --color-ak-secondary-container: var(--color-ak-accent-soft);
87
+ --color-ak-on-secondary-container: var(--color-ak-text);
88
+ --color-ak-tertiary: var(--color-ak-info);
89
+ --color-ak-tertiary-container: var(--color-ak-info-subtle);
90
+ --color-ak-on-tertiary-container: var(--color-ak-info-text);
91
+ --color-ak-error: var(--color-ak-danger);
92
+ --color-ak-error-container: var(--color-ak-danger-subtle);
93
+ --color-ak-on-error-container: var(--color-ak-danger-text);
94
+ --color-ak-scrim: var(--color-ak-overlay);
59
95
  --color-ak-highlight-soft: rgba(255, 255, 255, 0.45);
60
96
  --color-ak-highlight-strong: rgba(255, 255, 255, 0.72);
61
97
  --color-ak-skeleton-base: #ededed;
@@ -564,6 +600,12 @@
564
600
  --color-ak-bg: #111113;
565
601
  --color-ak-surface: #18191b;
566
602
  --color-ak-surface-2: #1e1f21;
603
+ --color-ak-surface-3: #252628;
604
+ --color-ak-surface-4: #2c2d30;
605
+ --color-ak-inverse-surface: #f4f4f5;
606
+ --color-ak-inverse-on-surface: #111113;
607
+ --color-ak-on-error: #111113;
608
+ --color-ak-on-tertiary: #111113;
567
609
  --color-ak-hover: rgba(255,255,255,0.04);
568
610
  --color-ak-active: rgba(255,255,255,0.08);
569
611
  --color-ak-elevated: #252628;
@@ -0,0 +1,29 @@
1
+ // Types for astralkit/motion. Kept structural (no framer-motion dependency).
2
+ // The objects are valid Framer Motion Variants / Transitions / motion props.
3
+
4
+ type AkVariants = Record<string, Record<string, unknown>>;
5
+ type AkTransition = Record<string, unknown>;
6
+ type AkMotionProps = Record<string, unknown>;
7
+
8
+ export declare const akTransition: {
9
+ fast: AkTransition;
10
+ smooth: AkTransition;
11
+ spring: AkTransition;
12
+ springSoft: AkTransition;
13
+ bounce: AkTransition;
14
+ };
15
+
16
+ export declare const fadeIn: AkVariants;
17
+ export declare const fadeInUp: AkVariants;
18
+ export declare const fadeInDown: AkVariants;
19
+ export declare const scaleIn: AkVariants;
20
+
21
+ export declare function staggerContainer(stagger?: number, delayChildren?: number): AkVariants;
22
+ export declare const staggerItem: AkVariants;
23
+
24
+ export declare const revealOnScroll: AkMotionProps;
25
+ export declare const pressable: AkMotionProps;
26
+ export declare const hoverLift: AkMotionProps;
27
+ export declare const hoverScale: AkMotionProps;
28
+
29
+ export declare function withReducedMotion(variants: AkVariants, reduced: boolean | null | undefined): AkVariants;
package/lib/motion.js ADDED
@@ -0,0 +1,85 @@
1
+ /**
2
+ * astralkit/motion — accessible Framer Motion presets tuned to AstralKit's
3
+ * motion tokens (--duration-ak-*, --ease-ak-spring/bounce/default).
4
+ *
5
+ * These are plain Framer Motion variant/transition OBJECTS — importing this
6
+ * module adds NO dependency. You bring your own `motion` (the MIT Framer
7
+ * Motion package) and spread/assign these presets:
8
+ *
9
+ * import { motion, useReducedMotion } from "motion/react"
10
+ * import { fadeInUp, staggerContainer, staggerItem, revealOnScroll, hoverLift, withReducedMotion } from "astralkit/motion"
11
+ *
12
+ * // Entrance
13
+ * <motion.div initial="hidden" animate="show" variants={fadeInUp} />
14
+ * // Staggered list
15
+ * <motion.ul initial="hidden" animate="show" variants={staggerContainer()}>
16
+ * {items.map(i => <motion.li key={i} variants={staggerItem} />)}
17
+ * </motion.ul>
18
+ * // Scroll reveal (spread onto the element)
19
+ * <motion.section {...revealOnScroll} />
20
+ * // Interaction
21
+ * <motion.button {...hoverLift} />
22
+ *
23
+ * Accessibility: ALWAYS honor reduced motion —
24
+ * const reduced = useReducedMotion()
25
+ * <motion.div initial="hidden" animate="show" variants={withReducedMotion(fadeInUp, reduced)} />
26
+ */
27
+
28
+ /** Transitions matched to AstralKit's --duration-ak-* / --ease-ak-* tokens. */
29
+ export const akTransition = {
30
+ fast: { duration: 0.11, ease: [0.4, 0, 0.2, 1] }, // --duration-ak-fast / --ease-ak-default
31
+ smooth: { duration: 0.24, ease: [0.4, 0, 0.2, 1] }, // --duration-ak-slow / --ease-ak-default
32
+ spring: { type: 'spring', stiffness: 400, damping: 30 }, // crisp UI spring
33
+ springSoft: { type: 'spring', stiffness: 260, damping: 26 },
34
+ bounce: { type: 'spring', stiffness: 500, damping: 18 }, // ~ --ease-ak-bounce
35
+ };
36
+
37
+ /** Entrance variants — use with initial="hidden" animate="show" (or whileInView). */
38
+ export const fadeIn = {
39
+ hidden: { opacity: 0 },
40
+ show: { opacity: 1, transition: akTransition.smooth },
41
+ };
42
+ export const fadeInUp = {
43
+ hidden: { opacity: 0, y: 12 },
44
+ show: { opacity: 1, y: 0, transition: akTransition.smooth },
45
+ };
46
+ export const fadeInDown = {
47
+ hidden: { opacity: 0, y: -12 },
48
+ show: { opacity: 1, y: 0, transition: akTransition.smooth },
49
+ };
50
+ export const scaleIn = {
51
+ hidden: { opacity: 0, scale: 0.96 },
52
+ show: { opacity: 1, scale: 1, transition: akTransition.spring },
53
+ };
54
+
55
+ /** Stagger a group of children (each child uses `staggerItem`). */
56
+ export const staggerContainer = (stagger = 0.06, delayChildren = 0) => ({
57
+ hidden: {},
58
+ show: { transition: { staggerChildren: stagger, delayChildren } },
59
+ });
60
+ export const staggerItem = fadeInUp;
61
+
62
+ /** Spread onto a motion element for a scroll-triggered reveal (animates once). */
63
+ export const revealOnScroll = {
64
+ initial: 'hidden',
65
+ whileInView: 'show',
66
+ viewport: { once: true, amount: 0.3 },
67
+ variants: fadeInUp,
68
+ };
69
+
70
+ /** Interaction presets — spread onto a motion element. */
71
+ export const pressable = { whileTap: { scale: 0.97 }, transition: akTransition.spring };
72
+ export const hoverLift = { whileHover: { y: -2 }, whileTap: { y: 0 }, transition: akTransition.spring };
73
+ export const hoverScale = { whileHover: { scale: 1.02 }, whileTap: { scale: 0.98 }, transition: akTransition.spring };
74
+
75
+ /**
76
+ * Return reduced-motion-safe variants. Pass the boolean from useReducedMotion().
77
+ * When reduced, transforms are dropped and only opacity changes (instantly).
78
+ */
79
+ export function withReducedMotion(variants, reduced) {
80
+ if (!reduced) return variants;
81
+ return {
82
+ hidden: { opacity: 0 },
83
+ show: { opacity: 1, transition: { duration: 0 } },
84
+ };
85
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astralkit",
3
- "version": "0.3.8",
3
+ "version": "0.5.0",
4
4
  "description": "Design tokens and component primitives for accessible UI — Tailwind CSS v3 & v4",
5
5
  "type": "module",
6
6
  "exports": {
@@ -10,6 +10,7 @@
10
10
  "./tailwind": "./tailwind.cjs",
11
11
  "./tailwind.cjs": "./tailwind.cjs",
12
12
  "./utils": "./lib/utils.js",
13
+ "./motion": "./lib/motion.js",
13
14
  "./ai-rules": "./ai-rules.md",
14
15
  "./palettes": "./palettes.css"
15
16
  },