From 76128b615ff1950ce92156dd28bccbf7dfae37ae Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Thu, 3 Sep 2026 02:56:50 +0300 Subject: [PATCH] feat: add Fixel font support Adds Fixel Text as a new UI font option Allows font sources to load from direct URLs Keeps existing fontsource-based loading working --- packages/ui/src/lib/fontLoader.ts | 4 ++++ packages/ui/src/lib/fontOptions.ts | 32 ++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/lib/fontLoader.ts b/packages/ui/src/lib/fontLoader.ts index 9df09c25..5bb95511 100644 --- a/packages/ui/src/lib/fontLoader.ts +++ b/packages/ui/src/lib/fontLoader.ts @@ -4,6 +4,10 @@ const loadedFaces = new Set(); const pendingFaces = new Map>(); const buildFontUrl = (source: FontFaceSource, weight: number) => { + if ('urls' in source) { + return source.urls[weight]; + } + const packageName = encodeURIComponent(source.packageName).replace('%40', '@').replace('%2F', '/'); return `https://cdn.jsdelivr.net/npm/${packageName}/files/${source.filePrefix}-latin-${weight}-normal.woff2`; }; diff --git a/packages/ui/src/lib/fontOptions.ts b/packages/ui/src/lib/fontOptions.ts index 6387698a..372b51a3 100644 --- a/packages/ui/src/lib/fontOptions.ts +++ b/packages/ui/src/lib/fontOptions.ts @@ -1,14 +1,23 @@ -export type UiFontOption = 'inter' | 'geist-sans' | 'atkinson-hyperlegible' | 'source-sans-3' | 'roboto' | 'noto-sans' | 'dm-sans' | 'manrope' | 'system'; +export type UiFontOption = 'inter' | 'fixel' | 'geist-sans' | 'atkinson-hyperlegible' | 'source-sans-3' | 'roboto' | 'noto-sans' | 'dm-sans' | 'manrope' | 'system'; export type MonoFontOption = 'jetbrains-mono' | 'fira-code' | 'geist-mono' | 'commit-mono' | 'source-code-pro' | 'cascadia-code' | 'roboto-mono' | 'iosevka' | 'system-mono'; -export interface FontFaceSource { +interface FontFaceSourceBase { family: string; - packageName: string; - filePrefix: string; weights: number[]; } +interface FontsourceFaceSource extends FontFaceSourceBase { + packageName: string; + filePrefix: string; +} + +interface DirectFontFaceSource extends FontFaceSourceBase { + urls: Record; +} + +export type FontFaceSource = FontsourceFaceSource | DirectFontFaceSource; + export interface FontOptionDefinition { id: T; label: string; @@ -26,6 +35,21 @@ export const UI_FONT_OPTIONS: FontOptionDefinition[] = [ stack: '"Inter", "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', source: { family: 'Inter', packageName: '@fontsource/inter', filePrefix: 'inter', weights: [400, 500, 600] } }, + { + id: 'fixel', + label: 'Fixel Text', + description: 'Humanist geometric sans-serif with full Ukrainian support.', + stack: '"Fixel Text", "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', + source: { + family: 'Fixel Text', + weights: [400, 500, 600], + urls: { + 400: 'https://cdn.jsdelivr.net/gh/MacPaw/Fixel@f6ee910e98add47e830db87f1a754130506c11a2/fonts/webfonts/FixelText-Regular.woff2', + 500: 'https://cdn.jsdelivr.net/gh/MacPaw/Fixel@f6ee910e98add47e830db87f1a754130506c11a2/fonts/webfonts/FixelText-Medium.woff2', + 600: 'https://cdn.jsdelivr.net/gh/MacPaw/Fixel@f6ee910e98add47e830db87f1a754130506c11a2/fonts/webfonts/FixelText-SemiBold.woff2' + } + } + }, { id: 'geist-sans', label: 'Geist Sans',