Files
bedolaga-cabinet/src/components/admin/Toggle.tsx
Fringg 74e6d52fee fix: news feature security, accessibility, performance improvements
- 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
2026-03-23 11:09:52 +03:00

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>
);
}