Exosphere is a set of small, modular, self-hostable community tools built on the AT Protocol.
app.exosphere.site
1import type { ComponentType } from "preact";
2import { theme, setTheme } from "../theme-state.ts";
3import * as ui from "@exosphere/client/ui.css";
4
5type IconComponent = ComponentType<{ size: string | number }>;
6
7interface ThemeToggleProps {
8 icons: Record<"light" | "dark" | "system", IconComponent>;
9}
10
11const themeOptions = ["light", "dark", "system"] as const;
12const labels: Record<(typeof themeOptions)[number], string> = {
13 light: "Light",
14 dark: "Dark",
15 system: "System",
16};
17
18export function ThemeToggle({ icons }: ThemeToggleProps) {
19 const current = theme.value;
20
21 return (
22 <div class={ui.themeToggle} role="radiogroup" aria-label="Theme">
23 {themeOptions.map((value) => {
24 const Icon = icons[value];
25 return (
26 <button
27 key={value}
28 class={`${ui.themeToggleBtn} ${current === value ? ui.themeToggleBtnActive : ""}`}
29 onClick={() => setTheme(value)}
30 role="radio"
31 aria-checked={current === value}
32 aria-label={labels[value]}
33 title={labels[value]}
34 >
35 <Icon size={16} />
36 </button>
37 );
38 })}
39 </div>
40 );
41}