Pure `nix fmt` output from the commit before this one — no hand edits. 203 files: 52 md, 42 tsx, 32 js, 32 css, 21 ts, 13 html, 8 json, 3 mjs. Reproduce with `nix develop -c nix fmt` on the parent commit; the result should be byte-identical to this tree. None of the 13 `.prettierignore` entries appears here — verified by intersecting the changed-file list against the ignore file, with a control proving the intersection finds a match when one exists.
64 lines
2.1 KiB
TypeScript
64 lines
2.1 KiB
TypeScript
// <SidePanel> — the slide-in drawer for the inbox/todos flyouts.
|
|
// Deliberately a new Preact component, not the shared
|
|
// `<hive-side-panel>` shadow-DOM custom element (@hive/shared/
|
|
// side-panel.js) — same rationale as StatusChips' Badge/Dropdown:
|
|
// mara's ask was real Preact components for this rewrite, not a port
|
|
// of the old widget family. Drops that element's drag-to-resize +
|
|
// localStorage width persistence for this first slice (fixed width via
|
|
// CSS, see SidePanel.css) — a real simplification, not an oversight;
|
|
// revisit if a fixed width proves cramped in practice.
|
|
//
|
|
// Content styling (`.agent-inbox`, `.inbox-*`, `.side-panel-empty`)
|
|
// already ships globally via `agent.css` and is reused verbatim by
|
|
// InboxPanel/TodosPanel — only the drawer chrome itself is new here.
|
|
import { useEffect } from "preact/hooks";
|
|
import type { ComponentChildren } from "preact";
|
|
import "./SidePanel.css";
|
|
|
|
export interface SidePanelProps {
|
|
open: boolean;
|
|
title: string;
|
|
onClose: () => void;
|
|
children?: ComponentChildren;
|
|
}
|
|
|
|
export function SidePanel({ open, title, onClose, children }: SidePanelProps) {
|
|
useEffect(() => {
|
|
if (!open) return;
|
|
function onKey(e: KeyboardEvent) {
|
|
if (e.key === "Escape") onClose();
|
|
}
|
|
document.addEventListener("keydown", onKey);
|
|
return () => document.removeEventListener("keydown", onKey);
|
|
}, [open, onClose]);
|
|
|
|
return (
|
|
<>
|
|
<div
|
|
class={`agent-side-panel-backdrop${open ? " open" : ""}`}
|
|
onClick={onClose}
|
|
aria-hidden="true"
|
|
/>
|
|
<aside
|
|
class={`agent-side-panel-drawer${open ? " open" : ""}`}
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-hidden={!open}
|
|
aria-label={title}
|
|
>
|
|
<div class="agent-side-panel-head">
|
|
<span class="agent-side-panel-title">{title}</span>
|
|
<button
|
|
type="button"
|
|
class="agent-side-panel-close"
|
|
title="close (esc)"
|
|
onClick={onClose}
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
<div class="agent-side-panel-body">{children}</div>
|
|
</aside>
|
|
</>
|
|
);
|
|
}
|