@burtson-labs/ui 0.12.0 → 0.12.2

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/dist/mui/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { accentTokens, dark, duration, easing, fontMono, fontSans, light, radius, shadow } from "../tokens.js";
1
+ import { accentTokens, contrast, dark, duration, easing, fontMono, fontSans, light, radius, shadow } from "../tokens.js";
2
2
  import { createTheme } from "@mui/material/styles";
3
3
  //#region src/mui/index.ts
4
4
  /**
@@ -52,7 +52,7 @@ function burtsonThemeOptions(modeOrConfig = "dark") {
52
52
  },
53
53
  secondary: {
54
54
  main: p.brand,
55
- contrastText: p["primary-foreground"]
55
+ contrastText: contrast(p.brand, "#ffffff") >= 4.5 ? "#ffffff" : p.background
56
56
  },
57
57
  info: {
58
58
  main: p.info,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/mui/index.ts"],"sourcesContent":["/**\n * The Burtson palette for MUI apps, so a screen built with MUI and one built\n * with Burtson UI components look like the same product.\n *\n * import { ThemeProvider } from '@mui/material/styles';\n * import { createBurtsonTheme } from '@burtson-labs/ui/mui';\n * <ThemeProvider theme={createBurtsonTheme('dark')}>…</ThemeProvider>\n * <ThemeProvider theme={createBurtsonTheme({ mode: 'dark', accent: '#2563eb', density: 'compact' })}>\n *\n * MUI is an adapter here: every colour, radius, shadow and timing comes from\n * the Burtson tokens, and the component overrides give MUI controls the same\n * shape and states as the Burtson components (focus ring, radius per role,\n * no uppercase buttons, quiet borders instead of heavy shadows).\n */\nimport { createTheme, type Shadows, type Theme, type ThemeOptions } from '@mui/material/styles';\n\nimport {\n accentTokens,\n dark,\n duration,\n easing,\n fontMono,\n fontSans,\n light,\n type Palette,\n radius,\n shadow,\n} from '../tokens';\n\nexport type BurtsonMode = 'light' | 'dark';\nexport type BurtsonDensity = 'comfortable' | 'compact';\n\nexport interface BurtsonThemeConfig {\n mode?: BurtsonMode;\n /** Any hex colour; primary, brand, soft and ring tones are derived with contrast kept. */\n accent?: string;\n /** `compact` for admin and data-dense screens: smaller controls, dense lists and tables. */\n density?: BurtsonDensity;\n /** Replace individual palette tokens (a product skin's tinted surfaces). */\n palette?: Partial<Palette>;\n}\n\nconst px = (rem: string) => Math.round(parseFloat(rem) * 16);\n\n/** The full token palette for a config: base mode, accent-derived brand tones, then explicit overrides. */\nexport function burtsonPalette(config: BurtsonThemeConfig = {}): Palette {\n const mode = config.mode ?? 'dark';\n const base = mode === 'dark' ? dark : light;\n return {\n ...base,\n ...(config.accent ? accentTokens(config.accent, mode) : {}),\n ...config.palette,\n };\n}\n\nfunction shadows(): Shadows {\n // MUI indexes elevation 0–24; the Burtson scale has three real levels.\n const levels = ['none', shadow.xs, shadow.xs, shadow.sm, shadow.sm, shadow.sm];\n return Array.from({ length: 25 }, (_, i) => levels[i] ?? shadow.md) as Shadows;\n}\n\n/** Theme options only, for apps that deep-merge their own overrides first. */\nexport function burtsonThemeOptions(\n modeOrConfig: BurtsonMode | BurtsonThemeConfig = 'dark',\n): ThemeOptions {\n const config = typeof modeOrConfig === 'string' ? { mode: modeOrConfig } : modeOrConfig;\n const mode = config.mode ?? 'dark';\n const compact = config.density === 'compact';\n const p = burtsonPalette(config);\n const focusRing = `0 0 0 3px color-mix(in srgb, ${p.ring} 24%, transparent)`;\n return {\n palette: {\n mode,\n primary: { main: p.primary, contrastText: p['primary-foreground'] },\n secondary: { main: p.brand, contrastText: p['primary-foreground'] },\n info: { main: p.info, contrastText: p['info-foreground'] },\n error: { main: p.destructive, contrastText: p['destructive-foreground'] },\n warning: { main: p.warning, contrastText: p['warning-foreground'] },\n success: { main: p.success, contrastText: p['success-foreground'] },\n background: { default: p.background, paper: p.surface },\n text: { primary: p.foreground, secondary: p['muted-foreground'] },\n divider: p.border,\n action: { hover: p.muted, selected: p['brand-soft'], focus: p['brand-soft'] },\n },\n shape: { borderRadius: px(radius.md) },\n shadows: shadows(),\n typography: {\n fontFamily: fontSans,\n fontSize: compact ? 13 : 14,\n button: { textTransform: 'none', fontWeight: 600, letterSpacing: '-0.01em' },\n h1: { fontWeight: 700, letterSpacing: '-0.03em' },\n h2: { fontWeight: 700, letterSpacing: '-0.025em' },\n h3: { fontWeight: 650, letterSpacing: '-0.02em' },\n h4: { fontWeight: 650, letterSpacing: '-0.015em' },\n h5: { fontWeight: 600 },\n h6: { fontWeight: 600 },\n overline: { fontWeight: 600, letterSpacing: '0.08em' },\n },\n transitions: {\n duration: {\n shortest: duration.fast,\n shorter: duration.fast,\n short: duration.standard,\n standard: duration.standard,\n complex: duration.emphasis,\n enteringScreen: duration.emphasis,\n leavingScreen: duration.exit,\n },\n easing: {\n easeInOut: easing.standard,\n easeOut: easing.emphasized,\n easeIn: easing.exit,\n sharp: easing.standard,\n },\n },\n components: {\n MuiCssBaseline: {\n styleOverrides: {\n 'code, kbd, pre, samp': { fontFamily: fontMono },\n '@media (prefers-reduced-motion: reduce)': {\n '*, ::before, ::after': {\n animationDuration: '1ms !important',\n transitionDuration: '1ms !important',\n },\n },\n },\n },\n MuiButtonBase: { defaultProps: { disableRipple: true } },\n MuiButton: {\n defaultProps: { disableElevation: true, size: compact ? 'small' : 'medium' },\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n '&:focus-visible': {\n boxShadow: focusRing,\n outline: `2px solid ${p.ring}`,\n outlineOffset: 2,\n },\n },\n outlined: { borderColor: p['border-strong'] },\n },\n },\n MuiIconButton: {\n defaultProps: { size: compact ? 'small' : 'medium' },\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n '&:focus-visible': { outline: `2px solid ${p.ring}`, outlineOffset: 2 },\n },\n },\n },\n MuiPaper: {\n styleOverrides: {\n root: { backgroundImage: 'none' },\n outlined: { borderColor: p.border },\n rounded: { borderRadius: radius.lg },\n },\n },\n MuiCard: {\n defaultProps: { variant: 'outlined' },\n styleOverrides: {\n root: { borderRadius: radius.lg, backgroundColor: p.card, borderColor: p.border },\n },\n },\n MuiDialog: {\n styleOverrides: {\n paper: { borderRadius: radius.xl, border: `1px solid ${p.border}`, boxShadow: shadow.md },\n },\n },\n MuiMenu: {\n styleOverrides: {\n paper: { borderRadius: radius.lg, border: `1px solid ${p.border}`, boxShadow: shadow.md },\n },\n },\n MuiPopover: {\n styleOverrides: { paper: { borderRadius: radius.lg, border: `1px solid ${p.border}` } },\n },\n MuiChip: {\n defaultProps: { size: 'small' },\n styleOverrides: { root: { borderRadius: radius.full, fontWeight: 500 } },\n },\n MuiTabs: {\n styleOverrides: { indicator: { backgroundColor: p.brand, height: 2 } },\n },\n MuiTab: {\n styleOverrides: {\n root: {\n textTransform: 'none',\n fontWeight: 500,\n minHeight: compact ? 36 : 44,\n '&.Mui-selected': { color: p.foreground },\n },\n },\n },\n MuiOutlinedInput: {\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n backgroundColor: p.surface,\n '& .MuiOutlinedInput-notchedOutline': { borderColor: p.input },\n '&:hover .MuiOutlinedInput-notchedOutline': { borderColor: p['border-strong'] },\n '&.Mui-focused .MuiOutlinedInput-notchedOutline': {\n borderColor: p.ring,\n borderWidth: 1,\n },\n '&.Mui-focused': { boxShadow: focusRing },\n },\n },\n },\n MuiTextField: { defaultProps: { size: compact ? 'small' : 'medium' } },\n MuiAlert: { styleOverrides: { root: { borderRadius: radius.md } } },\n MuiTooltip: {\n styleOverrides: {\n tooltip: {\n backgroundColor: p.code,\n color: p['code-foreground'],\n fontSize: 12,\n borderRadius: radius.sm,\n },\n },\n },\n MuiSwitch: {\n styleOverrides: {\n switchBase: {\n '&.Mui-checked + .MuiSwitch-track': { backgroundColor: p.brand, opacity: 1 },\n },\n track: { backgroundColor: p['border-strong'], opacity: 1 },\n },\n },\n MuiList: { defaultProps: { dense: compact } },\n MuiTable: { defaultProps: { size: compact ? 'small' : 'medium' } },\n MuiToolbar: { defaultProps: { variant: compact ? 'dense' : 'regular' } },\n MuiDivider: { styleOverrides: { root: { borderColor: p.border } } },\n },\n };\n}\n\n/**\n * `createBurtsonTheme('dark')` or `createBurtsonTheme({ mode, accent, density })`,\n * then any MUI overrides, merged in order.\n */\nexport function createBurtsonTheme(\n modeOrConfig: BurtsonMode | BurtsonThemeConfig = 'dark',\n ...overrides: ThemeOptions[]\n): Theme {\n return createTheme(burtsonThemeOptions(modeOrConfig), ...overrides);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/mui/index.ts"],"sourcesContent":["/**\n * The Burtson palette for MUI apps, so a screen built with MUI and one built\n * with Burtson UI components look like the same product.\n *\n * import { ThemeProvider } from '@mui/material/styles';\n * import { createBurtsonTheme } from '@burtson-labs/ui/mui';\n * <ThemeProvider theme={createBurtsonTheme('dark')}>…</ThemeProvider>\n * <ThemeProvider theme={createBurtsonTheme({ mode: 'dark', accent: '#2563eb', density: 'compact' })}>\n *\n * MUI is an adapter here: every colour, radius, shadow and timing comes from\n * the Burtson tokens, and the component overrides give MUI controls the same\n * shape and states as the Burtson components (focus ring, radius per role,\n * no uppercase buttons, quiet borders instead of heavy shadows).\n */\nimport { createTheme, type Shadows, type Theme, type ThemeOptions } from '@mui/material/styles';\n\nimport {\n accentTokens,\n contrast,\n dark,\n duration,\n easing,\n fontMono,\n fontSans,\n light,\n type Palette,\n radius,\n shadow,\n} from '../tokens';\n\nexport type BurtsonMode = 'light' | 'dark';\nexport type BurtsonDensity = 'comfortable' | 'compact';\n\nexport interface BurtsonThemeConfig {\n mode?: BurtsonMode;\n /** Any hex colour; primary, brand, soft and ring tones are derived with contrast kept. */\n accent?: string;\n /** `compact` for admin and data-dense screens: smaller controls, dense lists and tables. */\n density?: BurtsonDensity;\n /** Replace individual palette tokens (a product skin's tinted surfaces). */\n palette?: Partial<Palette>;\n}\n\nconst px = (rem: string) => Math.round(parseFloat(rem) * 16);\n\n/** The full token palette for a config: base mode, accent-derived brand tones, then explicit overrides. */\nexport function burtsonPalette(config: BurtsonThemeConfig = {}): Palette {\n const mode = config.mode ?? 'dark';\n const base = mode === 'dark' ? dark : light;\n return {\n ...base,\n ...(config.accent ? accentTokens(config.accent, mode) : {}),\n ...config.palette,\n };\n}\n\nfunction shadows(): Shadows {\n // MUI indexes elevation 0–24; the Burtson scale has three real levels.\n const levels = ['none', shadow.xs, shadow.xs, shadow.sm, shadow.sm, shadow.sm];\n return Array.from({ length: 25 }, (_, i) => levels[i] ?? shadow.md) as Shadows;\n}\n\n/** Theme options only, for apps that deep-merge their own overrides first. */\nexport function burtsonThemeOptions(\n modeOrConfig: BurtsonMode | BurtsonThemeConfig = 'dark',\n): ThemeOptions {\n const config = typeof modeOrConfig === 'string' ? { mode: modeOrConfig } : modeOrConfig;\n const mode = config.mode ?? 'dark';\n const compact = config.density === 'compact';\n const p = burtsonPalette(config);\n const focusRing = `0 0 0 3px color-mix(in srgb, ${p.ring} 24%, transparent)`;\n return {\n palette: {\n mode,\n primary: { main: p.primary, contrastText: p['primary-foreground'] },\n // Secondary fills use the brand text tone, which is light in dark mode;\n // their text is whichever of white or the page background reads.\n secondary: {\n main: p.brand,\n contrastText: contrast(p.brand, '#ffffff') >= 4.5 ? '#ffffff' : p.background,\n },\n info: { main: p.info, contrastText: p['info-foreground'] },\n error: { main: p.destructive, contrastText: p['destructive-foreground'] },\n warning: { main: p.warning, contrastText: p['warning-foreground'] },\n success: { main: p.success, contrastText: p['success-foreground'] },\n background: { default: p.background, paper: p.surface },\n text: { primary: p.foreground, secondary: p['muted-foreground'] },\n divider: p.border,\n action: { hover: p.muted, selected: p['brand-soft'], focus: p['brand-soft'] },\n },\n shape: { borderRadius: px(radius.md) },\n shadows: shadows(),\n typography: {\n fontFamily: fontSans,\n fontSize: compact ? 13 : 14,\n button: { textTransform: 'none', fontWeight: 600, letterSpacing: '-0.01em' },\n h1: { fontWeight: 700, letterSpacing: '-0.03em' },\n h2: { fontWeight: 700, letterSpacing: '-0.025em' },\n h3: { fontWeight: 650, letterSpacing: '-0.02em' },\n h4: { fontWeight: 650, letterSpacing: '-0.015em' },\n h5: { fontWeight: 600 },\n h6: { fontWeight: 600 },\n overline: { fontWeight: 600, letterSpacing: '0.08em' },\n },\n transitions: {\n duration: {\n shortest: duration.fast,\n shorter: duration.fast,\n short: duration.standard,\n standard: duration.standard,\n complex: duration.emphasis,\n enteringScreen: duration.emphasis,\n leavingScreen: duration.exit,\n },\n easing: {\n easeInOut: easing.standard,\n easeOut: easing.emphasized,\n easeIn: easing.exit,\n sharp: easing.standard,\n },\n },\n components: {\n MuiCssBaseline: {\n styleOverrides: {\n 'code, kbd, pre, samp': { fontFamily: fontMono },\n '@media (prefers-reduced-motion: reduce)': {\n '*, ::before, ::after': {\n animationDuration: '1ms !important',\n transitionDuration: '1ms !important',\n },\n },\n },\n },\n MuiButtonBase: { defaultProps: { disableRipple: true } },\n MuiButton: {\n defaultProps: { disableElevation: true, size: compact ? 'small' : 'medium' },\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n '&:focus-visible': {\n boxShadow: focusRing,\n outline: `2px solid ${p.ring}`,\n outlineOffset: 2,\n },\n },\n outlined: { borderColor: p['border-strong'] },\n },\n },\n MuiIconButton: {\n defaultProps: { size: compact ? 'small' : 'medium' },\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n '&:focus-visible': { outline: `2px solid ${p.ring}`, outlineOffset: 2 },\n },\n },\n },\n MuiPaper: {\n styleOverrides: {\n root: { backgroundImage: 'none' },\n outlined: { borderColor: p.border },\n rounded: { borderRadius: radius.lg },\n },\n },\n MuiCard: {\n defaultProps: { variant: 'outlined' },\n styleOverrides: {\n root: { borderRadius: radius.lg, backgroundColor: p.card, borderColor: p.border },\n },\n },\n MuiDialog: {\n styleOverrides: {\n paper: { borderRadius: radius.xl, border: `1px solid ${p.border}`, boxShadow: shadow.md },\n },\n },\n MuiMenu: {\n styleOverrides: {\n paper: { borderRadius: radius.lg, border: `1px solid ${p.border}`, boxShadow: shadow.md },\n },\n },\n MuiPopover: {\n styleOverrides: { paper: { borderRadius: radius.lg, border: `1px solid ${p.border}` } },\n },\n MuiChip: {\n defaultProps: { size: 'small' },\n styleOverrides: { root: { borderRadius: radius.full, fontWeight: 500 } },\n },\n MuiTabs: {\n styleOverrides: { indicator: { backgroundColor: p.brand, height: 2 } },\n },\n MuiTab: {\n styleOverrides: {\n root: {\n textTransform: 'none',\n fontWeight: 500,\n minHeight: compact ? 36 : 44,\n '&.Mui-selected': { color: p.foreground },\n },\n },\n },\n MuiOutlinedInput: {\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n backgroundColor: p.surface,\n '& .MuiOutlinedInput-notchedOutline': { borderColor: p.input },\n '&:hover .MuiOutlinedInput-notchedOutline': { borderColor: p['border-strong'] },\n '&.Mui-focused .MuiOutlinedInput-notchedOutline': {\n borderColor: p.ring,\n borderWidth: 1,\n },\n '&.Mui-focused': { boxShadow: focusRing },\n },\n },\n },\n MuiTextField: { defaultProps: { size: compact ? 'small' : 'medium' } },\n MuiAlert: { styleOverrides: { root: { borderRadius: radius.md } } },\n MuiTooltip: {\n styleOverrides: {\n tooltip: {\n backgroundColor: p.code,\n color: p['code-foreground'],\n fontSize: 12,\n borderRadius: radius.sm,\n },\n },\n },\n MuiSwitch: {\n styleOverrides: {\n switchBase: {\n '&.Mui-checked + .MuiSwitch-track': { backgroundColor: p.brand, opacity: 1 },\n },\n track: { backgroundColor: p['border-strong'], opacity: 1 },\n },\n },\n MuiList: { defaultProps: { dense: compact } },\n MuiTable: { defaultProps: { size: compact ? 'small' : 'medium' } },\n MuiToolbar: { defaultProps: { variant: compact ? 'dense' : 'regular' } },\n MuiDivider: { styleOverrides: { root: { borderColor: p.border } } },\n },\n };\n}\n\n/**\n * `createBurtsonTheme('dark')` or `createBurtsonTheme({ mode, accent, density })`,\n * then any MUI overrides, merged in order.\n */\nexport function createBurtsonTheme(\n modeOrConfig: BurtsonMode | BurtsonThemeConfig = 'dark',\n ...overrides: ThemeOptions[]\n): Theme {\n return createTheme(burtsonThemeOptions(modeOrConfig), ...overrides);\n}\n"],"mappings":"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"}
package/dist/tokens.js CHANGED
@@ -217,7 +217,7 @@ function ensureContrast(color, against, ratio, target) {
217
217
  function accentTokens(accent, mode) {
218
218
  const p = mode === "dark" ? dark : light;
219
219
  const white = "#ffffff";
220
- const onFill = contrast(accent, white) >= contrast(accent, "#111111") ? white : "#111111";
220
+ const onFill = contrast(accent, white) >= 2.6 ? white : "#111111";
221
221
  const primary = onFill === white ? ensureContrast(accent, white, 4.5, "#000000") : ensureContrast(accent, "#111111", 4.5, white);
222
222
  const brand = mode === "dark" ? ensureContrast(mix(accent, white, .12), p.background, 4.5, white) : ensureContrast(accent, p.background, 4.5, "#000000");
223
223
  const brandHover = mode === "dark" ? mix(brand, white, .18) : mix(brand, "#000000", .14);
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","names":[],"sources":["../src/tokens.ts"],"sourcesContent":["/**\n * Burtson UI design tokens. This file is the single source for colour, radius,\n * shadow and type: `scripts/theme.mjs` writes src/styles/theme.css from it, and the\n * MUI adapter (`@burtson-labs/ui/mui`) builds its palette from it, so Tailwind\n * apps and MUI apps render the same brand.\n *\n * Burtson's design language: technical, quiet, precise. Purple (`brand`) is a\n * signal colour for selection, focus, primary actions and small accents, not a\n * panel fill. Dark is a first-class palette, not an inversion of light. The\n * base colour names stay registry-compatible, so source copied into an app\n * keeps working.\n */\n\nexport type ColorToken =\n | 'background'\n | 'foreground'\n | 'surface'\n | 'surface-raised'\n | 'surface-muted'\n | 'card'\n | 'card-foreground'\n | 'popover'\n | 'popover-foreground'\n | 'primary'\n | 'primary-foreground'\n | 'secondary'\n | 'secondary-foreground'\n | 'muted'\n | 'muted-foreground'\n | 'accent'\n | 'accent-foreground'\n | 'destructive'\n | 'destructive-foreground'\n | 'success'\n | 'success-foreground'\n | 'warning'\n | 'warning-foreground'\n | 'info'\n | 'info-foreground'\n | 'recording'\n | 'recording-foreground'\n | 'border'\n | 'border-strong'\n | 'input'\n | 'ring'\n | 'brand'\n | 'brand-hover'\n | 'brand-soft'\n | 'brand-soft-foreground'\n | 'code'\n | 'code-foreground';\n\nexport type Palette = Record<ColorToken, string>;\n\n/** Burtson Labs purple. Use as signal, not wallpaper. */\nexport const brand = '#a60ee5';\n\nexport const light: Palette = {\n background: '#fbfafc',\n foreground: '#17131c',\n surface: '#ffffff',\n 'surface-raised': '#ffffff',\n 'surface-muted': '#f7f4f9',\n card: '#ffffff',\n 'card-foreground': '#17131c',\n popover: '#ffffff',\n 'popover-foreground': '#17131c',\n primary: '#8f0bc7',\n 'primary-foreground': '#ffffff',\n secondary: '#f1edf4',\n 'secondary-foreground': '#29212f',\n muted: '#f4f1f6',\n 'muted-foreground': '#6c6472',\n accent: '#f3e7fb',\n 'accent-foreground': '#561071',\n destructive: '#c92d3f',\n 'destructive-foreground': '#ffffff',\n success: '#0e7a56',\n 'success-foreground': '#ffffff',\n warning: '#9b5c08',\n 'warning-foreground': '#ffffff',\n info: '#2563eb',\n 'info-foreground': '#ffffff',\n // Live microphone capture. Red by convention, but its own token: recording\n // is a state, not an error, and apps can retint it without touching errors.\n recording: '#d6293e',\n 'recording-foreground': '#ffffff',\n border: '#e5dfe8',\n 'border-strong': '#cfc5d5',\n input: '#d8cfdd',\n ring: '#a60ee5',\n brand: '#a60ee5',\n 'brand-hover': '#8f0bc7',\n 'brand-soft': '#f5e8fc',\n 'brand-soft-foreground': '#5b1476',\n code: '#18141d',\n 'code-foreground': '#f5f0f7',\n};\n\nexport const dark: Palette = {\n background: '#0d0d12',\n foreground: '#f2eef5',\n surface: '#121218',\n 'surface-raised': '#18171f',\n 'surface-muted': '#17151c',\n card: '#14131a',\n 'card-foreground': '#f2eef5',\n popover: '#18171f',\n 'popover-foreground': '#f2eef5',\n primary: '#8f0bc7',\n 'primary-foreground': '#ffffff',\n secondary: '#211e28',\n 'secondary-foreground': '#e7e0eb',\n muted: '#1b1921',\n 'muted-foreground': '#a49ca9',\n accent: '#291734',\n 'accent-foreground': '#efd7fa',\n destructive: '#ef5b65',\n 'destructive-foreground': '#1b090b',\n success: '#36c58d',\n 'success-foreground': '#07160f',\n warning: '#f3b24c',\n 'warning-foreground': '#201304',\n info: '#6ea8ff',\n 'info-foreground': '#071226',\n recording: '#f2616d',\n 'recording-foreground': '#1b090b',\n border: '#2a2732',\n 'border-strong': '#403a49',\n input: '#34303d',\n ring: '#c65ef1',\n brand: '#c65ef1',\n 'brand-hover': '#d384f3',\n 'brand-soft': '#291734',\n 'brand-soft-foreground': '#efd7fa',\n code: '#09090d',\n 'code-foreground': '#f5f0f7',\n};\n\nexport const radius = {\n xs: '0.375rem',\n sm: '0.5rem',\n md: '0.625rem',\n lg: '0.75rem',\n xl: '1rem',\n full: '9999px',\n} as const;\n\nexport const shadow = {\n xs: '0 1px 2px rgb(10 8 14 / 0.05)',\n sm: '0 1px 3px rgb(10 8 14 / 0.08), 0 1px 2px rgb(10 8 14 / 0.05)',\n md: '0 10px 30px rgb(10 8 14 / 0.10), 0 2px 8px rgb(10 8 14 / 0.06)',\n focus: '0 0 0 3px color-mix(in srgb, var(--ring) 22%, transparent)',\n} as const;\n\nexport const fontSans =\n 'Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif';\nexport const fontMono =\n '\"JetBrains Mono\", \"SFMono-Regular\", Consolas, \"Liberation Mono\", monospace';\n\n/**\n * Motion. Surfaces enter from where they come from: popovers and menus slide a\n * few pixels from their trigger side (--bl-tx/--bl-ty, set per side by the\n * component), dialogs zoom slightly, sheets glide in with a drawer ease, and\n * everything leaves faster than it arrived. prefers-reduced-motion turns all\n * of it off (theme.css).\n */\nexport const motion = {\n animations: {\n in: 'bl-in 200ms cubic-bezier(0.16, 1, 0.3, 1)',\n out: 'bl-out 140ms cubic-bezier(0.4, 0, 1, 1) forwards',\n 'fade-in': 'bl-fade-in 200ms ease-out',\n 'fade-out': 'bl-fade-out 150ms ease-in forwards',\n 'sheet-in': 'bl-sheet-in 340ms cubic-bezier(0.32, 0.72, 0, 1)',\n 'sheet-out': 'bl-sheet-out 220ms cubic-bezier(0.4, 0, 1, 1) forwards',\n 'accordion-down': 'bl-accordion-down 200ms cubic-bezier(0.16, 1, 0.3, 1)',\n 'accordion-up': 'bl-accordion-up 160ms ease-out',\n 'collapsible-down': 'bl-collapsible-down 200ms cubic-bezier(0.16, 1, 0.3, 1)',\n 'collapsible-up': 'bl-collapsible-up 160ms ease-out',\n },\n keyframes: {\n 'bl-in': {\n from: {\n opacity: '0',\n transform: 'translate3d(var(--bl-tx, 0), var(--bl-ty, 0), 0) scale(var(--bl-scale, 0.96))',\n },\n },\n 'bl-out': {\n to: {\n opacity: '0',\n transform: 'translate3d(var(--bl-tx, 0), var(--bl-ty, 0), 0) scale(var(--bl-scale, 0.96))',\n },\n },\n 'bl-fade-in': { from: { opacity: '0' } },\n 'bl-fade-out': { to: { opacity: '0' } },\n 'bl-sheet-in': {\n from: { transform: 'translate3d(var(--bl-sheet-x, 100%), var(--bl-sheet-y, 0), 0)' },\n },\n 'bl-sheet-out': {\n to: { transform: 'translate3d(var(--bl-sheet-x, 100%), var(--bl-sheet-y, 0), 0)' },\n },\n 'bl-accordion-down': {\n from: { height: '0' },\n to: { height: 'var(--radix-accordion-content-height)' },\n },\n 'bl-accordion-up': {\n from: { height: 'var(--radix-accordion-content-height)' },\n to: { height: '0' },\n },\n 'bl-collapsible-down': {\n from: { height: '0' },\n to: { height: 'var(--radix-collapsible-content-height)' },\n },\n 'bl-collapsible-up': {\n from: { height: 'var(--radix-collapsible-content-height)' },\n to: { height: '0' },\n },\n },\n} as const;\n\n/**\n * Motion timing for code that animates outside CSS (MUI transitions, JS\n * animation). Things leave faster than they arrive; `emphasis` is for\n * surfaces that change the layout (drawers, dialogs, expanding panels).\n */\nexport const duration = { fast: 120, standard: 180, emphasis: 240, exit: 140 } as const;\nexport const easing = {\n standard: 'cubic-bezier(0.2, 0, 0, 1)',\n emphasized: 'cubic-bezier(0.16, 1, 0.3, 1)',\n exit: 'cubic-bezier(0.4, 0, 1, 1)',\n} as const;\n\n/** Named elevation levels over the shadow scale: 0 flat, 1 resting control, 2 card, 3 floating. */\nexport const elevation = { 0: 'none', 1: shadow.xs, 2: shadow.sm, 3: shadow.md } as const;\n\n// ─── Accent ────────────────────────────────────────────────────────────────\n\nexport type AccentTokens = Pick<\n Palette,\n | 'primary'\n | 'primary-foreground'\n | 'brand'\n | 'brand-hover'\n | 'brand-soft'\n | 'brand-soft-foreground'\n | 'accent'\n | 'accent-foreground'\n | 'ring'\n>;\n\ntype Rgb = [number, number, number];\n\nfunction parseHex(hex: string): Rgb {\n const h = hex.replace('#', '').trim();\n const full = h.length === 3 ? [...h].map((c) => c + c).join('') : h.slice(0, 6);\n if (!/^[0-9a-f]{6}$/i.test(full)) throw new Error(`Not a hex colour: ${hex}`);\n return [0, 2, 4].map((i) => parseInt(full.slice(i, i + 2), 16)) as Rgb;\n}\n\nconst toHex = (rgb: Rgb) =>\n '#' +\n rgb\n .map((v) =>\n Math.round(Math.max(0, Math.min(255, v)))\n .toString(16)\n .padStart(2, '0'),\n )\n .join('');\n\n/** Mix `a` toward `b` by `t` (0 = a, 1 = b), in sRGB. */\nexport function mix(a: string, b: string, t: number): string {\n const x = parseHex(a);\n const y = parseHex(b);\n return toHex([0, 1, 2].map((i) => x[i]! + (y[i]! - x[i]!) * t) as Rgb);\n}\n\nfunction luminance(hex: string): number {\n const c = parseHex(hex).map((v) => {\n const s = v / 255;\n return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * c[0]! + 0.7152 * c[1]! + 0.0722 * c[2]!;\n}\n\n/** WCAG contrast ratio between two hex colours. */\nexport function contrast(a: string, b: string): number {\n const [hi, lo] = [luminance(a), luminance(b)].sort((m, n) => n - m) as [number, number];\n return (hi + 0.05) / (lo + 0.05);\n}\n\n/** Step `color` toward `target` until it reaches `ratio` against `against`. */\nfunction ensureContrast(color: string, against: string, ratio: number, target: string): string {\n let c = color;\n for (let i = 0; i < 20 && contrast(c, against) < ratio; i++) c = mix(c, target, 0.1);\n return c;\n}\n\n/**\n * Brand tokens for any accent colour, kept legible: the primary fill always\n * carries its foreground at 4.5:1, and the brand colour used for links, focus\n * and selected text reads at 4.5:1 on the page background. Tenants and skins\n * choose an accent; they never choose the contrast.\n */\nexport function accentTokens(accent: string, mode: 'light' | 'dark'): AccentTokens {\n const p = mode === 'dark' ? dark : light;\n const white = '#ffffff';\n // A dark foreground on light fills (yellow, cyan) instead of forcing white.\n const onFill = contrast(accent, white) >= contrast(accent, '#111111') ? white : '#111111';\n const primary =\n onFill === white\n ? ensureContrast(accent, white, 4.5, '#000000')\n : ensureContrast(accent, '#111111', 4.5, white);\n const brand =\n mode === 'dark'\n ? ensureContrast(mix(accent, white, 0.12), p.background, 4.5, white)\n : ensureContrast(accent, p.background, 4.5, '#000000');\n const brandHover = mode === 'dark' ? mix(brand, white, 0.18) : mix(brand, '#000000', 0.14);\n const soft = mode === 'dark' ? mix(p.background, accent, 0.16) : mix(white, accent, 0.1);\n const softFg = mode === 'dark' ? mix(accent, white, 0.72) : mix(accent, '#000000', 0.55);\n return {\n primary,\n 'primary-foreground': onFill,\n brand,\n 'brand-hover': brandHover,\n 'brand-soft': soft,\n 'brand-soft-foreground': ensureContrast(softFg, soft, 4.5, mode === 'dark' ? white : '#000000'),\n accent: soft,\n 'accent-foreground': ensureContrast(softFg, soft, 4.5, mode === 'dark' ? white : '#000000'),\n ring: brand,\n };\n}\n\nexport const tokens = {\n brand,\n light,\n dark,\n radius,\n shadow,\n elevation,\n motion,\n duration,\n easing,\n fontSans,\n fontMono,\n} as const;\nexport default tokens;\n"],"mappings":"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"}
1
+ {"version":3,"file":"tokens.js","names":[],"sources":["../src/tokens.ts"],"sourcesContent":["/**\n * Burtson UI design tokens. This file is the single source for colour, radius,\n * shadow and type: `scripts/theme.mjs` writes src/styles/theme.css from it, and the\n * MUI adapter (`@burtson-labs/ui/mui`) builds its palette from it, so Tailwind\n * apps and MUI apps render the same brand.\n *\n * Burtson's design language: technical, quiet, precise. Purple (`brand`) is a\n * signal colour for selection, focus, primary actions and small accents, not a\n * panel fill. Dark is a first-class palette, not an inversion of light. The\n * base colour names stay registry-compatible, so source copied into an app\n * keeps working.\n */\n\nexport type ColorToken =\n | 'background'\n | 'foreground'\n | 'surface'\n | 'surface-raised'\n | 'surface-muted'\n | 'card'\n | 'card-foreground'\n | 'popover'\n | 'popover-foreground'\n | 'primary'\n | 'primary-foreground'\n | 'secondary'\n | 'secondary-foreground'\n | 'muted'\n | 'muted-foreground'\n | 'accent'\n | 'accent-foreground'\n | 'destructive'\n | 'destructive-foreground'\n | 'success'\n | 'success-foreground'\n | 'warning'\n | 'warning-foreground'\n | 'info'\n | 'info-foreground'\n | 'recording'\n | 'recording-foreground'\n | 'border'\n | 'border-strong'\n | 'input'\n | 'ring'\n | 'brand'\n | 'brand-hover'\n | 'brand-soft'\n | 'brand-soft-foreground'\n | 'code'\n | 'code-foreground';\n\nexport type Palette = Record<ColorToken, string>;\n\n/** Burtson Labs purple. Use as signal, not wallpaper. */\nexport const brand = '#a60ee5';\n\nexport const light: Palette = {\n background: '#fbfafc',\n foreground: '#17131c',\n surface: '#ffffff',\n 'surface-raised': '#ffffff',\n 'surface-muted': '#f7f4f9',\n card: '#ffffff',\n 'card-foreground': '#17131c',\n popover: '#ffffff',\n 'popover-foreground': '#17131c',\n primary: '#8f0bc7',\n 'primary-foreground': '#ffffff',\n secondary: '#f1edf4',\n 'secondary-foreground': '#29212f',\n muted: '#f4f1f6',\n 'muted-foreground': '#6c6472',\n accent: '#f3e7fb',\n 'accent-foreground': '#561071',\n destructive: '#c92d3f',\n 'destructive-foreground': '#ffffff',\n success: '#0e7a56',\n 'success-foreground': '#ffffff',\n warning: '#9b5c08',\n 'warning-foreground': '#ffffff',\n info: '#2563eb',\n 'info-foreground': '#ffffff',\n // Live microphone capture. Red by convention, but its own token: recording\n // is a state, not an error, and apps can retint it without touching errors.\n recording: '#d6293e',\n 'recording-foreground': '#ffffff',\n border: '#e5dfe8',\n 'border-strong': '#cfc5d5',\n input: '#d8cfdd',\n ring: '#a60ee5',\n brand: '#a60ee5',\n 'brand-hover': '#8f0bc7',\n 'brand-soft': '#f5e8fc',\n 'brand-soft-foreground': '#5b1476',\n code: '#18141d',\n 'code-foreground': '#f5f0f7',\n};\n\nexport const dark: Palette = {\n background: '#0d0d12',\n foreground: '#f2eef5',\n surface: '#121218',\n 'surface-raised': '#18171f',\n 'surface-muted': '#17151c',\n card: '#14131a',\n 'card-foreground': '#f2eef5',\n popover: '#18171f',\n 'popover-foreground': '#f2eef5',\n primary: '#8f0bc7',\n 'primary-foreground': '#ffffff',\n secondary: '#211e28',\n 'secondary-foreground': '#e7e0eb',\n muted: '#1b1921',\n 'muted-foreground': '#a49ca9',\n accent: '#291734',\n 'accent-foreground': '#efd7fa',\n destructive: '#ef5b65',\n 'destructive-foreground': '#1b090b',\n success: '#36c58d',\n 'success-foreground': '#07160f',\n warning: '#f3b24c',\n 'warning-foreground': '#201304',\n info: '#6ea8ff',\n 'info-foreground': '#071226',\n recording: '#f2616d',\n 'recording-foreground': '#1b090b',\n border: '#2a2732',\n 'border-strong': '#403a49',\n input: '#34303d',\n ring: '#c65ef1',\n brand: '#c65ef1',\n 'brand-hover': '#d384f3',\n 'brand-soft': '#291734',\n 'brand-soft-foreground': '#efd7fa',\n code: '#09090d',\n 'code-foreground': '#f5f0f7',\n};\n\nexport const radius = {\n xs: '0.375rem',\n sm: '0.5rem',\n md: '0.625rem',\n lg: '0.75rem',\n xl: '1rem',\n full: '9999px',\n} as const;\n\nexport const shadow = {\n xs: '0 1px 2px rgb(10 8 14 / 0.05)',\n sm: '0 1px 3px rgb(10 8 14 / 0.08), 0 1px 2px rgb(10 8 14 / 0.05)',\n md: '0 10px 30px rgb(10 8 14 / 0.10), 0 2px 8px rgb(10 8 14 / 0.06)',\n focus: '0 0 0 3px color-mix(in srgb, var(--ring) 22%, transparent)',\n} as const;\n\nexport const fontSans =\n 'Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif';\nexport const fontMono =\n '\"JetBrains Mono\", \"SFMono-Regular\", Consolas, \"Liberation Mono\", monospace';\n\n/**\n * Motion. Surfaces enter from where they come from: popovers and menus slide a\n * few pixels from their trigger side (--bl-tx/--bl-ty, set per side by the\n * component), dialogs zoom slightly, sheets glide in with a drawer ease, and\n * everything leaves faster than it arrived. prefers-reduced-motion turns all\n * of it off (theme.css).\n */\nexport const motion = {\n animations: {\n in: 'bl-in 200ms cubic-bezier(0.16, 1, 0.3, 1)',\n out: 'bl-out 140ms cubic-bezier(0.4, 0, 1, 1) forwards',\n 'fade-in': 'bl-fade-in 200ms ease-out',\n 'fade-out': 'bl-fade-out 150ms ease-in forwards',\n 'sheet-in': 'bl-sheet-in 340ms cubic-bezier(0.32, 0.72, 0, 1)',\n 'sheet-out': 'bl-sheet-out 220ms cubic-bezier(0.4, 0, 1, 1) forwards',\n 'accordion-down': 'bl-accordion-down 200ms cubic-bezier(0.16, 1, 0.3, 1)',\n 'accordion-up': 'bl-accordion-up 160ms ease-out',\n 'collapsible-down': 'bl-collapsible-down 200ms cubic-bezier(0.16, 1, 0.3, 1)',\n 'collapsible-up': 'bl-collapsible-up 160ms ease-out',\n },\n keyframes: {\n 'bl-in': {\n from: {\n opacity: '0',\n transform: 'translate3d(var(--bl-tx, 0), var(--bl-ty, 0), 0) scale(var(--bl-scale, 0.96))',\n },\n },\n 'bl-out': {\n to: {\n opacity: '0',\n transform: 'translate3d(var(--bl-tx, 0), var(--bl-ty, 0), 0) scale(var(--bl-scale, 0.96))',\n },\n },\n 'bl-fade-in': { from: { opacity: '0' } },\n 'bl-fade-out': { to: { opacity: '0' } },\n 'bl-sheet-in': {\n from: { transform: 'translate3d(var(--bl-sheet-x, 100%), var(--bl-sheet-y, 0), 0)' },\n },\n 'bl-sheet-out': {\n to: { transform: 'translate3d(var(--bl-sheet-x, 100%), var(--bl-sheet-y, 0), 0)' },\n },\n 'bl-accordion-down': {\n from: { height: '0' },\n to: { height: 'var(--radix-accordion-content-height)' },\n },\n 'bl-accordion-up': {\n from: { height: 'var(--radix-accordion-content-height)' },\n to: { height: '0' },\n },\n 'bl-collapsible-down': {\n from: { height: '0' },\n to: { height: 'var(--radix-collapsible-content-height)' },\n },\n 'bl-collapsible-up': {\n from: { height: 'var(--radix-collapsible-content-height)' },\n to: { height: '0' },\n },\n },\n} as const;\n\n/**\n * Motion timing for code that animates outside CSS (MUI transitions, JS\n * animation). Things leave faster than they arrive; `emphasis` is for\n * surfaces that change the layout (drawers, dialogs, expanding panels).\n */\nexport const duration = { fast: 120, standard: 180, emphasis: 240, exit: 140 } as const;\nexport const easing = {\n standard: 'cubic-bezier(0.2, 0, 0, 1)',\n emphasized: 'cubic-bezier(0.16, 1, 0.3, 1)',\n exit: 'cubic-bezier(0.4, 0, 1, 1)',\n} as const;\n\n/** Named elevation levels over the shadow scale: 0 flat, 1 resting control, 2 card, 3 floating. */\nexport const elevation = { 0: 'none', 1: shadow.xs, 2: shadow.sm, 3: shadow.md } as const;\n\n// ─── Accent ────────────────────────────────────────────────────────────────\n\nexport type AccentTokens = Pick<\n Palette,\n | 'primary'\n | 'primary-foreground'\n | 'brand'\n | 'brand-hover'\n | 'brand-soft'\n | 'brand-soft-foreground'\n | 'accent'\n | 'accent-foreground'\n | 'ring'\n>;\n\ntype Rgb = [number, number, number];\n\nfunction parseHex(hex: string): Rgb {\n const h = hex.replace('#', '').trim();\n const full = h.length === 3 ? [...h].map((c) => c + c).join('') : h.slice(0, 6);\n if (!/^[0-9a-f]{6}$/i.test(full)) throw new Error(`Not a hex colour: ${hex}`);\n return [0, 2, 4].map((i) => parseInt(full.slice(i, i + 2), 16)) as Rgb;\n}\n\nconst toHex = (rgb: Rgb) =>\n '#' +\n rgb\n .map((v) =>\n Math.round(Math.max(0, Math.min(255, v)))\n .toString(16)\n .padStart(2, '0'),\n )\n .join('');\n\n/** Mix `a` toward `b` by `t` (0 = a, 1 = b), in sRGB. */\nexport function mix(a: string, b: string, t: number): string {\n const x = parseHex(a);\n const y = parseHex(b);\n return toHex([0, 1, 2].map((i) => x[i]! + (y[i]! - x[i]!) * t) as Rgb);\n}\n\nfunction luminance(hex: string): number {\n const c = parseHex(hex).map((v) => {\n const s = v / 255;\n return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * c[0]! + 0.7152 * c[1]! + 0.0722 * c[2]!;\n}\n\n/** WCAG contrast ratio between two hex colours. */\nexport function contrast(a: string, b: string): number {\n const [hi, lo] = [luminance(a), luminance(b)].sort((m, n) => n - m) as [number, number];\n return (hi + 0.05) / (lo + 0.05);\n}\n\n/** Step `color` toward `target` until it reaches `ratio` against `against`. */\nfunction ensureContrast(color: string, against: string, ratio: number, target: string): string {\n let c = color;\n for (let i = 0; i < 20 && contrast(c, against) < ratio; i++) c = mix(c, target, 0.1);\n return c;\n}\n\n/**\n * Brand tokens for any accent colour, kept legible: the primary fill always\n * carries its foreground at 4.5:1, and the brand colour used for links, focus\n * and selected text reads at 4.5:1 on the page background. Tenants and skins\n * choose an accent; they never choose the contrast.\n */\nexport function accentTokens(accent: string, mode: 'light' | 'dark'): AccentTokens {\n const p = mode === 'dark' ? dark : light;\n const white = '#ffffff';\n // A dark foreground on light fills (yellow, cyan) instead of forcing white.\n // White text on the fill whenever darkening the accent a little gets there\n // (purples, blues, greens, reds: the usual brand colours, which read as the\n // brand when they carry white). Dark text only for genuinely light accents\n // such as yellow or pale cyan, where white would need the colour ruined.\n const onFill = contrast(accent, white) >= 2.6 ? white : '#111111';\n const primary =\n onFill === white\n ? ensureContrast(accent, white, 4.5, '#000000')\n : ensureContrast(accent, '#111111', 4.5, white);\n const brand =\n mode === 'dark'\n ? ensureContrast(mix(accent, white, 0.12), p.background, 4.5, white)\n : ensureContrast(accent, p.background, 4.5, '#000000');\n const brandHover = mode === 'dark' ? mix(brand, white, 0.18) : mix(brand, '#000000', 0.14);\n const soft = mode === 'dark' ? mix(p.background, accent, 0.16) : mix(white, accent, 0.1);\n const softFg = mode === 'dark' ? mix(accent, white, 0.72) : mix(accent, '#000000', 0.55);\n return {\n primary,\n 'primary-foreground': onFill,\n brand,\n 'brand-hover': brandHover,\n 'brand-soft': soft,\n 'brand-soft-foreground': ensureContrast(softFg, soft, 4.5, mode === 'dark' ? white : '#000000'),\n accent: soft,\n 'accent-foreground': ensureContrast(softFg, soft, 4.5, mode === 'dark' ? white : '#000000'),\n ring: brand,\n };\n}\n\nexport const tokens = {\n brand,\n light,\n dark,\n radius,\n shadow,\n elevation,\n motion,\n duration,\n easing,\n fontSans,\n fontMono,\n} as const;\nexport default tokens;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burtson-labs/ui",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "description": "React components for Burtson Labs products: Radix accessibility, Tailwind v4 styling, Burtson Icons. Install the package or copy the source.",
5
5
  "license": "MIT",
6
6
  "author": {