Files
multi-seal-mail-webui/src/layout/HelpMenu.tsx

123 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect, useRef, useState } from "react";
import { useLocation } from "react-router-dom";
import { HelpCircle, Info, BookOpen, GitBranch } from "lucide-react";
import Button from "../components/Button";
import { helpContextForPathname, helpQueryForContext, type HelpContext } from "../utils/helpContext";
export default function HelpMenu() {
const [open, setOpen] = useState(false);
const [aboutOpen, setAboutOpen] = useState(false);
const [contextOpen, setContextOpen] = useState(false);
const wrapRef = useRef<HTMLDivElement>(null);
const location = useLocation();
const helpContext = helpContextForPathname(location.pathname);
useEffect(() => {
function openContextHelp(event: KeyboardEvent) {
if (event.key !== "F1") return;
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
setOpen(false);
setContextOpen(true);
}
function onPointerDown(event: MouseEvent) {
if (wrapRef.current && !wrapRef.current.contains(event.target as Node)) {
setOpen(false);
}
}
window.addEventListener("keydown", openContextHelp, true);
window.addEventListener("mousedown", onPointerDown);
return () => {
window.removeEventListener("keydown", openContextHelp, true);
window.removeEventListener("mousedown", onPointerDown);
};
}, []);
function openHelp() {
setOpen(false);
setContextOpen(true);
}
return (
<div className="context-menu-wrap" ref={wrapRef}>
<button
className="titlebar-link"
onClick={() => setOpen(!open)}
onKeyDown={(event) => {
if (event.key === "F1") {
event.preventDefault();
event.stopPropagation();
openHelp();
}
}}
title="Help (F1)"
>
<HelpCircle size={17} /> Help
</button>
{open && (
<div className="dropdown-menu">
<button className="dropdown-item" onClick={openHelp}>
<HelpCircle size={16} /> Help <small>F1</small>
</button>
<hr />
<a className="dropdown-item" href="#" onClick={(e) => e.preventDefault()}><BookOpen size={16} /> User docs</a>
<a className="dropdown-item" href="#" onClick={(e) => e.preventDefault()}><BookOpen size={16} /> Admin docs</a>
<hr />
<a className="dropdown-item" href="https://git.add-ideas.de/add-ideas" target="_blank" rel="noreferrer"><GitBranch size={16} /> GitLab</a>
<button className="dropdown-item" onClick={() => { setAboutOpen(true); setOpen(false); }}><Info size={16} /> About</button>
</div>
)}
{contextOpen && <ContextHelpModal context={helpContext} onClose={() => setContextOpen(false)} />}
{aboutOpen && <AboutModal onClose={() => setAboutOpen(false)} />}
</div>
);
}
function ContextHelpModal({ context, onClose }: { context: HelpContext; onClose: () => void }) {
return (
<div className="overlay-backdrop" role="dialog" aria-modal="true" data-help-context={context.id}>
<div className="modal-panel">
<header className="modal-header">
<h2>Context help</h2>
<button className="modal-close" onClick={onClose}>×</button>
</header>
<div className="modal-body">
<div className="help-panel-section">
<h3>{context.title}</h3>
<p className="mono-small">Help context: {context.id}</p>
<p className="muted">This area is prepared for context-sensitive help. Future help content can use this context identifier, or the equivalent help query parameter <span className="kbd">{helpQueryForContext(context)}</span>, to open the right page or section.</p>
</div>
<div className="help-panel-section">
<h3>Next actions</h3>
<p className="muted">The first guided help content can cover campaign creation, review, attachment resolution and sending preparation.</p>
</div>
</div>
<footer className="modal-footer"><Button variant="primary" onClick={onClose}>Close</Button></footer>
</div>
</div>
);
}
function AboutModal({ onClose }: { onClose: () => void }) {
return (
<div className="overlay-backdrop" role="dialog" aria-modal="true">
<div className="modal-panel">
<header className="modal-header">
<h2>About MultiMailer</h2>
<button className="modal-close" onClick={onClose}>×</button>
</header>
<div className="modal-body">
<div className="about-logo" />
<p><strong>MultiMailer WebUI</strong></p>
<p className="muted">Version 0.1.0 early development build.</p>
<p>MultiMailer is a local-first / server-assisted campaign mailer for structured, personalized bulk messages with attachment resolution, review workflows and auditable sending.</p>
<p><a href="https://add-ideas.de" target="_blank" rel="noreferrer">add-ideas.de</a></p>
<p className="muted">License: project license pending / to be finalized. Backend components are currently development prototypes.</p>
</div>
<footer className="modal-footer"><Button variant="primary" onClick={onClose}>Close</Button></footer>
</div>
</div>
);
}