mirror of
https://github.com/dergigi/boris.git
synced 2026-01-06 00:14:48 +01:00
feat: add configurable reading font using Bunny Fonts
- Add readingFont setting to UserSettings interface - Create fontLoader utility to load fonts from Bunny Fonts - Add font selector dropdown in settings with popular reading fonts - Use CSS variable --reading-font to apply font to reader content - Support fonts: Inter, Lora, Merriweather, Open Sans, Roboto, Source Serif 4, Crimson Text, Libre Baskerville, PT Serif - Fonts loaded from https://fonts.bunny.net/ (GDPR-friendly)
This commit is contained in:
@@ -13,6 +13,7 @@ import { HighlightsPanel } from './HighlightsPanel'
|
||||
import { fetchReadableContent, ReadableContent } from '../services/readerService'
|
||||
import Settings from './Settings'
|
||||
import { UserSettings, loadSettings, saveSettings } from '../services/settingsService'
|
||||
import { loadFont, getFontFamily } from '../utils/fontLoader'
|
||||
|
||||
export type ViewMode = 'compact' | 'cards' | 'large'
|
||||
|
||||
@@ -65,6 +66,12 @@ const Bookmarks: React.FC<BookmarksProps> = ({ relayPool, onLogout }) => {
|
||||
if (settings.showUnderlines !== undefined) setShowUnderlines(settings.showUnderlines)
|
||||
if (settings.sidebarCollapsed !== undefined) setIsCollapsed(settings.sidebarCollapsed)
|
||||
if (settings.highlightsCollapsed !== undefined) setIsHighlightsCollapsed(settings.highlightsCollapsed)
|
||||
if (settings.readingFont) {
|
||||
loadFont(settings.readingFont)
|
||||
// Apply font to content panel
|
||||
const fontFamily = getFontFamily(settings.readingFont)
|
||||
document.documentElement.style.setProperty('--reading-font', fontFamily)
|
||||
}
|
||||
}, [settings])
|
||||
|
||||
const handleFetchBookmarks = async () => {
|
||||
|
||||
@@ -76,6 +76,27 @@ const Settings: React.FC<SettingsProps> = ({ settings, onSave, onClose, isSaving
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="setting-group">
|
||||
<label htmlFor="readingFont">Reading Font</label>
|
||||
<select
|
||||
id="readingFont"
|
||||
value={localSettings.readingFont || 'system'}
|
||||
onChange={(e) => setLocalSettings({ ...localSettings, readingFont: e.target.value })}
|
||||
className="setting-select"
|
||||
>
|
||||
<option value="system">System Default</option>
|
||||
<option value="inter">Inter</option>
|
||||
<option value="lora">Lora</option>
|
||||
<option value="merriweather">Merriweather</option>
|
||||
<option value="open-sans">Open Sans</option>
|
||||
<option value="roboto">Roboto</option>
|
||||
<option value="source-serif-4">Source Serif 4</option>
|
||||
<option value="crimson-text">Crimson Text</option>
|
||||
<option value="libre-baskerville">Libre Baskerville</option>
|
||||
<option value="pt-serif">PT Serif</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="setting-group">
|
||||
<label htmlFor="showUnderlines" className="checkbox-label">
|
||||
<input
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
|
||||
--reading-font: system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -524,11 +526,13 @@ body {
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-word;
|
||||
font-family: var(--reading-font);
|
||||
}
|
||||
|
||||
.reader-markdown {
|
||||
color: #ddd;
|
||||
line-height: 1.7;
|
||||
font-family: var(--reading-font);
|
||||
}
|
||||
|
||||
/* Ensure content is left-aligned even if source markup uses center */
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface UserSettings {
|
||||
showUnderlines?: boolean
|
||||
sidebarCollapsed?: boolean
|
||||
highlightsCollapsed?: boolean
|
||||
readingFont?: string
|
||||
}
|
||||
|
||||
export async function loadSettings(
|
||||
|
||||
43
src/utils/fontLoader.ts
Normal file
43
src/utils/fontLoader.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
// Map of font names to their Bunny Fonts family names
|
||||
const FONT_FAMILIES: Record<string, string> = {
|
||||
'inter': 'Inter',
|
||||
'lora': 'Lora',
|
||||
'merriweather': 'Merriweather',
|
||||
'open-sans': 'Open Sans',
|
||||
'roboto': 'Roboto',
|
||||
'source-serif-4': 'Source Serif 4',
|
||||
'crimson-text': 'Crimson Text',
|
||||
'libre-baskerville': 'Libre Baskerville',
|
||||
'pt-serif': 'PT Serif'
|
||||
}
|
||||
|
||||
const loadedFonts = new Set<string>()
|
||||
|
||||
export function loadFont(fontKey: string) {
|
||||
if (fontKey === 'system' || loadedFonts.has(fontKey)) {
|
||||
return
|
||||
}
|
||||
|
||||
const fontFamily = FONT_FAMILIES[fontKey]
|
||||
if (!fontFamily) {
|
||||
console.warn(`Unknown font: ${fontKey}`)
|
||||
return
|
||||
}
|
||||
|
||||
// Create a link element to load the font from Bunny Fonts
|
||||
const link = document.createElement('link')
|
||||
link.rel = 'stylesheet'
|
||||
link.href = `https://fonts.bunny.net/css?family=${encodeURIComponent(fontFamily.toLowerCase().replace(/ /g, '-'))}:400,400i,700,700i`
|
||||
document.head.appendChild(link)
|
||||
|
||||
loadedFonts.add(fontKey)
|
||||
}
|
||||
|
||||
export function getFontFamily(fontKey: string | undefined): string {
|
||||
if (!fontKey || fontKey === 'system') {
|
||||
return 'system-ui, -apple-system, sans-serif'
|
||||
}
|
||||
|
||||
const fontFamily = FONT_FAMILIES[fontKey]
|
||||
return fontFamily ? `'${fontFamily}', serif` : 'system-ui, -apple-system, sans-serif'
|
||||
}
|
||||
Reference in New Issue
Block a user