mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-19 04:52:06 +00:00
Dashboard UX polish pass — consolidates create forms into modals triggered from the page header, fixes layout inconsistencies, adds scroll-to navigation for the Keys page, and aligns the TokenBar with the design system. Changes: - App.tsx: add padding to sidebar header - resolve-page-title.ts: add missing routes, better fallback title - en.ts: fix nav labels (Profiles was 'profiles : multi agents') - ModelsPage: two-col layout, auxiliary tasks modal, TokenBar redesign - ProfilesPage: create button in header, form in modal, Checkbox component - CronPage: create button in header, form in modal - EnvPage: scroll-to sub-nav in header, fix text overflow Modal and dialog standardization: - Replace all native confirm()/window.confirm() with ConfirmDialog (OAuthProvidersCard, PluginsPage, ModelsPage, ConfigPage) - Add useModalBehavior hook (Escape-to-close, scroll lock, focus restore) - Apply hook to ProfilesPage, CronPage, AuxiliaryTasksModal Component fixes (from PR review): - Checkbox: fix controlled/uncontrolled mismatch, add focus-visible ring - TokenBar: add rounded-full to legend dots, remove dead code CI/test fixes: - Fix TS unused imports (noUnusedLocals), type-narrow PickerTarget union - Add windows-footgun suppression on platform-guarded os.killpg - Fix 19 stale unit tests + 9 e2e tests broken by recent main changes - Restore minimal example-dashboard plugin for plugin auth test
44 lines
1.1 KiB
TypeScript
44 lines
1.1 KiB
TypeScript
import { useEffect, useRef } from "react";
|
|
|
|
/**
|
|
* Hook that adds standard modal behaviors when `open` is true:
|
|
* - Escape key calls `onClose`
|
|
* - Body scroll is locked
|
|
* - Focus is restored to the previously focused element on close
|
|
*
|
|
* Returns a ref to attach to the modal container (for optional future focus trapping).
|
|
*/
|
|
export function useModalBehavior({
|
|
open,
|
|
onClose,
|
|
}: {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
}) {
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
if (!open) return;
|
|
|
|
const prevActive = document.activeElement as HTMLElement | null;
|
|
|
|
const onKey = (e: KeyboardEvent) => {
|
|
if (e.key === "Escape") {
|
|
e.preventDefault();
|
|
onClose();
|
|
}
|
|
};
|
|
|
|
document.addEventListener("keydown", onKey);
|
|
const prevOverflow = document.body.style.overflow;
|
|
document.body.style.overflow = "hidden";
|
|
|
|
return () => {
|
|
document.removeEventListener("keydown", onKey);
|
|
document.body.style.overflow = prevOverflow;
|
|
prevActive?.focus?.();
|
|
};
|
|
}, [open, onClose]);
|
|
|
|
return containerRef;
|
|
}
|