Files
harbor-net/src/web/features/diagnostics/DiagnosticsFeature.tsx
T
dokril dc1fd76c44
Build and Deploy Gateway / build-and-push (push) Successful in 35s
Build and Deploy Gateway / deploy (push) Successful in 7s
Simplify rail motion and add routing help toggle
2026-08-17 17:26:57 +03:00

73 lines
2.4 KiB
TypeScript

import { useEffect, useRef, useState } from 'react';
import { RailAction } from '../../ui/RailAction.js';
export function useDiagnosticsFeature() {
const [isOpen, setIsOpen] = useState(false);
const panelRef = useRef<HTMLElement>(null);
const toggleRef = useRef<HTMLButtonElement>(null);
const closeRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
if (!isOpen) return undefined;
const frame = requestAnimationFrame(() => closeRef.current?.focus());
const closeDiagnostics = (event: PointerEvent | KeyboardEvent) => {
if (event.type === 'keydown' && (event as KeyboardEvent).key !== 'Escape') return;
if (event.type !== 'keydown' && (
panelRef.current?.contains(event.target as Node) || toggleRef.current?.contains(event.target as Node)
)) return;
setIsOpen(false);
};
document.addEventListener('pointerdown', closeDiagnostics);
document.addEventListener('keydown', closeDiagnostics);
return () => {
cancelAnimationFrame(frame);
document.removeEventListener('pointerdown', closeDiagnostics);
document.removeEventListener('keydown', closeDiagnostics);
requestAnimationFrame(() => {
if (panelRef.current?.contains(document.activeElement)) toggleRef.current?.focus();
});
};
}, [isOpen]);
return {
isOpen,
panelRef,
toggleRef,
closeRef,
close: () => setIsOpen(false),
toggle: () => setIsOpen((open) => !open),
};
}
export type DiagnosticsFeature = ReturnType<typeof useDiagnosticsFeature>;
export function DiagnosticsToggle({
feature,
open,
onToggle,
}: {
feature: DiagnosticsFeature;
open: boolean;
onToggle: () => void;
}) {
return <RailAction
buttonRef={feature.toggleRef}
className="client-instructions-toggle client-diagnostics-toggle"
open={open}
controls="client-diagnostics"
ariaLabel={open ? 'Закрыть диагностику' : 'Проверить маршруты'}
label="Диагностика"
onClick={onToggle}
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path className="client-rail-diagnostics-trace" d="M4.5 10h2l1.2-2.4 2.2 4.8 1.2-2.4h3.4" />
<g className="client-rail-diagnostics-position">
<g className="client-rail-diagnostics-glass">
<circle cx="9.5" cy="9.5" r="6.5" />
<path d="m14.2 14.2 6.3 6.3" />
</g>
</g>
</svg>
</RailAction>;
}