"use client";
import { useStatusBlocksLabels } from "@openstatus/ui/components/blocks/status-i18n";
import {
THEME_VALUES,
type ThemeValue,
} from "@openstatus/ui/components/blocks/status.types";
import { Button } from "@openstatus/ui/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@openstatus/ui/components/ui/dropdown-menu";
import { Skeleton } from "@openstatus/ui/components/ui/skeleton";
import { cn } from "@openstatus/ui/lib/utils";
import { Laptop, Moon, Sun } from "lucide-react";
export type { ThemeValue };
function ThemeIcon({
value,
className,
}: {
value: ThemeValue;
className?: string;
}) {
const Icon = value === "light" ? Sun : value === "dark" ? Moon : Laptop;
return ;
}
/**
* StatusThemeSwitcher — agnostic light/dark/system switcher.
*
* Pure presentation: caller owns the value and onValueChange wiring (next-themes,
* form state, etc.). The block does no hydration handling — render a Skeleton
* yourself before the active theme is known.
*/
export function StatusThemeSwitcher({
value,
onValueChange,
className,
...props
}: Omit<
React.ComponentProps,
"value" | "onValueChange"
> & {
value: ThemeValue;
onValueChange: (value: ThemeValue) => void;
}) {
const labels = useStatusBlocksLabels();
return (
{THEME_VALUES.map((v) => {
const isActive = v === value;
return (
onValueChange(v)}
>
{labels.themeNames[v]}
);
})}
);
}
/**
* StatusThemeSwitcherSkeleton — same footprint as the trigger button.
* Render while the active theme isn't known yet (e.g. before next-themes
* hydrates) so the surrounding layout doesn't shift.
*/
export function StatusThemeSwitcherSkeleton({
className,
...props
}: React.ComponentProps) {
return (
);
}