Font support on themes

This commit is contained in:
Sean Edmunds
2026-01-28 16:11:54 -06:00
parent 983fcbe2ae
commit 9d46c5824d
5 changed files with 53 additions and 4 deletions

View File

@@ -24,6 +24,7 @@ import 'react-fontpicker-ts/dist/index.css';
import '@gfazioli/mantine-text-animate/styles.css';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { Homepage, Settings } from 'pages';
import FontPicker from 'react-fontpicker-ts';
import type { Theme, ThemePlaylist } from 'types';
function App() {
@@ -55,7 +56,7 @@ function App() {
search: colorsTuple(theme.searchColor),
},
white: theme?.backgroundColor,
fontFamily: `${personalData?.[0]?.defaultFont},Helvetica Neue,Roboto,system-ui,sans-serif`,
fontFamily: `${theme?.themeFont || personalData?.[0]?.defaultFont},system-ui,sans-serif`,
autoContrast: true,
});
const mantineTheme = mergeMantineTheme(DEFAULT_THEME, overrides);
@@ -139,6 +140,9 @@ function App() {
<>
{theme && (
<MantineProvider theme={mantineTheme}>
{theme.themeFont && (
<FontPicker loaderOnly loadFonts={theme.themeFont} autoLoad />
)}
<Notifications />
<Loading loaded={loaded} />
<RouterProvider router={router} />

View File

@@ -15,7 +15,8 @@ import {
} from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { useCommonHooks } from 'hooks';
import { useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import FontPicker from 'react-fontpicker-ts';
import { FaShuffle } from 'react-icons/fa6';
import { FiImage, FiSave, FiShuffle, FiX } from 'react-icons/fi';
import {
@@ -64,13 +65,27 @@ export function ThemeEditor({
const viewportRef = useRef<HTMLDivElement>(null);
const [colorId, setColorId] = useState<string>('');
const [colorValue, setColorValue] = useState('#000000');
const [font, setFont] = useState<Theme['themeFont']>();
const re = /(?:\.([^.]+))?$/;
const [backgroundPicker, { open: openBackgroundPicker, close: closeBackgroundPicker }] =
useDisclosure(false);
const filtered = backgroundList.filter((item: string) =>
item.toLowerCase().includes(query.toLowerCase()),
);
useEffect(() => {
if (font) {
setSelectedTheme({
...selectedTheme,
themeFont: font,
});
} else {
setSelectedTheme({
...selectedTheme,
themeFont: null,
});
}
}, [font]);
const items = filtered.map((item: string, index: number) => {
return (
<UnstyledButton
@@ -516,6 +531,23 @@ export function ThemeEditor({
},
}}
/>
<Group w={'100%'} justify='center'>
<FontPicker
style={{ width: '75%' }}
autoLoad
defaultValue={
selectedTheme.themeFont === null ? 'Jost' : selectedTheme.themeFont
}
value={(font: string) => setFont(font)}
/>
<ActionIcon
onClick={() => {
setFont(null);
}}
>
<FiX />
</ActionIcon>
</Group>
</Stack>
{JSON.stringify(defaultTheme) !== JSON.stringify(selectedTheme) && (
<>
@@ -609,6 +641,16 @@ export function ThemeEditor({
)}
</Group>
)}
{key.includes('Font') && (
<Group w={'100%'} justify='center'>
<Text>
{defaultTheme[key as keyof Theme] ||
'Default (Jost)'}
</Text>
<Text>→</Text>
<Text>{designerTheme[key as keyof Theme]}</Text>
</Group>
)}
</Stack>
);
},

View File

@@ -31,6 +31,7 @@ export function ThemeModalContent({ selectedTheme }: { selectedTheme: Theme }) {
'--mantine-color-border-0': selectedTheme?.borderColor,
'--mantine-color-search-0': selectedTheme?.searchColor,
transition: 'all 0.2s ease',
fontFamily: selectedTheme.themeFont ?? undefined,
}}
align='center'
gap={0}
@@ -45,6 +46,7 @@ export function ThemeModalContent({ selectedTheme }: { selectedTheme: Theme }) {
color: selectedTheme?.primaryColor,
borderBottom: `thin solid ${selectedTheme?.borderColor}`,
backgroundColor: `color-mix(in srgb, ${selectedTheme?.searchColor}, transparent 50%)`,
fontFamily: selectedTheme.themeFont ?? undefined,
},
}}
data={[

View File

@@ -73,6 +73,7 @@ export function Themes() {
randomEnabled: 1,
textShadowsEnabled: 0,
appShadowsEnabled: 0,
themeFont: null,
});
const [isLoading, setIsLoading] = useState(false);
@@ -97,7 +98,6 @@ export function Themes() {
setIsLoading(false);
}
}, [debouncedSearch]);
return (
<Stack>
<ThemeModal

View File

@@ -10,6 +10,7 @@ export interface Theme {
randomEnabled: number;
textShadowsEnabled: number;
appShadowsEnabled: number;
themeFont?: string | null;
}
export interface ThemePlaylist {