mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-11 07:56:50 +02:00
feat: Add theme selector to user menu, remove configurable border radius
- Remove border radius from theme configuration (borders are always square) - Add theme selector dropdown to user menu (available to all users) - Theme selector shows active theme indicator - Theme selection persists via localStorage
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { User, HardDrive } from "lucide-react";
|
||||
import { User, HardDrive, Palette } from "lucide-react";
|
||||
import accounts from "@/services/accounts";
|
||||
import { useProfile } from "@/hooks/useProfile";
|
||||
import { use$ } from "applesauce-react/hooks";
|
||||
@@ -20,6 +20,7 @@ import { RelayLink } from "./RelayLink";
|
||||
import SettingsDialog from "@/components/SettingsDialog";
|
||||
import LoginDialog from "./LoginDialog";
|
||||
import { useState } from "react";
|
||||
import { useTheme } from "@/lib/themes";
|
||||
|
||||
function UserAvatar({ pubkey }: { pubkey: string }) {
|
||||
const profile = useProfile(pubkey);
|
||||
@@ -57,6 +58,7 @@ export default function UserMenu() {
|
||||
const blossomServers = state.activeAccount?.blossomServers;
|
||||
const [showSettings, setShowSettings] = useState(false);
|
||||
const [showLogin, setShowLogin] = useState(false);
|
||||
const { themeId, setTheme, availableThemes } = useTheme();
|
||||
|
||||
function openProfile() {
|
||||
if (!account?.pubkey) return;
|
||||
@@ -153,22 +155,72 @@ export default function UserMenu() {
|
||||
)}
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
{/* <DropdownMenuItem
|
||||
onClick={() => setShowSettings(true)}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Settings className="mr-2 size-4" />
|
||||
Settings
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator /> */}
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuLabel className="text-xs text-muted-foreground font-normal flex items-center gap-1.5">
|
||||
<Palette className="size-3.5" />
|
||||
<span>Theme</span>
|
||||
</DropdownMenuLabel>
|
||||
{availableThemes.map((theme) => (
|
||||
<DropdownMenuItem
|
||||
key={theme.id}
|
||||
className="cursor-crosshair"
|
||||
onClick={() => setTheme(theme.id)}
|
||||
>
|
||||
<span
|
||||
className={`size-3 rounded-full mr-2 ${
|
||||
themeId === theme.id
|
||||
? "bg-primary"
|
||||
: "bg-muted-foreground/30"
|
||||
}`}
|
||||
/>
|
||||
<span className="text-sm">{theme.name}</span>
|
||||
{themeId === theme.id && (
|
||||
<span className="ml-auto text-xs text-muted-foreground">
|
||||
active
|
||||
</span>
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={logout} className="cursor-crosshair">
|
||||
Log out
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
) : (
|
||||
<DropdownMenuItem onClick={() => setShowLogin(true)}>
|
||||
Log in
|
||||
</DropdownMenuItem>
|
||||
<>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuLabel className="text-xs text-muted-foreground font-normal flex items-center gap-1.5">
|
||||
<Palette className="size-3.5" />
|
||||
<span>Theme</span>
|
||||
</DropdownMenuLabel>
|
||||
{availableThemes.map((theme) => (
|
||||
<DropdownMenuItem
|
||||
key={theme.id}
|
||||
className="cursor-crosshair"
|
||||
onClick={() => setTheme(theme.id)}
|
||||
>
|
||||
<span
|
||||
className={`size-3 rounded-full mr-2 ${
|
||||
themeId === theme.id
|
||||
? "bg-primary"
|
||||
: "bg-muted-foreground/30"
|
||||
}`}
|
||||
/>
|
||||
<span className="text-sm">{theme.name}</span>
|
||||
{themeId === theme.id && (
|
||||
<span className="ml-auto text-xs text-muted-foreground">
|
||||
active
|
||||
</span>
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={() => setShowLogin(true)}>
|
||||
Log in
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
@@ -81,12 +81,6 @@ export function applyTheme(theme: Theme): void {
|
||||
root.style.setProperty("--gradient-2", theme.gradient.color2);
|
||||
root.style.setProperty("--gradient-3", theme.gradient.color3);
|
||||
root.style.setProperty("--gradient-4", theme.gradient.color4);
|
||||
|
||||
// Layout
|
||||
root.style.setProperty("--radius", theme.radius);
|
||||
|
||||
// Remove the dark class management - we now handle this via CSS variables directly
|
||||
// The dark class is no longer needed as themes apply their own color values
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,7 +138,5 @@ export function getThemeVariables(): string[] {
|
||||
"--gradient-2",
|
||||
"--gradient-3",
|
||||
"--gradient-4",
|
||||
// Layout
|
||||
"--radius",
|
||||
];
|
||||
}
|
||||
|
||||
@@ -75,6 +75,4 @@ export const darkTheme: Theme = {
|
||||
color3: "168 85 247", // purple-500
|
||||
color4: "34 211 238", // cyan-400
|
||||
},
|
||||
|
||||
radius: "0.5rem",
|
||||
};
|
||||
|
||||
@@ -75,6 +75,4 @@ export const lightTheme: Theme = {
|
||||
color3: "147 51 234", // purple-600
|
||||
color4: "6 182 212", // cyan-500
|
||||
},
|
||||
|
||||
radius: "0.5rem",
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@ import type { Theme } from "../types";
|
||||
* - Black text for high contrast
|
||||
* - Bright yellow selections
|
||||
* - Dark blue accents
|
||||
* - No rounded corners (squared aesthetic)
|
||||
*/
|
||||
export const plan9Theme: Theme = {
|
||||
id: "plan9",
|
||||
@@ -92,7 +91,4 @@ export const plan9Theme: Theme = {
|
||||
color3: "100 60 180", // Muted purple
|
||||
color4: "40 160 180", // Teal
|
||||
},
|
||||
|
||||
// Plan9 has no rounded corners - everything is squared
|
||||
radius: "0",
|
||||
};
|
||||
|
||||
@@ -126,9 +126,6 @@ export interface Theme {
|
||||
|
||||
/** Gradient colors */
|
||||
gradient: ThemeGradient;
|
||||
|
||||
/** Border radius base value (e.g., "0.5rem", "0") */
|
||||
radius: string;
|
||||
}
|
||||
|
||||
/** Theme metadata for listings (without full color data) */
|
||||
|
||||
Reference in New Issue
Block a user