From 9d3b2a90316a1a5f735845f61abbd8a875529060 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Sat, 14 Feb 2026 10:12:22 -0800 Subject: feat: add font theme support (fixing NK-rn4nzp) --- frontend/src/App.tsx | 26 ++++++++++++++++++++++---- frontend/src/components/FeedItem.css | 4 ++-- frontend/src/components/FeedList.css | 7 ++----- frontend/src/components/Settings.css | 21 +++++++++++++++++++-- frontend/src/components/Settings.tsx | 29 ++++++++++++++++++++++++++++- frontend/src/index.css | 31 +++++++++++++++++++++++++++++-- 6 files changed, 102 insertions(+), 16 deletions(-) (limited to 'frontend') diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 74ae89e..1812451 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -36,12 +36,19 @@ import FeedList from './components/FeedList'; import FeedItems from './components/FeedItems'; import Settings from './components/Settings'; -function Dashboard({ theme, setTheme }: { theme: string; setTheme: (t: string) => void }) { +interface DashboardProps { + theme: string; + setTheme: (t: string) => void; + fontTheme: string; + setFontTheme: (t: string) => void; +} + +function Dashboard({ theme, setTheme, fontTheme, setFontTheme }: DashboardProps) { const [sidebarVisible, setSidebarVisible] = useState(true); return (
{!sidebarVisible && ( @@ -60,7 +67,7 @@ function Dashboard({ theme, setTheme }: { theme: string; setTheme: (t: string) = } /> } /> - } /> + } /> } /> @@ -71,12 +78,18 @@ function Dashboard({ theme, setTheme }: { theme: string; setTheme: (t: string) = function App() { const [theme, setTheme] = useState(localStorage.getItem('neko-theme') || 'light'); + const [fontTheme, setFontTheme] = useState(localStorage.getItem('neko-font-theme') || 'default'); const handleSetTheme = (newTheme: string) => { setTheme(newTheme); localStorage.setItem('neko-theme', newTheme); }; + const handleSetFontTheme = (newFontTheme: string) => { + setFontTheme(newFontTheme); + localStorage.setItem('neko-font-theme', newFontTheme); + }; + const basename = window.location.pathname.startsWith('/v2') ? '/v2' : '/'; return ( @@ -87,7 +100,12 @@ function App() { path="/*" element={ - + } /> diff --git a/frontend/src/components/FeedItem.css b/frontend/src/components/FeedItem.css index 3becb20..4eca2b1 100644 --- a/frontend/src/components/FeedItem.css +++ b/frontend/src/components/FeedItem.css @@ -15,7 +15,7 @@ } .item-title { - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-family: var(--font-heading); font-size: 1.8rem; font-weight: bold; text-decoration: none; @@ -114,7 +114,7 @@ border: 1px solid var(--border-color, #ccc); color: blue; cursor: pointer; - font-family: 'Helvetica Neue'; + font-family: var(--font-heading); font-weight: bold; font-size: 0.8rem; padding: 2px 6px; diff --git a/frontend/src/components/FeedList.css b/frontend/src/components/FeedList.css index 7bb0f4c..7c39901 100644 --- a/frontend/src/components/FeedList.css +++ b/frontend/src/components/FeedList.css @@ -1,6 +1,6 @@ .feed-list { padding: 1rem; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-family: var(--font-heading); color: #777; /* specific v1 color */ font-size: 0.8rem; @@ -18,9 +18,6 @@ z-index: 10; padding-bottom: 0.5rem; color: var(--text-color); - /* Usually dark/white depending on theme, v1 was white on blue? No, white on fixed header? No, v1 logo class says color: white. But sidebar is #ccc. */ - /* In v1 logo was fixed top left (blue header bar?). In v2 sidebar is #ccc. - Let's use theme text color but maybe bolder? */ } /* Override logo color if necessary for themes */ @@ -55,7 +52,7 @@ margin: 1rem 0 0.25rem 0; cursor: pointer; user-select: none; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-family: var(--font-heading); color: #333; /* Darker than list items */ text-transform: lowercase; diff --git a/frontend/src/components/Settings.css b/frontend/src/components/Settings.css index ec6fc83..c8784a0 100644 --- a/frontend/src/components/Settings.css +++ b/frontend/src/components/Settings.css @@ -4,7 +4,8 @@ margin: 0 auto; } -.add-feed-section { +.add-feed-section, +.appearance-section { background: var(--sidebar-bg); padding: 1.5rem; border-radius: 8px; @@ -12,6 +13,22 @@ border: 1px solid var(--border-color); } +.font-selector { + display: flex; + align-items: center; + gap: 1rem; +} + +.font-select { + padding: 0.5rem; + border: 1px solid var(--border-color); + background: var(--bg-color); + color: var(--text-color); + border-radius: 4px; + font-size: 1rem; + min-width: 200px; +} + .add-feed-form { display: flex; gap: 1rem; @@ -57,7 +74,7 @@ } .feed-title { - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-family: var(--font-heading); font-weight: bold; font-size: 1.1rem; } diff --git a/frontend/src/components/Settings.tsx b/frontend/src/components/Settings.tsx index 16cf6a3..80e3068 100644 --- a/frontend/src/components/Settings.tsx +++ b/frontend/src/components/Settings.tsx @@ -3,14 +3,21 @@ import type { Feed } from '../types'; import './Settings.css'; import { apiFetch } from '../utils'; -export default function Settings() { +interface SettingsProps { + fontTheme?: string; + setFontTheme?: (t: string) => void; +} + +export default function Settings({ fontTheme, setFontTheme }: SettingsProps) { const [feeds, setFeeds] = useState([]); + /* ... existing state ... */ const [newFeedUrl, setNewFeedUrl] = useState(''); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [importFile, setImportFile] = useState(null); + /* ... existing fetchFeeds ... */ const fetchFeeds = () => { setLoading(true); apiFetch('/api/feed/') @@ -32,6 +39,7 @@ export default function Settings() { fetchFeeds(); }, []); + /* ... existing handlers ... */ const handleAddFeed = (e: React.FormEvent) => { e.preventDefault(); if (!newFeedUrl) return; @@ -106,6 +114,25 @@ export default function Settings() {

Settings

+ {setFontTheme && ( +
+

Appearance

+
+ + +
+
+ )} +

Add New Feed

diff --git a/frontend/src/index.css b/frontend/src/index.css index 3365d34..6396633 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,5 +1,11 @@ +:root { + /* Font Variables */ + --font-body: Palatino, 'Palatino Linotype', 'Palatino LT STD', 'Book Antiqua', Georgia, serif; + --font-heading: 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + body { - font-family: Palatino, 'Palatino Linotype', 'Palatino LT STD', 'Book Antiqua', Georgia, serif; + font-family: var(--font-body); } h1, @@ -10,10 +16,31 @@ h5, .logo, .nav-link, .logout-btn { - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-family: var(--font-heading); font-weight: bold; } +/* Font Themes */ +.font-default { + --font-body: Palatino, 'Palatino Linotype', 'Palatino LT STD', 'Book Antiqua', Georgia, serif; + --font-heading: 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +.font-serif { + --font-body: Georgia, 'Times New Roman', Times, serif; + --font-heading: Georgia, 'Times New Roman', Times, serif; +} + +.font-sans { + --font-body: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + --font-heading: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; +} + +.font-mono { + --font-body: Menlo, Monaco, Consolas, 'Courier New', monospace; + --font-heading: Menlo, Monaco, Consolas, 'Courier New', monospace; +} + :root { line-height: 1.5; font-size: 18px; -- cgit v1.2.3