From 9d46c5824dac3919ea9e3944139acdd6ac171da8 Mon Sep 17 00:00:00 2001 From: Sean Edmunds Date: Wed, 28 Jan 2026 16:11:54 -0600 Subject: [PATCH] Font support on themes --- src/App.tsx | 6 ++- .../ThemeModal/components/ThemeEditor.tsx | 46 ++++++++++++++++++- .../components/ThemeModalContent.tsx | 2 + .../components/Theming/Themes/Themes.tsx | 2 +- src/types/theme.ts | 1 + 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 9df271a..251f329 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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 && ( + {theme.themeFont && ( + + )} diff --git a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx index 14739c0..fa06bb5 100644 --- a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx +++ b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx @@ -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(null); const [colorId, setColorId] = useState(''); const [colorValue, setColorValue] = useState('#000000'); - + const [font, setFont] = useState(); 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 ( + + setFont(font)} + /> + { + setFont(null); + }} + > + + + {JSON.stringify(defaultTheme) !== JSON.stringify(selectedTheme) && ( <> @@ -609,6 +641,16 @@ export function ThemeEditor({ )} )} + {key.includes('Font') && ( + + + {defaultTheme[key as keyof Theme] || + 'Default (Jost)'} + + → + {designerTheme[key as keyof Theme]} + + )} ); }, diff --git a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeModalContent.tsx b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeModalContent.tsx index 3ee4697..f1d0e9f 100644 --- a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeModalContent.tsx +++ b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeModalContent.tsx @@ -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={[ diff --git a/src/pages/settings/components/Theming/Themes/Themes.tsx b/src/pages/settings/components/Theming/Themes/Themes.tsx index 4a02b00..fee9192 100644 --- a/src/pages/settings/components/Theming/Themes/Themes.tsx +++ b/src/pages/settings/components/Theming/Themes/Themes.tsx @@ -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 (