Skip to main content
Glama
senseisven

MCP Remote macOS Control Server

by senseisven
ThemeToggle.tsx4.02 kB
'use client' import { useThemeStore } from '@/stores/themeStore' import { SunIcon, MoonIcon, ComputerDesktopIcon } from '@heroicons/react/24/outline' import { useEffect, useState } from 'react' interface ThemeToggleProps { variant?: 'dropdown' | 'button' showLabel?: boolean } export default function ThemeToggle({ variant = 'button', showLabel = false }: ThemeToggleProps) { const { theme, resolvedTheme, setTheme, toggleTheme, initTheme } = useThemeStore() const [mounted, setMounted] = useState(false) useEffect(() => { setMounted(true) initTheme() }, [initTheme]) // Prevent hydration mismatch if (!mounted) { return ( <div className="w-10 h-10 bg-background-tertiary animate-pulse rounded-md"></div> ) } const themes = [ { value: 'light', label: 'Light', icon: SunIcon }, { value: 'dark', label: 'Dark', icon: MoonIcon }, { value: 'system', label: 'System', icon: ComputerDesktopIcon } ] as const if (variant === 'dropdown') { return ( <div className="relative"> <select value={theme} onChange={(e) => setTheme(e.target.value as any)} className="input pr-10 appearance-none cursor-pointer" > {themes.map((themeOption) => ( <option key={themeOption.value} value={themeOption.value}> {themeOption.label} </option> ))} </select> <div className="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none"> {(() => { const currentTheme = themes.find(t => t.value === theme) if (currentTheme) { const Icon = currentTheme.icon return <Icon className="w-4 h-4 text-foreground-secondary" /> } return null })()} </div> </div> ) } return ( <div className="flex items-center gap-2"> {/* Quick toggle button */} <button onClick={toggleTheme} className="btn-secondary p-2 relative overflow-hidden group" title={`Switch theme (currently ${theme === 'system' ? `system - ${resolvedTheme}` : theme})`} > <div className="relative"> {resolvedTheme === 'light' ? ( <SunIcon className="w-5 h-5 transition-transform duration-300 group-hover:rotate-45" /> ) : ( <MoonIcon className="w-5 h-5 transition-transform duration-300 group-hover:rotate-12" /> )} {/* Theme indicator dot */} {theme === 'system' && ( <div className="absolute -top-1 -right-1 w-2 h-2 bg-accent rounded-full animate-pulse"></div> )} </div> </button> {/* Theme selector for more options */} <div className="flex bg-background-tertiary rounded-lg p-1"> {themes.map((themeOption) => { const Icon = themeOption.icon const isActive = theme === themeOption.value return ( <button key={themeOption.value} onClick={() => setTheme(themeOption.value)} className={` p-2 rounded-md transition-all duration-200 relative ${isActive ? 'bg-background-elevated text-foreground shadow-sm' : 'text-foreground-secondary hover:text-foreground hover:bg-background-secondary' } `} title={`${themeOption.label} theme${themeOption.value === 'system' ? ` (currently ${resolvedTheme})` : ''}`} > <Icon className="w-4 h-4" /> {/* Active indicator */} {isActive && ( <div className="absolute inset-0 bg-primary/10 rounded-md animate-fade-in"></div> )} {showLabel && ( <span className="text-xs ml-2">{themeOption.label}</span> )} </button> ) })} </div> </div> ) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/senseisven/mcp_macos'

If you have feedback or need assistance with the MCP directory API, please join our Discord server