Status Theme Switcher
openstatus/status-theme-switcherFreeBlock
Agnostic light/dark/system theme switcher. Caller owns the value and onValueChange wiring (next-themes, form state, etc.)
Install it
npx shadcn@latest add https://openstatus.dev/r/status-theme-switcher.jsonSource
1"use client";23import { useStatusBlocksLabels } from "@/components/blocks/status-i18n";4import {5 THEME_VALUES,6 type ThemeValue,7} from "@/components/blocks/status.types";8import { Button } from "@/components/ui/button";9import {10 DropdownMenu,11 DropdownMenuContent,12 DropdownMenuItem,13 DropdownMenuTrigger,14} from "@/components/ui/dropdown-menu";15import { Skeleton } from "@/components/ui/skeleton";16import { cn } from "@/lib/utils";17import { Laptop, Moon, Sun } from "lucide-react";1819export type { ThemeValue };2021function ThemeIcon({22 value,23 className,24}: {25 value: ThemeValue;26 className?: string;27}) {28 const Icon = value === "light" ? Sun : value === "dark" ? Moon : Laptop;29 return <Icon className={cn("h-4 w-4", className)} />;30}3132/**33 * StatusThemeSwitcher — agnostic light/dark/system switcher.34 *35 * Pure presentation: caller owns the value and onValueChange wiring (next-themes,36 * form state, etc.). The block does no hydration handling — render a Skeleton37 * yourself before the active theme is known.38 */39export function StatusThemeSwitcher({40 value,41 onValueChange,42 className,43 ...props44}: Omit<45 React.ComponentProps<typeof DropdownMenuTrigger>,46 "value" | "onValueChange"47> & {48 value: ThemeValue;49 onValueChange: (value: ThemeValue) => void;50}) {51 const labels = useStatusBlocksLabels();52 return (53 <DropdownMenu>54 <DropdownMenuTrigger asChild className={className} {...props}>55 <Button data-slot="status-theme-switcher" variant="ghost" size="icon">56 <ThemeIcon value={value} />57 <span className="sr-only">{labels.ariaToggleTheme}</span>58 </Button>59 </DropdownMenuTrigger>60 <DropdownMenuContent align="end" alignOffset={-4}>61 {THEME_VALUES.map((v) => {62 const isActive = v === value;63 return (64 <DropdownMenuItem65 data-slot="status-theme-switcher-item"66 key={v}67 onClick={() => onValueChange(v)}68 >69 <span>{labels.themeNames[v]}</span>70 <span className="ml-auto">71 <ThemeIcon72 value={v}73 className={74 isActive ? "text-foreground" : "text-muted-foreground"75 }76 />77 </span>78 </DropdownMenuItem>79 );80 })}81 </DropdownMenuContent>82 </DropdownMenu>83 );84}8586/**87 * StatusThemeSwitcherSkeleton — same footprint as the trigger button.88// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from openstatus
All 26 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Status Bannerstatus-banner | openstatus | Blocks | Free | no deps | |
| Status Barstatus-bar | openstatus | Blocks | Free | 1 dep | |
| Status Blank Statesstatus-blank | openstatus | Blocks | Free | no deps | |
| Status Calendarstatus-calendar | openstatus | Blocks | Free | 3 deps | |
| Status Page Chromestatus-chrome | openstatus | Blocks | Free | no deps | |
| Status Page (Complete)status-complete | openstatus | Blocks | Free | no deps | |
| Status Componentstatus-component | openstatus | Blocks | Free | 2 deps | |
| Status Component Groupstatus-component-group | openstatus | Blocks | Free | no deps |
