You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
526 lines
11 KiB
526 lines
11 KiB
import {
|
|
defineEidosConfig,
|
|
extendEidosConfig,
|
|
type EidosConfigPatch
|
|
} from '../options'
|
|
import { STATIC_PRIMITIVES } from '../primitives/static'
|
|
import type {
|
|
ColorRoleMap,
|
|
ColorScales,
|
|
EidosConfig,
|
|
ShadowScale,
|
|
ThemeColorSet
|
|
} from '../config-types'
|
|
import { THEME_BASE_RECIPE_TOKENS } from '../recipes/base'
|
|
import { RADIX_EXTRA_LIGHT_SCALES, RADIX_EXTRA_DARK_SCALES } from './color-scales'
|
|
import {
|
|
BUILTIN_KEYFRAMES,
|
|
BUILTIN_SIGNATURES,
|
|
BUILTIN_CSS_PRESETS
|
|
} from '../motion/presets/css'
|
|
|
|
export const THEME_BASE_COLOR_ROLES: ColorRoleMap = {
|
|
primary: 'purple',
|
|
secondary: 'slate',
|
|
// Tertiary is a SATURATED accent — distinct from the near-gray secondary (slate)
|
|
// and the gray neutral. Indigo is purple's cool ~60° neighbor (Material 3's
|
|
// tertiary-hue rule) and sits in a hue band no intent occupies, so it reads as
|
|
// hierarchy, not a signal. (Was `gray` — collided with neutral.)
|
|
// RESERVED (2026-06-15 audit): defined + emitted (`--color-tertiary-*`) but no
|
|
// component consumes it yet — a deliberate third-hierarchy slot apps/themes can
|
|
// reach for. Not dead code; not to be removed.
|
|
tertiary: 'indigo',
|
|
// `gray-9` (el sólido neutral) es un gris medio: ni blanco ni negro
|
|
// contrastan por defecto. El slot `contrast` se fija al step 12 — casi-negro
|
|
// en light, casi-blanco en dark — para que el texto sobre el sólido neutral
|
|
// supere AA en ambos modos (5.0:1 light / 4.6:1 dark). Ver THEMING_AUDIT P0-2.
|
|
neutral: { scale: 'gray', slots: { contrast: '12' } },
|
|
affirm: 'teal',
|
|
fulfill: 'green',
|
|
risk: 'orange',
|
|
threat: 'red',
|
|
// `plum` (canonical loss) — distinct from primary=purple. (Was `purple`, which
|
|
// collided with primary. plum is a graver, more magenta violet.)
|
|
loss: 'plum'
|
|
}
|
|
|
|
export const THEME_BASE_LIGHT_COLOR_SCALES: ColorScales = {
|
|
gray: {
|
|
1: '#fcfcfc',
|
|
2: '#f9f9f9',
|
|
3: '#f0f0f0',
|
|
4: '#e8e8e8',
|
|
5: '#e0e0e0',
|
|
6: '#d9d9d9',
|
|
7: '#cecece',
|
|
8: '#bbbbbb',
|
|
9: '#8d8d8d',
|
|
10: '#838383',
|
|
11: '#646464',
|
|
12: '#202020'
|
|
},
|
|
slate: {
|
|
1: '#fcfcfd',
|
|
2: '#f9f9fb',
|
|
3: '#f0f0f3',
|
|
4: '#e8e8ec',
|
|
5: '#e0e1e6',
|
|
6: '#d9d9e0',
|
|
7: '#cdced6',
|
|
8: '#b9bbc6',
|
|
9: '#8b8d98',
|
|
10: '#80838d',
|
|
11: '#60646c',
|
|
12: '#1c2024'
|
|
},
|
|
blue: {
|
|
1: '#fbfdff',
|
|
2: '#f4faff',
|
|
3: '#e6f4fe',
|
|
4: '#d5efff',
|
|
5: '#c2e5ff',
|
|
6: '#acd8fc',
|
|
7: '#8ec8f6',
|
|
8: '#5eb1ef',
|
|
9: '#0090ff',
|
|
10: '#0588f0',
|
|
11: '#0d74ce',
|
|
12: '#113264'
|
|
},
|
|
cyan: {
|
|
1: '#fafdfe',
|
|
2: '#f2fafb',
|
|
3: '#def7f9',
|
|
4: '#caf1f6',
|
|
5: '#b5e9f0',
|
|
6: '#9ddde7',
|
|
7: '#7dcedc',
|
|
8: '#3db9cf',
|
|
9: '#00a2c7',
|
|
10: '#0797b9',
|
|
11: '#107d98',
|
|
12: '#0d3c48'
|
|
},
|
|
teal: {
|
|
1: '#fafefd',
|
|
2: '#f3fbf9',
|
|
3: '#e0f8f3',
|
|
4: '#ccf3ea',
|
|
5: '#b8eae0',
|
|
6: '#a1ded2',
|
|
7: '#83cdc1',
|
|
8: '#53b9ab',
|
|
9: '#12a594',
|
|
10: '#0d9b8a',
|
|
11: '#008573',
|
|
12: '#0d3d38'
|
|
},
|
|
green: {
|
|
1: '#fbfefc',
|
|
2: '#f4fbf6',
|
|
3: '#e6f6eb',
|
|
4: '#d6f1df',
|
|
5: '#c4e8d1',
|
|
6: '#adddc0',
|
|
7: '#8eceaa',
|
|
8: '#5bb98b',
|
|
9: '#30a46c',
|
|
10: '#2b9a66',
|
|
11: '#218358',
|
|
12: '#193b2d'
|
|
},
|
|
yellow: {
|
|
1: '#fdfdf9',
|
|
2: '#fffce8',
|
|
3: '#fffbd1',
|
|
4: '#fff8bb',
|
|
5: '#fef2a4',
|
|
6: '#f9e68c',
|
|
7: '#efd36c',
|
|
8: '#ebbc00',
|
|
9: '#f5d90a',
|
|
10: '#f7ce00',
|
|
11: '#946800',
|
|
12: '#35290f'
|
|
},
|
|
amber: {
|
|
1: '#fefdfb',
|
|
2: '#fefbe9',
|
|
3: '#fff7c2',
|
|
4: '#ffee9c',
|
|
5: '#fbe577',
|
|
6: '#f3d673',
|
|
7: '#e9c162',
|
|
8: '#e2a336',
|
|
9: '#ffc53d',
|
|
10: '#ffba18',
|
|
11: '#ab6400',
|
|
12: '#4f3422'
|
|
},
|
|
orange: {
|
|
1: '#fefcfb',
|
|
2: '#fff7ed',
|
|
3: '#ffefd6',
|
|
4: '#ffdfb5',
|
|
5: '#ffd19a',
|
|
6: '#ffc182',
|
|
7: '#f5ae73',
|
|
8: '#ec9455',
|
|
9: '#f76b15',
|
|
10: '#ef5f00',
|
|
11: '#cc4e00',
|
|
12: '#582d1d'
|
|
},
|
|
red: {
|
|
1: '#fffcfc',
|
|
2: '#fff7f7',
|
|
3: '#feebec',
|
|
4: '#ffdbdc',
|
|
5: '#ffcdce',
|
|
6: '#fdbdbe',
|
|
7: '#f4a9aa',
|
|
8: '#eb8e90',
|
|
9: '#e5484d',
|
|
10: '#dc3e42',
|
|
11: '#ce2c31',
|
|
12: '#641723'
|
|
},
|
|
pink: {
|
|
1: '#fffcfe',
|
|
2: '#fff7fc',
|
|
3: '#feeef8',
|
|
4: '#fce5f3',
|
|
5: '#f9d8ec',
|
|
6: '#f3c6e2',
|
|
7: '#ecadd4',
|
|
8: '#e38ec3',
|
|
9: '#d6409f',
|
|
10: '#d23197',
|
|
11: '#cd1d8d',
|
|
12: '#651249'
|
|
},
|
|
purple: {
|
|
1: '#fefcfe',
|
|
2: '#fbf7fe',
|
|
3: '#f7edfe',
|
|
4: '#f2e2fc',
|
|
5: '#ead5f9',
|
|
6: '#e0c4f4',
|
|
7: '#d1afec',
|
|
8: '#be93e4',
|
|
9: '#8e4ec6',
|
|
10: '#8347b9',
|
|
11: '#8145b5',
|
|
12: '#402060'
|
|
},
|
|
...RADIX_EXTRA_LIGHT_SCALES
|
|
}
|
|
|
|
export const THEME_BASE_DARK_COLOR_SCALES: ColorScales = {
|
|
gray: {
|
|
1: '#111111',
|
|
2: '#191919',
|
|
3: '#222222',
|
|
4: '#2a2a2a',
|
|
5: '#313131',
|
|
6: '#3a3a3a',
|
|
7: '#484848',
|
|
8: '#606060',
|
|
9: '#6e6e6e',
|
|
10: '#7b7b7b',
|
|
11: '#b4b4b4',
|
|
12: '#eeeeee'
|
|
},
|
|
slate: {
|
|
1: '#111113',
|
|
2: '#18191b',
|
|
3: '#212225',
|
|
4: '#272a2d',
|
|
5: '#2e3135',
|
|
6: '#363a3f',
|
|
7: '#43484e',
|
|
8: '#5a6169',
|
|
9: '#696e77',
|
|
10: '#777b84',
|
|
11: '#b0b4ba',
|
|
12: '#edeef0'
|
|
},
|
|
blue: {
|
|
1: '#0d1520',
|
|
2: '#111927',
|
|
3: '#0d2847',
|
|
4: '#003362',
|
|
5: '#004074',
|
|
6: '#104d87',
|
|
7: '#205d9e',
|
|
8: '#2870bd',
|
|
9: '#0090ff',
|
|
10: '#3b9eff',
|
|
11: '#70b8ff',
|
|
12: '#c2e6ff'
|
|
},
|
|
cyan: {
|
|
1: '#0b161a',
|
|
2: '#101b20',
|
|
3: '#082c36',
|
|
4: '#003848',
|
|
5: '#004558',
|
|
6: '#045468',
|
|
7: '#12677e',
|
|
8: '#11809c',
|
|
9: '#00a2c7',
|
|
10: '#23afd0',
|
|
11: '#4ccce6',
|
|
12: '#b6ecf7'
|
|
},
|
|
teal: {
|
|
1: '#0d1514',
|
|
2: '#111c1b',
|
|
3: '#0d2d2a',
|
|
4: '#023b37',
|
|
5: '#084843',
|
|
6: '#145750',
|
|
7: '#1c6961',
|
|
8: '#207e73',
|
|
9: '#12a594',
|
|
10: '#0eb39e',
|
|
11: '#0bd8b6',
|
|
12: '#adf0dd'
|
|
},
|
|
green: {
|
|
1: '#0e1512',
|
|
2: '#121b17',
|
|
3: '#132d21',
|
|
4: '#113b29',
|
|
5: '#174933',
|
|
6: '#20573e',
|
|
7: '#28684a',
|
|
8: '#2f7c57',
|
|
9: '#30a46c',
|
|
10: '#33b074',
|
|
11: '#3dd68c',
|
|
12: '#b1f1cb'
|
|
},
|
|
yellow: {
|
|
1: '#14120b',
|
|
2: '#1b180f',
|
|
3: '#2d2305',
|
|
4: '#362b00',
|
|
5: '#433500',
|
|
6: '#524202',
|
|
7: '#665417',
|
|
8: '#836a21',
|
|
9: '#ffe629',
|
|
10: '#ffff57',
|
|
11: '#f5e147',
|
|
12: '#f6eeb4'
|
|
},
|
|
amber: {
|
|
1: '#16120c',
|
|
2: '#1d180f',
|
|
3: '#302008',
|
|
4: '#3f2700',
|
|
5: '#4d3000',
|
|
6: '#5c3d05',
|
|
7: '#714f19',
|
|
8: '#8f6424',
|
|
9: '#ffc53d',
|
|
10: '#ffd60a',
|
|
11: '#ffca16',
|
|
12: '#ffe7b3'
|
|
},
|
|
orange: {
|
|
1: '#17120e',
|
|
2: '#1e160f',
|
|
3: '#331e0b',
|
|
4: '#462100',
|
|
5: '#562800',
|
|
6: '#66350c',
|
|
7: '#7e451d',
|
|
8: '#a35829',
|
|
9: '#f76b15',
|
|
10: '#ff801f',
|
|
11: '#ffa057',
|
|
12: '#ffe0c2'
|
|
},
|
|
red: {
|
|
1: '#191111',
|
|
2: '#201314',
|
|
3: '#3b1219',
|
|
4: '#500f1c',
|
|
5: '#611623',
|
|
6: '#72232d',
|
|
7: '#8c333a',
|
|
8: '#b54548',
|
|
9: '#e5484d',
|
|
10: '#ec5d5e',
|
|
11: '#ff9592',
|
|
12: '#ffd1d9'
|
|
},
|
|
pink: {
|
|
1: '#191117',
|
|
2: '#21121d',
|
|
3: '#37172f',
|
|
4: '#4b143d',
|
|
5: '#591c47',
|
|
6: '#692955',
|
|
7: '#833869',
|
|
8: '#a84885',
|
|
9: '#d6409f',
|
|
10: '#de51a8',
|
|
11: '#ff8dcc',
|
|
12: '#fdd1ea'
|
|
},
|
|
purple: {
|
|
1: '#18111b',
|
|
2: '#1e1523',
|
|
3: '#301c3b',
|
|
4: '#3d224e',
|
|
5: '#48295c',
|
|
6: '#54346b',
|
|
7: '#664282',
|
|
8: '#8457aa',
|
|
9: '#8e4ec6',
|
|
10: '#9a5cd0',
|
|
11: '#d19dff',
|
|
12: '#ecd9fa'
|
|
},
|
|
...RADIX_EXTRA_DARK_SCALES
|
|
}
|
|
|
|
export const THEME_BASE_LIGHT_COLOR_SEMANTICS: Pick<
|
|
ThemeColorSet,
|
|
'surface' | 'content' | 'border' | 'focus'
|
|
> = {
|
|
surface: {
|
|
default: 'var(--primitive-neutral-1)',
|
|
raised: 'var(--primitive-neutral-2)',
|
|
// overlay sits ABOVE muted (consistent ladder default<raised<muted<overlay,
|
|
// matching dark). Was neutral-3 == muted, so popovers/menus were
|
|
// indistinguishable from muted panels in light mode.
|
|
overlay: 'var(--primitive-neutral-4)',
|
|
muted: 'var(--primitive-neutral-3)',
|
|
backdrop: 'rgb(28 25 23 / 0.42)'
|
|
},
|
|
content: {
|
|
primary: 'var(--primitive-neutral-12)',
|
|
secondary: 'var(--primitive-neutral-11)',
|
|
muted: 'var(--primitive-neutral-10)',
|
|
disabled: 'var(--primitive-neutral-8)',
|
|
onSolid: '#ffffff',
|
|
onSolidContrast: '#1c1917'
|
|
},
|
|
border: {
|
|
subtle: 'var(--primitive-neutral-4)',
|
|
default: 'var(--primitive-neutral-6)',
|
|
strong: 'var(--primitive-neutral-8)'
|
|
},
|
|
focus: {
|
|
ring: 'color-mix(in srgb, var(--primitive-primary-8) 48%, transparent)',
|
|
ringError: 'color-mix(in srgb, var(--primitive-risk-8) 52%, transparent)'
|
|
}
|
|
}
|
|
|
|
export const THEME_BASE_DARK_COLOR_SEMANTICS: Pick<
|
|
ThemeColorSet,
|
|
'surface' | 'content' | 'border' | 'focus'
|
|
> = {
|
|
surface: {
|
|
default: 'var(--primitive-neutral-1)',
|
|
raised: 'var(--primitive-neutral-2)',
|
|
overlay: 'var(--primitive-neutral-4)',
|
|
muted: 'var(--primitive-neutral-3)',
|
|
backdrop: 'rgb(0 0 0 / 0.66)'
|
|
},
|
|
content: {
|
|
primary: 'var(--primitive-neutral-12)',
|
|
secondary: 'var(--primitive-neutral-11)',
|
|
muted: 'var(--primitive-neutral-10)',
|
|
disabled: 'var(--primitive-neutral-8)',
|
|
onSolid: '#ffffff',
|
|
onSolidContrast: '#1c1917'
|
|
},
|
|
border: {
|
|
subtle: 'var(--primitive-neutral-4)',
|
|
default: 'var(--primitive-neutral-6)',
|
|
strong: 'var(--primitive-neutral-8)'
|
|
},
|
|
focus: {
|
|
ring: 'color-mix(in srgb, var(--primitive-primary-8) 52%, transparent)',
|
|
ringError: 'color-mix(in srgb, var(--primitive-risk-8) 56%, transparent)'
|
|
}
|
|
}
|
|
|
|
export const THEME_BASE_LIGHT_SHADOW: ShadowScale = {
|
|
none: 'none',
|
|
subtle: 'var(--shadow-1)',
|
|
raised: 'var(--shadow-3)',
|
|
overlay: 'var(--shadow-5)',
|
|
'1': '0 1px 2px rgb(15 23 42 / 0.08)',
|
|
'2': '0 4px 12px rgb(15 23 42 / 0.10)',
|
|
'3': '0 8px 24px rgb(15 23 42 / 0.12)',
|
|
'4': '0 14px 36px rgb(15 23 42 / 0.15)',
|
|
'5': '0 18px 48px rgb(15 23 42 / 0.18)',
|
|
'6': '0 28px 72px rgb(15 23 42 / 0.22)',
|
|
// Inner-shadow tier (recessed wells). Same slate base as the drop shadows; soft + inset.
|
|
'inset-subtle': 'inset 0 1px 2px rgb(15 23 42 / 0.08)',
|
|
'inset-deep': 'inset 0 2px 4px rgb(15 23 42 / 0.12)'
|
|
}
|
|
|
|
export const THEME_BASE_DARK_SHADOW: ShadowScale = {
|
|
none: 'none',
|
|
subtle: 'var(--shadow-1)',
|
|
raised: 'var(--shadow-3)',
|
|
overlay: 'var(--shadow-5)',
|
|
'1': '0 1px 2px rgb(0 0 0 / 0.28)',
|
|
'2': '0 5px 16px rgb(0 0 0 / 0.34)',
|
|
'3': '0 10px 30px rgb(0 0 0 / 0.42)',
|
|
'4': '0 16px 44px rgb(0 0 0 / 0.48)',
|
|
'5': '0 22px 60px rgb(0 0 0 / 0.55)',
|
|
'6': '0 34px 88px rgb(0 0 0 / 0.62)',
|
|
// Inner-shadow tier (recessed wells). Dark wells read as a darker inset (not a
|
|
// light rim) — black base, deeper alpha, mode-correct unlike a contrast-mix.
|
|
'inset-subtle': 'inset 0 1px 2px rgb(0 0 0 / 0.30)',
|
|
'inset-deep': 'inset 0 2px 4px rgb(0 0 0 / 0.45)'
|
|
}
|
|
|
|
export const THEME_BASE_OPTIONS: EidosConfig = defineEidosConfig({
|
|
primitives: STATIC_PRIMITIVES,
|
|
semantics: {
|
|
color: {
|
|
roles: THEME_BASE_COLOR_ROLES
|
|
}
|
|
},
|
|
recipes: THEME_BASE_RECIPE_TOKENS,
|
|
motion: {
|
|
keyframes: BUILTIN_KEYFRAMES,
|
|
signatures: BUILTIN_SIGNATURES,
|
|
// CSS presets only — the EidosConfig is serializable (deep-cloned via
|
|
// `clonePlain`), and JS presets carry functions (`MotionRun`). The JS
|
|
// (`spring`) tier is registered DIRECTLY with the engine in `ActiveEidos`.
|
|
presets: BUILTIN_CSS_PRESETS
|
|
},
|
|
themes: {
|
|
'base-light': {
|
|
color: {
|
|
scales: THEME_BASE_LIGHT_COLOR_SCALES,
|
|
...THEME_BASE_LIGHT_COLOR_SEMANTICS
|
|
},
|
|
shadow: THEME_BASE_LIGHT_SHADOW
|
|
},
|
|
'base-dark': {
|
|
color: {
|
|
scales: THEME_BASE_DARK_COLOR_SCALES,
|
|
...THEME_BASE_DARK_COLOR_SEMANTICS
|
|
},
|
|
shadow: THEME_BASE_DARK_SHADOW
|
|
}
|
|
}
|
|
})
|
|
|
|
export function createThemeBaseEidosConfig(
|
|
patch?: EidosConfigPatch
|
|
): EidosConfig {
|
|
return extendEidosConfig(THEME_BASE_OPTIONS, patch)
|
|
}
|