Skip to content

Commit

Permalink
✨ Show current theme option on theme switcher
Browse files Browse the repository at this point in the history
  • Loading branch information
wancup committed Oct 25, 2024
1 parent 79fb77c commit bc1d178
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 32 deletions.
83 changes: 52 additions & 31 deletions src/features/color-theme/components/color-theme-switcher.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
import { css } from "$panda/css";
import { IconButton } from "$park/icon-button";
import { Menu } from "$park/menu";
import { MoonIcon, SunIcon } from "lucide-solid";
import { createSignal, type JSX, onMount } from "solid-js";
import { Tooltip } from "$park/tooltip";
import { CheckIcon, MoonIcon, SunIcon, SunMoonIcon } from "lucide-solid";
import { createSignal, Index, type JSX, onMount } from "solid-js";
import { match } from "ts-pattern";
import { COLOR_THEME_OPTION, STORAGE_KEY } from "~/site";
import { type ColorTheme } from "../types/color-theme-type";
import { type ColorThemeOption } from "../types/color-theme-type";

function parseThemeOption(theme: string | null): ColorThemeOption {
return match(theme)
.with(COLOR_THEME_OPTION.dark, () => (COLOR_THEME_OPTION.dark))
.with(COLOR_THEME_OPTION.light, () => COLOR_THEME_OPTION.light)
.otherwise(() => COLOR_THEME_OPTION.system);
}

export function ColorThemeSwitcher(): JSX.Element {
const [theme, setTheme] = createSignal<ColorTheme>(COLOR_THEME_OPTION.light);
const [theme, setTheme] = createSignal<ColorThemeOption>(COLOR_THEME_OPTION.system);

onMount(() => {
const currentTheme = document.documentElement.classList.contains(COLOR_THEME_OPTION.dark)
? COLOR_THEME_OPTION.dark
: COLOR_THEME_OPTION.light;
const storagedTheme = localStorage.getItem(STORAGE_KEY.colorTheme);
const currentTheme = parseThemeOption(storagedTheme);
setTheme(currentTheme);
});

const handleSelectTheme = (selectedTheme: string): void => {
const newTheme = match(selectedTheme)
.with(COLOR_THEME_OPTION.dark, () => (COLOR_THEME_OPTION.dark))
.with(COLOR_THEME_OPTION.light, () => COLOR_THEME_OPTION.light)
.otherwise(() => COLOR_THEME_OPTION.system);
const newTheme = parseThemeOption(selectedTheme);
localStorage.setItem(STORAGE_KEY.colorTheme, newTheme);

const themeClass = match(newTheme)
Expand All @@ -35,38 +39,55 @@ export function ColorThemeSwitcher(): JSX.Element {
.otherwise((t) => t);
document.documentElement.classList.remove(COLOR_THEME_OPTION.dark, COLOR_THEME_OPTION.light);
document.documentElement.classList.add(themeClass);
setTheme(newTheme);
};

return (
<Menu.Root
positioning={{ placement: "bottom-end" }}
onSelect={(item) => {
handleSelectTheme(item.value);
}}
>
<Menu.Trigger
asChild={(triggerProps) => (
<IconButton {...triggerProps()} variant="ghost" size="sm">
{match(theme())
.with("dark", () => <MoonIcon />)
.with("light", () => <SunIcon />)
.exhaustive()}
</IconButton>
<Tooltip.Root openDelay={200}>
<Tooltip.Trigger>
<IconButton {...triggerProps()} variant="ghost" size="sm">
{match(theme())
.with("dark", () => <MoonIcon />)
.with("light", () => <SunIcon />)
.with("system", () => <SunMoonIcon />)
.exhaustive()}
</IconButton>
</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Arrow>
<Tooltip.ArrowTip />
</Tooltip.Arrow>
<Tooltip.Content>Change color theme</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
)}
/>
<Menu.Positioner class={css({ marginRight: "16px" })}>
<Menu.Content>
<Menu.ItemGroup>
<Menu.Item value={COLOR_THEME_OPTION.dark}>
Dark
</Menu.Item>
<Menu.Item value={COLOR_THEME_OPTION.light}>
Light
</Menu.Item>
<Menu.Item value={COLOR_THEME_OPTION.system}>
System
</Menu.Item>
</Menu.ItemGroup>
<Menu.RadioItemGroup
value={theme()}
onValueChange={(theme) => {
handleSelectTheme(theme.value);
}}
>
<Index each={Object.values(COLOR_THEME_OPTION)}>
{(theme) => (
<Menu.RadioItem value={theme()}>
<Menu.ItemIndicator>
<CheckIcon />
</Menu.ItemIndicator>
<Menu.ItemText class={css({ textTransform: "capitalize" })}>
{theme()}
</Menu.ItemText>
</Menu.RadioItem>
)}
</Index>
</Menu.RadioItemGroup>
</Menu.Content>
</Menu.Positioner>
</Menu.Root>
Expand Down
1 change: 0 additions & 1 deletion src/features/color-theme/types/color-theme-type.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { type COLOR_THEME_OPTION } from "~/site";

export type ColorThemeOption = typeof COLOR_THEME_OPTION[keyof typeof COLOR_THEME_OPTION];
export type ColorTheme = Exclude<ColorThemeOption, "system">;

0 comments on commit bc1d178

Please sign in to comment.