2026-07-16 00:36:53 -05:00
|
|
|
/**
|
|
|
|
|
* Shared Tailwind preset. Consuming apps do:
|
|
|
|
|
* // tailwind.config.js
|
|
|
|
|
* module.exports = {
|
|
|
|
|
* presets: [require("@jason/ui-kit/preset")],
|
|
|
|
|
* content: [
|
|
|
|
|
* "./src/**\/*.{ts,tsx}",
|
|
|
|
|
* "./node_modules/@jason/ui-kit/dist/**\/*.js" // so component classes aren't purged
|
|
|
|
|
* ],
|
|
|
|
|
* };
|
|
|
|
|
*
|
|
|
|
|
* Colors are driven by CSS variables (see styles/globals.css) so light/dark and
|
|
|
|
|
* per-app rebranding work without recompiling the preset.
|
|
|
|
|
*/
|
2026-07-23 04:23:19 -05:00
|
|
|
const tokens = require("./src/lib/tokens.json");
|
2026-07-16 00:36:53 -05:00
|
|
|
const v = (name) => `hsl(var(${name}) / <alpha-value>)`;
|
2026-07-23 04:23:19 -05:00
|
|
|
const family = (value) => value.split(",").map((part) => part.trim().replace(/^"|"$/g, ""));
|
2026-07-16 00:36:53 -05:00
|
|
|
|
|
|
|
|
/** @type {import('tailwindcss').Config} */
|
|
|
|
|
module.exports = {
|
|
|
|
|
darkMode: ["class"],
|
|
|
|
|
theme: {
|
|
|
|
|
extend: {
|
|
|
|
|
colors: {
|
|
|
|
|
bg: v("--bg"),
|
|
|
|
|
surface: v("--surface"),
|
|
|
|
|
"surface-2": v("--surface-2"),
|
|
|
|
|
border: v("--border"),
|
|
|
|
|
input: v("--border"),
|
|
|
|
|
ring: v("--brand"),
|
|
|
|
|
text: v("--text"),
|
|
|
|
|
muted: v("--muted"),
|
2026-07-23 04:23:19 -05:00
|
|
|
brand: {
|
|
|
|
|
DEFAULT: v("--brand"),
|
|
|
|
|
bright: v("--brand-bright"),
|
|
|
|
|
dark: v("--brand-dark"),
|
|
|
|
|
foreground: v("--brand-foreground"),
|
|
|
|
|
},
|
|
|
|
|
success: { DEFAULT: v("--success"), foreground: v("--success-foreground") },
|
|
|
|
|
warning: { DEFAULT: v("--warning"), foreground: v("--warning-foreground") },
|
|
|
|
|
danger: { DEFAULT: v("--danger"), foreground: v("--danger-foreground") },
|
|
|
|
|
info: { DEFAULT: v("--info"), foreground: v("--info-foreground") },
|
2026-07-16 00:36:53 -05:00
|
|
|
},
|
|
|
|
|
fontFamily: {
|
2026-07-23 04:23:19 -05:00
|
|
|
display: family(tokens.font.display),
|
|
|
|
|
sans: family(tokens.font.sans),
|
|
|
|
|
mono: family(tokens.font.mono),
|
|
|
|
|
},
|
|
|
|
|
borderRadius: {
|
|
|
|
|
sm: tokens.radius.sm,
|
|
|
|
|
DEFAULT: tokens.radius.md,
|
|
|
|
|
md: tokens.radius.md,
|
|
|
|
|
lg: tokens.radius.lg,
|
|
|
|
|
xl: tokens.radius.xl,
|
2026-07-16 00:36:53 -05:00
|
|
|
},
|
|
|
|
|
boxShadow: {
|
2026-07-23 04:23:19 -05:00
|
|
|
sm: tokens.shadow.sm,
|
|
|
|
|
DEFAULT: tokens.shadow.md,
|
|
|
|
|
md: tokens.shadow.md,
|
|
|
|
|
lg: tokens.shadow.lg,
|
|
|
|
|
glow: tokens.shadow.glow,
|
2026-07-16 00:36:53 -05:00
|
|
|
},
|
|
|
|
|
transitionTimingFunction: {
|
2026-07-23 04:23:19 -05:00
|
|
|
out: tokens.ease.out,
|
|
|
|
|
"in-out": tokens.ease.inOut,
|
|
|
|
|
},
|
|
|
|
|
transitionDuration: {
|
|
|
|
|
fast: tokens.duration.fast,
|
|
|
|
|
DEFAULT: tokens.duration.base,
|
|
|
|
|
base: tokens.duration.base,
|
|
|
|
|
slow: tokens.duration.slow,
|
2026-07-16 00:36:53 -05:00
|
|
|
},
|
|
|
|
|
keyframes: {
|
|
|
|
|
"fade-in": { from: { opacity: "0" }, to: { opacity: "1" } },
|
|
|
|
|
"fade-up": { from: { opacity: "0", transform: "translateY(8px)" }, to: { opacity: "1", transform: "translateY(0)" } },
|
|
|
|
|
"scale-in": { from: { opacity: "0", transform: "scale(0.97)" }, to: { opacity: "1", transform: "scale(1)" } },
|
|
|
|
|
shimmer: { from: { backgroundPosition: "200% 0" }, to: { backgroundPosition: "-200% 0" } },
|
|
|
|
|
},
|
|
|
|
|
animation: {
|
|
|
|
|
"fade-in": "fade-in 180ms cubic-bezier(0.22,1,0.36,1)",
|
|
|
|
|
"fade-up": "fade-up 320ms cubic-bezier(0.22,1,0.36,1)",
|
|
|
|
|
"scale-in": "scale-in 180ms cubic-bezier(0.22,1,0.36,1)",
|
|
|
|
|
shimmer: "shimmer 2.2s linear infinite",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
plugins: [],
|
|
|
|
|
};
|