84 lines
4.1 KiB
JavaScript
84 lines
4.1 KiB
JavaScript
// Astryx brand theme — extends the stock "neutral" theme with Doormile's
|
|
// brand colour so migrated surfaces match the existing DT token palette
|
|
// (see themes/dt/tokens.js). Runtime-injected (not `astryx theme build`)
|
|
// since this repo doesn't do SSR — see `astryx docs theme`.
|
|
import { defineTheme } from '@astryxdesign/core/theme';
|
|
import { neutralTheme } from '@astryxdesign/theme-neutral';
|
|
import { DT } from 'themes/dt/tokens';
|
|
|
|
// The brand is pure black. Astryx's `color.accent` generator derives a whole
|
|
// ramp from the accent's hue + lightness, and black has NO hue and zero
|
|
// lightness — feeding it `#000000` made the generator clamp it into a mid-tone
|
|
// and invent a hue, which rendered every primary button magenta (#A23760).
|
|
//
|
|
// So the accent tokens are pinned explicitly via `tokens` instead, which
|
|
// `defineTheme` documents as taking precedence over scale-generated values.
|
|
// Each entry is a [light, dark] pair. `--color-accent-muted` has to be listed
|
|
// too: the generated value inlines the accent hex inside a color-mix() rather
|
|
// than referencing var(--color-accent), so it does not follow automatically.
|
|
const BRAND_ON_LIGHT = DT.brand; // #000000
|
|
const BRAND_ON_DARK = '#FFFFFF';
|
|
|
|
// Shared fallback stack. Every role appends this after its own family, so a
|
|
// blocked/slow Google Fonts request degrades to the platform UI font rather
|
|
// than to Times New Roman.
|
|
const SYSTEM_SANS = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
|
|
|
|
export const doormileTheme = defineTheme({
|
|
name: 'doormile',
|
|
extends: neutralTheme,
|
|
color: { neutralStyle: 'cool' },
|
|
// ---------------------------------------------------------------------
|
|
// Typography. This is the ONLY place font families and the type scale are
|
|
// decided; it drives --font-family-body/-heading/-code and the whole
|
|
// --text-heading-*/--text-body-* scale, so every Astryx component in the
|
|
// app moves together.
|
|
//
|
|
// Before this existed the app had three disagreeing sources and no scale at
|
|
// all: this file set no typography, config.js said 'Public Sans' (MUI), and
|
|
// Dispatch.css hardcoded 'Inter' + 'JetBrains Mono' in ~25 declarations.
|
|
//
|
|
// The families themselves are loaded by the <link> in public/index.html —
|
|
// Astryx explicitly does not load fonts, it only names them. Change one
|
|
// without the other and you get a silent fallback.
|
|
//
|
|
// base 14, not 16: this is a dense operator console and 14px is what the
|
|
// existing tables already assume. ratio 1.2 keeps the heading steps tight
|
|
// so an h1 doesn't tower over a data-heavy page.
|
|
// ---------------------------------------------------------------------
|
|
typography: {
|
|
scale: { base: 14, ratio: 1.2 },
|
|
body: { family: 'Inter', fallbacks: SYSTEM_SANS },
|
|
heading: { family: 'Sora', fallbacks: SYSTEM_SANS, weight: 'semibold' },
|
|
code: { family: 'ui-monospace', fallbacks: 'SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace' }
|
|
},
|
|
tokens: {
|
|
// ---- Corner radius -------------------------------------------------
|
|
// Overridden at the token level so EVERY Astryx component moves at once
|
|
// (cards, dialogs, popovers, buttons, inputs, menus, chat surfaces).
|
|
// Setting it per-component would leave the ones nobody remembered to
|
|
// list still rounded.
|
|
//
|
|
// `--radius-full` is deliberately untouched: it drives avatars, status
|
|
// dots and pill chips, which are meant to be round.
|
|
'--radius-page': '5px',
|
|
'--radius-container': '5px',
|
|
'--radius-element': '5px',
|
|
'--radius-inner': '5px',
|
|
'--radius-chat': '5px',
|
|
'--color-accent': [BRAND_ON_LIGHT, BRAND_ON_DARK],
|
|
'--color-icon-accent': [BRAND_ON_LIGHT, BRAND_ON_DARK],
|
|
'--color-text-accent': [BRAND_ON_LIGHT, BRAND_ON_DARK],
|
|
// Text/icon colour that sits ON a filled accent surface — inverted.
|
|
'--color-on-accent': ['#FFFFFF', '#000000'],
|
|
'--color-accent-muted': [
|
|
`color-mix(in srgb, ${BRAND_ON_LIGHT} 12%, transparent)`,
|
|
`color-mix(in srgb, ${BRAND_ON_DARK} 20%, transparent)`
|
|
]
|
|
},
|
|
components: {
|
|
card: { base: { borderRadius: `${DT.radiusCard}px` } },
|
|
'text-input': { base: { borderRadius: `${DT.radiusInner}px` } }
|
|
}
|
|
});
|