mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 09:33:46 +00:00
- DOMPurify strict allowlist with sandbox on iframes - safeColor() CSS injection prevention for category_color - URL validation (http/https) for images and links - encodeURIComponent for slug in API calls - Keyboard navigation on news cards (Enter/Space) - aria-label, aria-pressed, type=button on all buttons - 44px touch targets on remaining buttons - memo() wrappers + stable callbacks (fewer re-renders) - Canvas draw call batching (~75% reduction) - TipTap extensions useMemo deps fix ([t] -> []) - Featured image loading=eager fetchPriority=high (LCP) - Unsafe Number(id) NaN guard
48 lines
1.0 KiB
TypeScript
48 lines
1.0 KiB
TypeScript
import { cn } from '../../lib/utils';
|
|
|
|
interface ToggleProps {
|
|
checked: boolean;
|
|
onChange: () => void;
|
|
disabled?: boolean;
|
|
'aria-label'?: string;
|
|
className?: string;
|
|
}
|
|
|
|
export function Toggle({
|
|
checked,
|
|
onChange,
|
|
disabled,
|
|
'aria-label': ariaLabel,
|
|
className,
|
|
}: ToggleProps) {
|
|
return (
|
|
<button
|
|
type="button"
|
|
role="switch"
|
|
aria-checked={checked}
|
|
aria-label={ariaLabel}
|
|
onClick={onChange}
|
|
disabled={disabled}
|
|
className={cn(
|
|
'flex min-h-[44px] items-center',
|
|
disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer',
|
|
className,
|
|
)}
|
|
>
|
|
<div
|
|
className={cn(
|
|
'relative h-8 w-14 rounded-full transition-colors',
|
|
checked ? 'bg-accent-500' : 'bg-dark-600',
|
|
)}
|
|
>
|
|
<div
|
|
className={cn(
|
|
'absolute left-1 top-1 h-6 w-6 rounded-full bg-white transition-transform duration-200',
|
|
checked ? 'translate-x-6' : 'translate-x-0',
|
|
)}
|
|
/>
|
|
</div>
|
|
</button>
|
|
);
|
|
}
|