astralkit 0.3.7 → 0.4.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,24 @@ 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.4.0] — 2026-06-06
9
+
10
+ ### Added
11
+ - **`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`.
12
+
13
+ ### Changed
14
+ - **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).
15
+ - `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.
16
+
17
+ ## [0.3.8] — 2026-06-06
18
+
19
+ ### Fixed
20
+ - **Body font corrected to Inter.** `--font-ak-sans` was `'DM Sans'` in `astralkit-theme.css`, `astralkit-theme-v4.css`, and the Tailwind plugin, contradicting the canonical Inter body font. Replaced with `'Inter'` everywhere.
21
+ - **Tailwind v3 plugin export repointed to `tailwind.cjs`.** `astralkit/tailwind` resolved to a stale `tailwind.js` that was both an incomplete token subset and broken under the package's `"type": "module"` (it used CommonJS `require()`). Removed `tailwind.js`; `astralkit/tailwind` now resolves to the complete `tailwind.cjs`. Single source of truth for v3 utilities.
22
+
23
+ ### Added (v3 plugin token parity with v4)
24
+ - Registered every token the v4 `@theme` auto-generates but the v3 plugin was missing: colors (`surface-raised`/`-soft`, `surface-glass`/`-strong`, `highlight-soft`/`-strong`, `skeleton-base`/`-shine`, `sheet-handle`, `pink`/`pink-subtle`), avatar/badge text sizes, spacing `ak-9`/`ak-11`/`ak-14`, `rounded-ak-xs`, `duration-ak-skeleton`, and `size-ak-avatar-xs`. v3 and v4 now expose an identical utility surface.
25
+
8
26
  ## [0.3.3] — 2026-04-22
9
27
 
10
28
  ### Changed
package/ai-rules.md CHANGED
@@ -19,11 +19,11 @@ 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
 
26
- **Never use generic fonts.** The system fonts are DM Sans (`font-ak-sans`), DM Serif Display (`font-ak-serif`), and JetBrains Mono (`font-ak-mono`). Do not add Arial, Inter, Roboto, or system-ui.
26
+ **Never use generic fonts.** The system fonts are Inter (`font-ak-sans`), DM Serif Display (`font-ak-serif`), and JetBrains Mono (`font-ak-mono`). Do not add Arial, DM Sans, Roboto, or bare system-ui.
27
27
 
28
28
  **Never put gradients on every surface.** Gradients are for hero sections and marketing areas only (`.ak-mesh-dark`, `.ak-mesh-light`). Dashboard chrome, cards, and data views use flat semantic surfaces.
29
29
 
@@ -96,7 +96,7 @@
96
96
  --color-ak-info-text: #1d4ed8;
97
97
 
98
98
  /* ── Font families ── */
99
- --font-ak-sans: 'DM Sans', system-ui, -apple-system, sans-serif;
99
+ --font-ak-sans: 'Inter', system-ui, -apple-system, sans-serif;
100
100
  --font-ak-serif: 'DM Serif Display', Georgia, serif;
101
101
  --font-ak-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, monospace;
102
102
 
@@ -98,7 +98,7 @@
98
98
  --color-ak-info-text: #1d4ed8;
99
99
 
100
100
  /* ── Font families ── */
101
- --font-ak-sans: 'DM Sans', system-ui, -apple-system, sans-serif;
101
+ --font-ak-sans: 'Inter', system-ui, -apple-system, sans-serif;
102
102
  --font-ak-serif: 'DM Serif Display', Georgia, serif;
103
103
  --font-ak-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, monospace;
104
104
 
@@ -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,15 +1,16 @@
1
1
  {
2
2
  "name": "astralkit",
3
- "version": "0.3.7",
3
+ "version": "0.4.0",
4
4
  "description": "Design tokens and component primitives for accessible UI — Tailwind CSS v3 & v4",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  "./theme": "./astralkit-theme.css",
8
8
  "./theme-v4": "./astralkit-theme-v4.css",
9
9
  "./utilities": "./astralkit-utilities.css",
10
- "./tailwind": "./tailwind.js",
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
  },
@@ -19,7 +20,6 @@
19
20
  "astralkit-utilities.css",
20
21
  "palettes.css",
21
22
  "primitives/",
22
- "tailwind.js",
23
23
  "tailwind.cjs",
24
24
  "ai-rules.md",
25
25
  "lib/",
package/tailwind.cjs CHANGED
@@ -44,8 +44,11 @@ const AK_SPACING = {
44
44
  'ak-6': 'var(--spacing-ak-6)',
45
45
  'ak-7': 'var(--spacing-ak-7)',
46
46
  'ak-8': 'var(--spacing-ak-8)',
47
+ 'ak-9': 'var(--spacing-ak-9)',
47
48
  'ak-10': 'var(--spacing-ak-10)',
49
+ 'ak-11': 'var(--spacing-ak-11)',
48
50
  'ak-12': 'var(--spacing-ak-12)',
51
+ 'ak-14': 'var(--spacing-ak-14)',
49
52
  'ak-16': 'var(--spacing-ak-16)',
50
53
  'ak-20': 'var(--spacing-ak-20)',
51
54
  'ak-24': 'var(--spacing-ak-24)',
@@ -107,6 +110,15 @@ module.exports = plugin(
107
110
  'ak-hover': 'var(--color-ak-hover)',
108
111
  'ak-active': 'var(--color-ak-active)',
109
112
  'ak-elevated': 'var(--color-ak-elevated)',
113
+ 'ak-surface-raised': 'var(--color-ak-surface-raised)',
114
+ 'ak-surface-raised-soft': 'var(--color-ak-surface-raised-soft)',
115
+ 'ak-surface-glass': 'var(--color-ak-surface-glass)',
116
+ 'ak-surface-glass-strong': 'var(--color-ak-surface-glass-strong)',
117
+ 'ak-highlight-soft': 'var(--color-ak-highlight-soft)',
118
+ 'ak-highlight-strong': 'var(--color-ak-highlight-strong)',
119
+ 'ak-skeleton-base': 'var(--color-ak-skeleton-base)',
120
+ 'ak-skeleton-shine': 'var(--color-ak-skeleton-shine)',
121
+ 'ak-sheet-handle': 'var(--color-ak-sheet-handle)',
110
122
  'ak-on-primary': 'var(--color-ak-on-primary)',
111
123
  'ak-primary-subtle': 'var(--color-ak-primary-subtle)',
112
124
  'ak-primary-subtle-hover': 'var(--color-ak-primary-subtle-hover)',
@@ -141,6 +153,8 @@ module.exports = plugin(
141
153
  'ak-info': 'var(--color-ak-info)',
142
154
  'ak-info-subtle': 'var(--color-ak-info-subtle)',
143
155
  'ak-info-text': 'var(--color-ak-info-text)',
156
+ 'ak-pink': 'var(--color-ak-pink)',
157
+ 'ak-pink-subtle': 'var(--color-ak-pink-subtle)',
144
158
  'ak-chart-1': 'var(--color-ak-chart-1)',
145
159
  'ak-chart-2': 'var(--color-ak-chart-2)',
146
160
  'ak-chart-3': 'var(--color-ak-chart-3)',
@@ -186,7 +200,7 @@ module.exports = plugin(
186
200
 
187
201
  /* ── Font Family ── */
188
202
  fontFamily: {
189
- 'ak-sans': ['DM Sans', 'system-ui', '-apple-system', 'sans-serif'],
203
+ 'ak-sans': ['Inter', 'system-ui', '-apple-system', 'sans-serif'],
190
204
  'ak-serif': ['DM Serif Display', 'Georgia', 'serif'],
191
205
  'ak-mono': ['JetBrains Mono', 'Fira Code', 'ui-monospace', 'monospace'],
192
206
  },
@@ -264,6 +278,20 @@ module.exports = plugin(
264
278
  'ak-watermark-3xl': 'clamp(1rem, 33cqi, 38rem)',
265
279
  'ak-watermark-4xl': 'clamp(1rem, 36cqi, 42rem)',
266
280
  'ak-watermark-5xl': 'clamp(1rem, 40cqi, 48rem)',
281
+ // Avatar initials font size
282
+ 'ak-avatar-xs': 'var(--text-ak-avatar-xs)',
283
+ 'ak-avatar-sm': 'var(--text-ak-avatar-sm)',
284
+ 'ak-avatar-md': 'var(--text-ak-avatar-md)',
285
+ 'ak-avatar-lg': 'var(--text-ak-avatar-lg)',
286
+ 'ak-avatar-xl': 'var(--text-ak-avatar-xl)',
287
+ 'ak-avatar-2xl': 'var(--text-ak-avatar-2xl)',
288
+ 'ak-avatar-3xl': 'var(--text-ak-avatar-3xl)',
289
+ // Badge text size
290
+ 'ak-badge-md': 'var(--text-ak-badge-md)',
291
+ 'ak-badge-lg': 'var(--text-ak-badge-lg)',
292
+ 'ak-badge-xl': 'var(--text-ak-badge-xl)',
293
+ 'ak-badge-2xl': 'var(--text-ak-badge-2xl)',
294
+ 'ak-badge-3xl': 'var(--text-ak-badge-3xl)',
267
295
  },
268
296
 
269
297
  /* ── Line Height ── */
@@ -299,6 +327,7 @@ module.exports = plugin(
299
327
  /* ── Border Radius ── */
300
328
  borderRadius: {
301
329
  'ak-none': 'var(--radius-ak-none)',
330
+ 'ak-xs': 'var(--radius-ak-xs)',
302
331
  'ak-sm': 'var(--radius-ak-sm)',
303
332
  'ak-md': 'var(--radius-ak-md)',
304
333
  'ak-lg': 'var(--radius-ak-lg)',
@@ -425,6 +454,7 @@ module.exports = plugin(
425
454
  'ak-icon-xl': 'var(--size-ak-icon-xl)',
426
455
  'ak-icon-2xl': 'var(--size-ak-icon-2xl)',
427
456
  'ak-icon-3xl': 'var(--size-ak-icon-3xl)',
457
+ 'ak-avatar-xs': 'var(--size-ak-avatar-xs)',
428
458
  'ak-avatar-sm': 'var(--size-ak-avatar-sm)',
429
459
  'ak-avatar-md': 'var(--size-ak-avatar-md)',
430
460
  'ak-avatar-lg': 'var(--size-ak-avatar-lg)',
@@ -437,9 +467,10 @@ module.exports = plugin(
437
467
 
438
468
  /* ── Transition Duration ── */
439
469
  transitionDuration: {
440
- 'ak-fast': 'var(--duration-ak-fast)',
441
- 'ak-base': 'var(--duration-ak-base)',
442
- 'ak-slow': 'var(--duration-ak-slow)',
470
+ 'ak-fast': 'var(--duration-ak-fast)',
471
+ 'ak-base': 'var(--duration-ak-base)',
472
+ 'ak-slow': 'var(--duration-ak-slow)',
473
+ 'ak-skeleton': 'var(--duration-ak-skeleton)',
443
474
  },
444
475
 
445
476
  /* ── Transition Timing Function ── */
package/tailwind.js DELETED
@@ -1,491 +0,0 @@
1
- /**
2
- * AstralKit Tailwind CSS v3 Compatibility Plugin
3
- *
4
- * Registers all ak-* design tokens as Tailwind theme extensions
5
- * so that utility classes like bg-ak-bg, text-ak-text, p-ak-2, etc.
6
- * work in Tailwind v3 projects.
7
- *
8
- * Usage (tailwind.config.js):
9
- * const astralkit = require('astralkit/tailwind')
10
- * module.exports = { plugins: [astralkit] }
11
- *
12
- * In Tailwind v4, this plugin is NOT needed — the @theme directive
13
- * in astralkit/theme-v4 handles everything automatically.
14
- */
15
-
16
- const plugin = require('tailwindcss/plugin')
17
-
18
- // Shared spacing map — used by spacing, width, height, minWidth, minHeight, maxWidth
19
- // In Tailwind v4 spacing auto-feeds all sizing utils; in v3 we must extend each explicitly
20
- const AK_SPACING = {
21
- 'ak-0': 'var(--spacing-ak-0)',
22
- 'ak-px': 'var(--spacing-ak-px)',
23
- 'ak-0_5': 'var(--spacing-ak-0_5)',
24
- 'ak-0.5': 'var(--spacing-ak-0_5)',
25
- 'ak-1': 'var(--spacing-ak-1)',
26
- 'ak-1_5': 'var(--spacing-ak-1_5)',
27
- 'ak-1.5': 'var(--spacing-ak-1_5)',
28
- 'ak-2': 'var(--spacing-ak-2)',
29
- 'ak-2_5': 'var(--spacing-ak-2_5)',
30
- 'ak-2.5': 'var(--spacing-ak-2_5)',
31
- 'ak-3': 'var(--spacing-ak-3)',
32
- 'ak-3_5': 'var(--spacing-ak-3_5)',
33
- 'ak-3.5': 'var(--spacing-ak-3_5)',
34
- 'ak-4': 'var(--spacing-ak-4)',
35
- 'ak-4_5': 'var(--spacing-ak-4_5)',
36
- 'ak-4.5': 'var(--spacing-ak-4_5)',
37
- 'ak-5': 'var(--spacing-ak-5)',
38
- 'ak-5_5': 'var(--spacing-ak-5_5)',
39
- 'ak-5.5': 'var(--spacing-ak-5_5)',
40
- 'ak-6': 'var(--spacing-ak-6)',
41
- 'ak-7': 'var(--spacing-ak-7)',
42
- 'ak-8': 'var(--spacing-ak-8)',
43
- 'ak-10': 'var(--spacing-ak-10)',
44
- 'ak-12': 'var(--spacing-ak-12)',
45
- 'ak-16': 'var(--spacing-ak-16)',
46
- 'ak-20': 'var(--spacing-ak-20)',
47
- 'ak-24': 'var(--spacing-ak-24)',
48
- 'ak-mobile-bar': 'var(--spacing-ak-mobile-bar)',
49
- }
50
-
51
- module.exports = plugin(
52
- // Plugin function — injects the CSS custom property definitions as base styles
53
- function ({ addBase }) {
54
- addBase({
55
- ':root': {
56
- /* ── Neutral scale ── */
57
- '--color-ak-neutral-0': '#ffffff',
58
- '--color-ak-neutral-50': '#fafafa',
59
- '--color-ak-neutral-100': '#f5f5f5',
60
- '--color-ak-neutral-200': '#e5e5e5',
61
- '--color-ak-neutral-300': '#d4d4d4',
62
- '--color-ak-neutral-400': '#a3a3a3',
63
- '--color-ak-neutral-500': '#737373',
64
- '--color-ak-neutral-600': '#525252',
65
- '--color-ak-neutral-700': '#404040',
66
- '--color-ak-neutral-800': '#262626',
67
- '--color-ak-neutral-900': '#171717',
68
- '--color-ak-neutral-950': '#0a0a0a',
69
-
70
- /* ── Primary scale ── */
71
- '--color-ak-primary-50': '#f5f5f5',
72
- '--color-ak-primary-100': '#e5e5e5',
73
- '--color-ak-primary-200': '#cccccc',
74
- '--color-ak-primary-300': '#a3a3a3',
75
- '--color-ak-primary-400': '#737373',
76
- '--color-ak-primary-500': '#525252',
77
- '--color-ak-primary-600': '#404040',
78
- '--color-ak-primary-700': '#333333',
79
- '--color-ak-primary-800': '#1a1a1a',
80
- '--color-ak-primary-900': '#000000',
81
- '--color-ak-primary-950': '#000000',
82
-
83
- /* ── Primary action ── */
84
- '--color-ak-primary': '#000000',
85
- '--color-ak-primary-hover': '#1a1a1a',
86
- '--color-ak-primary-active': '#333333',
87
-
88
- /* ── Semantic surfaces ── */
89
- '--color-ak-bg': '#ffffff',
90
- '--color-ak-surface': '#fafafa',
91
- '--color-ak-surface-2': '#f5f5f5',
92
- '--color-ak-hover': '#f7f7f7',
93
- '--color-ak-active': '#f0f0f0',
94
- '--color-ak-elevated': '#ffffff',
95
- '--color-ak-surface-raised': '#ffffff',
96
- '--color-ak-surface-raised-soft': 'rgba(255, 255, 255, 0.78)',
97
- '--color-ak-surface-glass': 'rgba(255, 255, 255, 0.72)',
98
- '--color-ak-surface-glass-strong': 'rgba(255, 255, 255, 0.84)',
99
- '--color-ak-highlight-soft': 'rgba(255, 255, 255, 0.45)',
100
- '--color-ak-highlight-strong': 'rgba(255, 255, 255, 0.72)',
101
- '--color-ak-skeleton-base': '#ededed',
102
- '--color-ak-skeleton-shine': 'rgba(255, 255, 255, 0.72)',
103
- '--color-ak-overlay': 'rgba(0, 0, 0, 0.5)',
104
- '--color-ak-on-primary': '#ffffff',
105
- '--color-ak-primary-subtle': '#f5f5f5',
106
-
107
- /* ── Semantic text ── */
108
- '--color-ak-text': '#171717',
109
- '--color-ak-text-secondary': '#525252',
110
- '--color-ak-text-muted': '#a3a3a3',
111
- '--color-ak-text-disabled': '#d4d4d4',
112
- '--color-ak-text-inverse': '#ffffff',
113
- '--color-ak-text-link': '#000000',
114
- '--color-ak-text-placeholder':'#a3a3a3',
115
-
116
- /* ── Semantic border ── */
117
- '--color-ak-border': '#e5e5e5',
118
- '--color-ak-border-subtle': '#f5f5f5',
119
- '--color-ak-border-strong': '#d4d4d4',
120
- '--color-ak-border-focus': '#000000',
121
-
122
- /* ── Status ── */
123
- '--color-ak-success': '#16a34a',
124
- '--color-ak-success-subtle': '#f0fdf4',
125
- '--color-ak-success-text': '#15803d',
126
- '--color-ak-warning': '#d97706',
127
- '--color-ak-warning-subtle': '#fffbeb',
128
- '--color-ak-warning-text': '#b45309',
129
- '--color-ak-danger': '#dc2626',
130
- '--color-ak-danger-subtle': '#fef2f2',
131
- '--color-ak-danger-text': '#b91c1c',
132
- '--color-ak-info': '#2563eb',
133
- '--color-ak-info-subtle': '#eff6ff',
134
- '--color-ak-info-text': '#1d4ed8',
135
-
136
- /* ── Spacing tokens ── */
137
- '--spacing-ak-0': '0rem',
138
- '--spacing-ak-px': '0.0625rem',
139
- '--spacing-ak-0_5': '0.25rem',
140
- '--spacing-ak-1': '0.5rem',
141
- '--spacing-ak-1_5': '0.75rem',
142
- '--spacing-ak-2': '1rem',
143
- '--spacing-ak-2_5': '1.25rem',
144
- '--spacing-ak-3': '1.5rem',
145
- '--spacing-ak-3_5': '1.75rem',
146
- '--spacing-ak-4': '2rem',
147
- '--spacing-ak-4_5': '2.25rem',
148
- '--spacing-ak-5': '2.5rem',
149
- '--spacing-ak-5_5': '2.75rem',
150
- '--spacing-ak-6': '3rem',
151
- '--spacing-ak-7': '3.5rem',
152
- '--spacing-ak-8': '4rem',
153
- '--spacing-ak-10': '5rem',
154
- '--spacing-ak-12': '6rem',
155
- '--spacing-ak-16': '8rem',
156
- '--spacing-ak-20': '10rem',
157
- '--spacing-ak-24': '12rem',
158
- '--spacing-ak-mobile-bar': '4.5rem',
159
-
160
- /* ── Size tokens ── */
161
- '--size-ak-panel-width': '260px',
162
- '--size-ak-icon-xs': '0.75rem',
163
- '--size-ak-icon-sm': '1rem',
164
- '--size-ak-icon-md': '1.25rem',
165
- '--size-ak-icon-lg': '1.5rem',
166
- '--size-ak-icon-xl': '1.75rem',
167
- '--size-ak-icon-2xl': '2rem',
168
- '--size-ak-icon-3xl': '3rem',
169
- '--size-ak-sheet-handle-width': '2.25rem',
170
- '--size-ak-sheet-handle-height': '0.25rem',
171
- '--color-ak-sheet-handle': '#d4d4d4',
172
-
173
- /* ── Animation tokens ── */
174
- '--duration-ak-fast': '110ms',
175
- '--duration-ak-base': '150ms',
176
- '--duration-ak-slow': '240ms',
177
- '--duration-ak-skeleton': '1800ms',
178
- '--ease-ak-default': 'cubic-bezier(0.4, 0, 0.2, 1)',
179
- '--ease-ak-in': 'cubic-bezier(0.4, 0, 1, 1)',
180
- '--ease-ak-out': 'cubic-bezier(0, 0, 0.2, 1)',
181
- '--ease-ak-spring': 'cubic-bezier(0.34, 1.56, 0.64, 1)',
182
- '--ease-ak-bounce': 'cubic-bezier(0.25, 1, 0.5, 1)',
183
-
184
- /* ── Z-index tokens ── */
185
- '--z-ak-sticky': '100',
186
- '--z-ak-dropdown': '200',
187
- '--z-ak-overlay': '300',
188
- '--z-ak-modal': '400',
189
-
190
- /* ── Radius tokens ── */
191
- '--radius-ak-none': '0',
192
- '--radius-ak-sm': '0.25rem',
193
- '--radius-ak-md': '0.5rem',
194
- '--radius-ak-lg': '0.75rem',
195
- '--radius-ak-xl': '1rem',
196
- '--radius-ak-2xl': '1.5rem',
197
- '--radius-ak-3xl': '2rem',
198
- '--radius-ak-full': '9999px',
199
-
200
- /* ── Font families ── */
201
- '--font-ak-sans': "'DM Sans', system-ui, -apple-system, sans-serif",
202
- '--font-ak-serif': "'DM Serif Display', Georgia, serif",
203
- '--font-ak-mono': "'JetBrains Mono', 'Fira Code', ui-monospace, monospace",
204
- },
205
- })
206
- },
207
-
208
- // Config — extends Tailwind's theme with ak-* utilities
209
- {
210
- theme: {
211
- extend: {
212
- /* ── Colors ──
213
- Every ak-* color token becomes a Tailwind color utility:
214
- bg-ak-bg, text-ak-text, border-ak-border, etc. */
215
- colors: {
216
- // Neutral scale
217
- 'ak-neutral-0': 'var(--color-ak-neutral-0)',
218
- 'ak-neutral-50': 'var(--color-ak-neutral-50)',
219
- 'ak-neutral-100': 'var(--color-ak-neutral-100)',
220
- 'ak-neutral-200': 'var(--color-ak-neutral-200)',
221
- 'ak-neutral-300': 'var(--color-ak-neutral-300)',
222
- 'ak-neutral-400': 'var(--color-ak-neutral-400)',
223
- 'ak-neutral-500': 'var(--color-ak-neutral-500)',
224
- 'ak-neutral-600': 'var(--color-ak-neutral-600)',
225
- 'ak-neutral-700': 'var(--color-ak-neutral-700)',
226
- 'ak-neutral-800': 'var(--color-ak-neutral-800)',
227
- 'ak-neutral-900': 'var(--color-ak-neutral-900)',
228
- 'ak-neutral-950': 'var(--color-ak-neutral-950)',
229
-
230
- // Primary scale
231
- 'ak-primary-50': 'var(--color-ak-primary-50)',
232
- 'ak-primary-100': 'var(--color-ak-primary-100)',
233
- 'ak-primary-200': 'var(--color-ak-primary-200)',
234
- 'ak-primary-300': 'var(--color-ak-primary-300)',
235
- 'ak-primary-400': 'var(--color-ak-primary-400)',
236
- 'ak-primary-500': 'var(--color-ak-primary-500)',
237
- 'ak-primary-600': 'var(--color-ak-primary-600)',
238
- 'ak-primary-700': 'var(--color-ak-primary-700)',
239
- 'ak-primary-800': 'var(--color-ak-primary-800)',
240
- 'ak-primary-900': 'var(--color-ak-primary-900)',
241
- 'ak-primary-950': 'var(--color-ak-primary-950)',
242
-
243
- // Primary action
244
- 'ak-primary': 'var(--color-ak-primary)',
245
- 'ak-primary-hover': 'var(--color-ak-primary-hover)',
246
- 'ak-primary-active': 'var(--color-ak-primary-active)',
247
-
248
- // Semantic surfaces
249
- 'ak-bg': 'var(--color-ak-bg)',
250
- 'ak-surface': 'var(--color-ak-surface)',
251
- 'ak-surface-2': 'var(--color-ak-surface-2)',
252
- 'ak-hover': 'var(--color-ak-hover)',
253
- 'ak-active': 'var(--color-ak-active)',
254
- 'ak-elevated': 'var(--color-ak-elevated)',
255
- 'ak-on-primary': 'var(--color-ak-on-primary)',
256
- 'ak-primary-subtle': 'var(--color-ak-primary-subtle)',
257
- 'ak-overlay': 'var(--color-ak-overlay)',
258
-
259
- // Semantic text
260
- 'ak-text': 'var(--color-ak-text)',
261
- 'ak-text-secondary': 'var(--color-ak-text-secondary)',
262
- 'ak-text-muted': 'var(--color-ak-text-muted)',
263
- 'ak-text-disabled': 'var(--color-ak-text-disabled)',
264
- 'ak-text-inverse': 'var(--color-ak-text-inverse)',
265
- 'ak-text-link': 'var(--color-ak-text-link)',
266
- 'ak-text-placeholder':'var(--color-ak-text-placeholder)',
267
-
268
- // Semantic border
269
- 'ak-border': 'var(--color-ak-border)',
270
- 'ak-border-subtle': 'var(--color-ak-border-subtle)',
271
- 'ak-border-strong': 'var(--color-ak-border-strong)',
272
- 'ak-border-focus': 'var(--color-ak-border-focus)',
273
-
274
- // Status
275
- 'ak-success': 'var(--color-ak-success)',
276
- 'ak-success-subtle': 'var(--color-ak-success-subtle)',
277
- 'ak-success-text': 'var(--color-ak-success-text)',
278
- 'ak-warning': 'var(--color-ak-warning)',
279
- 'ak-warning-subtle': 'var(--color-ak-warning-subtle)',
280
- 'ak-warning-text': 'var(--color-ak-warning-text)',
281
- 'ak-danger': 'var(--color-ak-danger)',
282
- 'ak-danger-subtle': 'var(--color-ak-danger-subtle)',
283
- 'ak-danger-text': 'var(--color-ak-danger-text)',
284
- 'ak-info': 'var(--color-ak-info)',
285
- 'ak-info-subtle': 'var(--color-ak-info-subtle)',
286
- 'ak-info-text': 'var(--color-ak-info-text)',
287
- },
288
-
289
- /* ── Spacing ──
290
- p-ak-2, m-ak-3, gap-ak-1, etc.
291
- In v3, spacing doesn't auto-feed into w-/h-/min-w-/min-h-/max-w-
292
- so we also spread AK_SPACING into those configs below. */
293
- spacing: {
294
- ...AK_SPACING,
295
- // Fluid spacing
296
- 'ak-fl-3xs': 'clamp(0.25rem, 0.21rem + 0.14vw, 0.375rem)',
297
- 'ak-fl-2xs': 'clamp(0.5rem, 0.43rem + 0.28vw, 0.75rem)',
298
- 'ak-fl-xs': 'clamp(0.75rem, 0.65rem + 0.42vw, 1rem)',
299
- 'ak-fl-sm': 'clamp(1rem, 0.86rem + 0.56vw, 1.5rem)',
300
- 'ak-fl-md': 'clamp(1.5rem, 1.29rem + 0.83vw, 2rem)',
301
- 'ak-fl-lg': 'clamp(2rem, 1.72rem + 1.11vw, 3rem)',
302
- 'ak-fl-xl': 'clamp(3rem, 2.5rem + 1.85vw, 4.5rem)',
303
- 'ak-fl-2xl': 'clamp(4rem, 3.22rem + 2.78vw, 6rem)',
304
- 'ak-fl-3xl': 'clamp(6rem, 4.86rem + 4.17vw, 9rem)',
305
- // Fluid space pairs
306
- 'ak-fl-xs-md': 'clamp(0.75rem, 0.43rem + 1.39vw, 2rem)',
307
- 'ak-fl-xs-lg': 'clamp(0.75rem, 0.14rem + 2.78vw, 3rem)',
308
- 'ak-fl-sm-lg': 'clamp(1rem, 0.43rem + 2.78vw, 3rem)',
309
- 'ak-fl-sm-xl': 'clamp(1rem, 0rem + 4.17vw, 4.5rem)',
310
- 'ak-fl-md-xl': 'clamp(1.5rem, 0.57rem + 3.47vw, 4.5rem)',
311
- 'ak-fl-md-2xl': 'clamp(1.5rem, 0rem + 5.56vw, 6rem)',
312
- 'ak-fl-lg-2xl': 'clamp(2rem, 0.57rem + 5.56vw, 6rem)',
313
- 'ak-fl-xl-3xl': 'clamp(3rem, 0.57rem + 8.33vw, 9rem)',
314
- },
315
-
316
- /* ── Font Family ── */
317
- fontFamily: {
318
- 'ak-sans': ['DM Sans', 'system-ui', '-apple-system', 'sans-serif'],
319
- 'ak-serif': ['DM Serif Display', 'Georgia', 'serif'],
320
- 'ak-mono': ['JetBrains Mono', 'Fira Code', 'ui-monospace', 'monospace'],
321
- },
322
-
323
- /* ── Font Size ──
324
- text-ak-base, text-ak-lg, text-ak-fl-2xl, etc. */
325
- fontSize: {
326
- // Static scale
327
- 'ak-2xs': 'var(--text-ak-2xs)',
328
- 'ak-xs': 'var(--text-ak-xs)',
329
- 'ak-sm': 'var(--text-ak-sm)',
330
- 'ak-base': 'var(--text-ak-base)',
331
- 'ak-lg': 'var(--text-ak-lg)',
332
- 'ak-xl': 'var(--text-ak-xl)',
333
- 'ak-2xl': 'var(--text-ak-2xl)',
334
- 'ak-3xl': 'var(--text-ak-3xl)',
335
- 'ak-4xl': 'var(--text-ak-4xl)',
336
- 'ak-5xl': 'var(--text-ak-5xl)',
337
- 'ak-6xl': 'var(--text-ak-6xl)',
338
- 'ak-7xl': 'var(--text-ak-7xl)',
339
- 'ak-8xl': 'var(--text-ak-8xl)',
340
- 'ak-9xl': 'var(--text-ak-9xl)',
341
- // Fluid scale
342
- 'ak-fl-xs': 'clamp(0.6875rem, 0.67rem + 0.06vw, 0.75rem)',
343
- 'ak-fl-sm': 'clamp(0.75rem, 0.71rem + 0.12vw, 0.875rem)',
344
- 'ak-fl-base': 'clamp(0.875rem, 0.84rem + 0.12vw, 1rem)',
345
- 'ak-fl-lg': 'clamp(1rem, 0.96rem + 0.12vw, 1.125rem)',
346
- 'ak-fl-xl': 'clamp(1.125rem, 1.09rem + 0.12vw, 1.25rem)',
347
- 'ak-fl-2xl': 'clamp(1.25rem, 1.18rem + 0.23vw, 1.5rem)',
348
- 'ak-fl-3xl': 'clamp(1.5rem, 1.39rem + 0.35vw, 1.875rem)',
349
- 'ak-fl-4xl': 'clamp(1.875rem, 1.76rem + 0.35vw, 2.25rem)',
350
- 'ak-fl-5xl': 'clamp(2.25rem, 2.03rem + 0.69vw, 3rem)',
351
- 'ak-fl-6xl': 'clamp(3rem, 2.78rem + 0.69vw, 3.75rem)',
352
- 'ak-fl-7xl': 'clamp(3.5rem, 3.2rem + 0.93vw, 4.5rem)',
353
- 'ak-fl-8xl': 'clamp(4.5rem, 4.06rem + 1.39vw, 6rem)',
354
- 'ak-fl-9xl': 'clamp(5.25rem, 4.73rem + 1.62vw, 7rem)',
355
- // Display scale
356
- 'ak-display-xs': 'clamp(0.75rem, 0.7rem + 0.15vw, 0.875rem)',
357
- 'ak-display-sm': 'clamp(0.875rem, 0.83rem + 0.19vw, 1rem)',
358
- 'ak-display-base': 'clamp(1rem, 0.94rem + 0.28vw, 1.1875rem)',
359
- 'ak-display-lg': 'clamp(1.125rem, 1.01rem + 0.52vw, 1.5rem)',
360
- 'ak-display-xl': 'clamp(1.25rem, 1.07rem + 0.83vw, 1.875rem)',
361
- 'ak-display-2xl': 'clamp(1.5rem, 1.2rem + 1.11vw, 2.25rem)',
362
- 'ak-display-3xl': 'clamp(1.875rem, 1.42rem + 1.67vw, 3rem)',
363
- 'ak-display-4xl': 'clamp(2.25rem, 1.58rem + 2.5vw, 3.75rem)',
364
- 'ak-display-5xl': 'clamp(3rem, 2.07rem + 3.47vw, 5.25rem)',
365
- 'ak-display-6xl': 'clamp(3.75rem, 2.5rem + 4.63vw, 7rem)',
366
- 'ak-display-7xl': 'clamp(4.5rem, 3.06rem + 5.56vw, 8rem)',
367
- 'ak-display-8xl': 'clamp(5rem, 3.06rem + 6.94vw, 9rem)',
368
- 'ak-display-9xl': 'clamp(5.5rem, 3.06rem + 7.64vw, 10rem)',
369
- },
370
-
371
- /* ── Line Height ── */
372
- lineHeight: {
373
- 'ak-display': 'var(--leading-ak-display)',
374
- 'ak-tighter': 'var(--leading-ak-tighter)',
375
- 'ak-none': 'var(--leading-ak-none)',
376
- 'ak-tight': 'var(--leading-ak-tight)',
377
- 'ak-snug': 'var(--leading-ak-snug)',
378
- 'ak-normal': 'var(--leading-ak-normal)',
379
- 'ak-relaxed': 'var(--leading-ak-relaxed)',
380
- 'ak-loose': 'var(--leading-ak-loose)',
381
- },
382
-
383
- /* ── Letter Spacing ── */
384
- letterSpacing: {
385
- 'ak-tighter': 'var(--tracking-ak-tighter)',
386
- 'ak-tight': 'var(--tracking-ak-tight)',
387
- 'ak-normal': 'var(--tracking-ak-normal)',
388
- 'ak-wide': 'var(--tracking-ak-wide)',
389
- 'ak-wider': 'var(--tracking-ak-wider)',
390
- 'ak-widest': 'var(--tracking-ak-widest)',
391
- },
392
-
393
- /* ── Border Radius ── */
394
- borderRadius: {
395
- 'ak-none': 'var(--radius-ak-none)',
396
- 'ak-sm': 'var(--radius-ak-sm)',
397
- 'ak-md': 'var(--radius-ak-md)',
398
- 'ak-lg': 'var(--radius-ak-lg)',
399
- 'ak-xl': 'var(--radius-ak-xl)',
400
- 'ak-2xl': 'var(--radius-ak-2xl)',
401
- 'ak-3xl': 'var(--radius-ak-3xl)',
402
- 'ak-full': 'var(--radius-ak-full)',
403
- },
404
-
405
- /* ── Box Shadow ── */
406
- boxShadow: {
407
- 'ak-xs': 'var(--shadow-ak-xs)',
408
- 'ak-sm': 'var(--shadow-ak-sm)',
409
- 'ak-md': 'var(--shadow-ak-md)',
410
- 'ak-lg': 'var(--shadow-ak-lg)',
411
- 'ak-xl': 'var(--shadow-ak-xl)',
412
- 'ak-2xl': 'var(--shadow-ak-2xl)',
413
- },
414
-
415
- /* ── Max Width (containers) ── */
416
- maxWidth: {
417
- 'ak-page': 'var(--container-ak-page)',
418
- 'ak-xs': 'var(--container-ak-xs)',
419
- 'ak-sm': 'var(--container-ak-sm)',
420
- 'ak-md': 'var(--container-ak-md)',
421
- 'ak-lg': 'var(--container-ak-lg)',
422
- 'ak-xl': 'var(--container-ak-xl)',
423
- 'ak-2xl': 'var(--container-ak-2xl)',
424
- 'ak-3xl': 'var(--container-ak-3xl)',
425
- 'ak-4xl': 'var(--container-ak-4xl)',
426
- 'ak-prose': 'var(--container-ak-prose)',
427
- },
428
-
429
- /* ── Z-Index ── */
430
- zIndex: {
431
- 'ak-sticky': 'var(--z-ak-sticky)',
432
- 'ak-dropdown': 'var(--z-ak-dropdown)',
433
- 'ak-overlay': 'var(--z-ak-overlay)',
434
- 'ak-modal': 'var(--z-ak-modal)',
435
- },
436
-
437
- /* ── Height ── (spacing + named heights) */
438
- height: {
439
- ...AK_SPACING,
440
- 'ak-nav': 'var(--height-ak-nav)',
441
- 'ak-touch': 'var(--height-ak-touch)',
442
- 'ak-control-sm': 'var(--height-ak-control-sm)',
443
- 'ak-control-md': 'var(--height-ak-control-md)',
444
- 'ak-control-lg': 'var(--height-ak-control-lg)',
445
- 'ak-control-xl': 'var(--height-ak-control-xl)',
446
- },
447
-
448
- /* ── Min Height ── */
449
- minHeight: {
450
- ...AK_SPACING,
451
- 'ak-nav': 'var(--height-ak-nav)',
452
- 'ak-touch': 'var(--height-ak-touch)',
453
- 'ak-control-sm': 'var(--height-ak-control-sm)',
454
- 'ak-control-md': 'var(--height-ak-control-md)',
455
- 'ak-control-lg': 'var(--height-ak-control-lg)',
456
- 'ak-control-xl': 'var(--height-ak-control-xl)',
457
- },
458
-
459
- /* ── Width ── */
460
- width: {
461
- ...AK_SPACING,
462
- 'ak-touch': 'var(--width-ak-touch)',
463
- 'ak-panel-width': 'var(--size-ak-panel-width)',
464
- },
465
-
466
- /* ── Min Width ── */
467
- minWidth: {
468
- ...AK_SPACING,
469
- 'ak-touch': 'var(--width-ak-touch)',
470
- 'ak-panel-width': 'var(--size-ak-panel-width)',
471
- },
472
-
473
- /* ── Transition Duration ── */
474
- transitionDuration: {
475
- 'ak-fast': 'var(--duration-ak-fast)',
476
- 'ak-base': 'var(--duration-ak-base)',
477
- 'ak-slow': 'var(--duration-ak-slow)',
478
- },
479
-
480
- /* ── Transition Timing Function ── */
481
- transitionTimingFunction: {
482
- 'ak-default': 'var(--ease-ak-default)',
483
- 'ak-in': 'var(--ease-ak-in)',
484
- 'ak-out': 'var(--ease-ak-out)',
485
- 'ak-spring': 'var(--ease-ak-spring)',
486
- 'ak-bounce': 'var(--ease-ak-bounce)',
487
- },
488
- },
489
- },
490
- }
491
- )