import type { ReactNode } from 'react'; // Shared visual language for the /headscale panels, matching the /soulseek grouped views: almost-black // cards on hairline white borders. Kept local to the app so the look changes in one place. export const Card = ({ children }: { children: ReactNode }) => (
{children}
); export const SectionHeader = ({ title, subtitle, action, }: { title: string; subtitle?: string; action?: ReactNode; }) => (

{title}

{subtitle &&

{subtitle}

}
{action &&
{action}
}
); type ButtonProps = { children: ReactNode; onClick?: () => void; type?: 'button' | 'submit'; variant?: 'primary' | 'ghost' | 'danger'; disabled?: boolean; title?: string; }; const VARIANTS: Record, string> = { primary: 'border-primary/40 bg-primary/15 text-primary hover:bg-primary/25', ghost: 'border-white/10 bg-white/[0.02] text-zinc-300 hover:bg-white/10 hover:text-zinc-100', danger: 'border-red-500/30 bg-red-500/10 text-red-300 hover:bg-red-500/20', }; export const Button = ({ children, onClick, type = 'button', variant = 'ghost', disabled, title }: ButtonProps) => ( ); type FieldProps = { label: string; value: string; onChange: (value: string) => void; placeholder?: string; hint?: string; type?: 'text' | 'password'; autoFocus?: boolean; }; export const Field = ({ label, value, onChange, placeholder, hint, type = 'text', autoFocus }: FieldProps) => ( ); /** Tiny status light: green healthy, amber unknown/unverified, red failing. */ export const Dot = ({ tone }: { tone: 'ok' | 'warn' | 'bad' | 'idle' }) => { const color = tone === 'ok' ? 'bg-emerald-400' : tone === 'warn' ? 'bg-amber-400' : tone === 'bad' ? 'bg-red-400' : 'bg-zinc-600'; return ; }; export const Badge = ({ children, tone = 'neutral' }: { children: ReactNode; tone?: 'neutral' | 'active' }) => ( {children} ); export const ErrorNote = ({ children }: { children: ReactNode }) => (
{children}
);