diff options
| author | Fuwn <[email protected]> | 2026-02-07 01:42:57 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-07 01:42:57 -0800 |
| commit | 5c5b1993edd890a80870ee05607ac5f088191d4e (patch) | |
| tree | a721b76bcd49ba10826c53efc87302c7a689512f /apps/web/app/reader/settings/_components/appearance-settings.tsx | |
| download | asa.news-5c5b1993edd890a80870ee05607ac5f088191d4e.tar.xz asa.news-5c5b1993edd890a80870ee05607ac5f088191d4e.zip | |
feat: asa.news RSS reader with developer tier, REST API, and webhooks
Full-stack RSS reader SaaS: Supabase + Next.js + Go worker.
Includes three subscription tiers (free/pro/developer), API key auth,
read-only REST API, webhook push notifications, Stripe billing with
proration, and PWA support.
Diffstat (limited to 'apps/web/app/reader/settings/_components/appearance-settings.tsx')
| -rw-r--r-- | apps/web/app/reader/settings/_components/appearance-settings.tsx | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/apps/web/app/reader/settings/_components/appearance-settings.tsx b/apps/web/app/reader/settings/_components/appearance-settings.tsx new file mode 100644 index 0000000..9c0e214 --- /dev/null +++ b/apps/web/app/reader/settings/_components/appearance-settings.tsx @@ -0,0 +1,123 @@ +"use client" + +import { useTheme } from "next-themes" +import { useUserInterfaceStore } from "@/lib/stores/user-interface-store" + +export function AppearanceSettings() { + const { theme, setTheme } = useTheme() + const entryListViewMode = useUserInterfaceStore( + (state) => state.entryListViewMode + ) + const setEntryListViewMode = useUserInterfaceStore( + (state) => state.setEntryListViewMode + ) + const displayDensity = useUserInterfaceStore( + (state) => state.displayDensity + ) + const setDisplayDensity = useUserInterfaceStore( + (state) => state.setDisplayDensity + ) + const showFeedFavicons = useUserInterfaceStore( + (state) => state.showFeedFavicons + ) + const setShowFeedFavicons = useUserInterfaceStore( + (state) => state.setShowFeedFavicons + ) + const focusFollowsInteraction = useUserInterfaceStore( + (state) => state.focusFollowsInteraction + ) + const setFocusFollowsInteraction = useUserInterfaceStore( + (state) => state.setFocusFollowsInteraction + ) + + return ( + <div className="px-4 py-3"> + <div className="mb-6"> + <h3 className="mb-2 text-text-primary">theme</h3> + <p className="mb-3 text-text-dim"> + controls the colour scheme of the application + </p> + <select + value={theme ?? "system"} + onChange={(event) => setTheme(event.target.value)} + className="border border-border bg-background-primary px-3 py-2 text-text-primary outline-none focus:border-text-dim" + > + <option value="system">system</option> + <option value="light">light</option> + <option value="dark">dark</option> + </select> + </div> + <div className="mb-6"> + <h3 className="mb-2 text-text-primary">display density</h3> + <p className="mb-3 text-text-dim"> + controls the overall text size and spacing + </p> + <select + value={displayDensity} + onChange={(event) => + setDisplayDensity( + event.target.value as "compact" | "default" | "spacious" + ) + } + className="border border-border bg-background-primary px-3 py-2 text-text-primary outline-none focus:border-text-dim" + > + <option value="compact">compact</option> + <option value="default">default</option> + <option value="spacious">spacious</option> + </select> + </div> + <div className="mb-6"> + <h3 className="mb-2 text-text-primary">entry list view</h3> + <p className="mb-3 text-text-dim"> + controls how entries are displayed in the list + </p> + <select + value={entryListViewMode} + onChange={(event) => + setEntryListViewMode( + event.target.value as "compact" | "comfortable" | "expanded" + ) + } + className="border border-border bg-background-primary px-3 py-2 text-text-primary outline-none focus:border-text-dim" + > + <option value="compact">compact</option> + <option value="comfortable">comfortable</option> + <option value="expanded">expanded</option> + </select> + </div> + <div className="mb-6"> + <h3 className="mb-2 text-text-primary">feed favicons</h3> + <p className="mb-3 text-text-dim"> + show website icons next to feed names in the sidebar + </p> + <label className="flex cursor-pointer items-center gap-2 text-text-primary"> + <input + type="checkbox" + checked={showFeedFavicons} + onChange={(event) => setShowFeedFavicons(event.target.checked)} + className="accent-text-primary" + /> + <span>show favicons</span> + </label> + </div> + <div> + <h3 className="mb-2 text-text-primary">focus follows interaction</h3> + <p className="mb-3 text-text-dim"> + automatically move keyboard panel focus to the last pane you + interacted with (clicked or scrolled) + </p> + <label className="flex cursor-pointer items-center gap-2 text-text-primary"> + <input + type="checkbox" + checked={focusFollowsInteraction} + onChange={(event) => + setFocusFollowsInteraction(event.target.checked) + } + className="accent-text-primary" + /> + <span>enable focus follows interaction</span> + </label> + </div> + </div> + ) +} |