Files
feuerwerk/src/ui/Theme.ts
T
rootandClaude Fable 5.1 5a46124454 Initial commit: Game Maker phase 1
Canvas-only 2D game editor/runtime built on PixiJS v8 + Vite + TypeScript.

- core: asset model (Scene/Camera/Sprite), scene objects with sparse
  overrides, property schema + resolve, command stack (undo/redo),
  serialization and project store interface (16 unit tests)
- ui: custom in-canvas widget toolkit (panels, fields, color picker,
  list/scroll, popup) with a hidden <input> keyboard bridge
- editor: asset/hierarchy panels, schema-driven inspector, toolbar
- viewport: box rendering, camera frame, selection gizmo, drag/zoom/pan
- runtime: world/entity instantiation for play mode, input, camera follow
- api: PHP JSON project store with revision counter (409 on conflict)
- tools: CDP-based e2e smoke test

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-07 10:07:06 +02:00

71 lines
2.1 KiB
TypeScript

import { TextStyle } from 'pixi.js';
/** Design tokens for the canvas UI. Widgets never hard-code colors or sizes. */
export const Theme = {
font: 'Inter, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
monoFont: '"JetBrains Mono", Consolas, "Courier New", monospace',
fontSize: 13,
smallFontSize: 11,
rowHeight: 26,
controlHeight: 24,
padding: 8,
gap: 6,
radius: 4,
colors: {
background: 0x1b1d22,
panel: 0x24272e,
panelHeader: 0x2c3038,
border: 0x383c46,
control: 0x16181d,
controlHover: 0x1e2127,
controlActive: 0x2a2e37,
accent: 0x4c8dff,
accentText: 0xffffff,
text: 0xe6e8ee,
textMuted: 0x8a90a0,
textDisabled: 0x5a5f6d,
selection: 0x2b4a80,
override: 0xf0b13d,
danger: 0xe0553f,
viewport: 0x121316,
grid: 0x1f2126,
gizmo: 0x4c8dff,
},
} as const;
const styleCache = new Map<string, TextStyle>();
export type TextStyleToken = 'body' | 'bodyBold' | 'muted' | 'small' | 'title' | 'mono' | 'accent';
/** Shared TextStyle instances so Pixi can cache glyph measurements per token. */
export function textStyle(token: TextStyleToken = 'body'): TextStyle {
let style = styleCache.get(token);
if (style) return style;
const base = { fontFamily: Theme.font, fontSize: Theme.fontSize, fill: Theme.colors.text };
switch (token) {
case 'body':
style = new TextStyle(base);
break;
case 'bodyBold':
style = new TextStyle({ ...base, fontWeight: '600' });
break;
case 'muted':
style = new TextStyle({ ...base, fill: Theme.colors.textMuted });
break;
case 'small':
style = new TextStyle({ ...base, fontSize: Theme.smallFontSize, fill: Theme.colors.textMuted });
break;
case 'title':
style = new TextStyle({ ...base, fontSize: Theme.smallFontSize, fontWeight: '700', letterSpacing: 0.5, fill: Theme.colors.textMuted });
break;
case 'mono':
style = new TextStyle({ ...base, fontFamily: Theme.monoFont });
break;
case 'accent':
style = new TextStyle({ ...base, fill: Theme.colors.accentText, fontWeight: '600' });
break;
}
styleCache.set(token, style);
return style;
}