Files
excalidraw-box/src/client/components/DrawingSidebar.tsx

111 lines
3.3 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 { type DrawingMeta } from "../../core/shared";
type DrawingSidebarProps = {
open: boolean;
drawings: DrawingMeta[];
activeId: string | null;
activeTitle: string;
onClose: () => void;
onCreate: () => void;
onSelect: (drawingId: string) => void;
onDelete: (drawingId: string) => void;
onTitleChange: (title: string) => void;
onTitleSubmit: () => void;
};
function DrawerIcon() {
return (
<svg viewBox="0 0 24 24" aria-hidden="true">
<rect x="3.5" y="5" width="17" height="14" rx="2.5" fill="none" stroke="currentColor" strokeWidth="1.8" />
<path d="M9 5v14" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
<path d="M5.75 9h1.5M5.75 12h1.5M5.75 15h1.5" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
</svg>
);
}
export function DrawingsToggle({ onClick }: { onClick: () => void }) {
return (
<button
type="button"
className="secondary-button app-actions-toggle"
onClick={onClick}
aria-label="Open drawings"
>
<DrawerIcon />
<span className="sr-only">Open drawings</span>
</button>
);
}
export function DrawingSidebar({
open,
drawings,
activeId,
activeTitle,
onClose,
onCreate,
onSelect,
onDelete,
onTitleChange,
onTitleSubmit,
}: DrawingSidebarProps) {
return (
<>
<div
className={open ? "sidebar-backdrop sidebar-backdrop-open" : "sidebar-backdrop"}
onClick={onClose}
aria-hidden={!open}
/>
<aside className={open ? "sidebar sidebar-open" : "sidebar"} aria-hidden={!open}>
<div className="sidebar-header">
<h1>excali-box</h1>
<div className="sidebar-actions">
<button type="button" className="primary-button" onClick={onCreate}>
New
</button>
<button type="button" className="icon-button" onClick={onClose} aria-label="Close drawings">
×
</button>
</div>
</div>
<div className="drawing-list">
{drawings.map((drawing) => (
<div
key={drawing.id}
className={drawing.id === activeId ? "drawing-item drawing-item-active" : "drawing-item"}
>
{drawing.id === activeId ? (
<div className="drawing-link">
<input
className="title-input"
value={activeTitle}
onChange={(event) => onTitleChange(event.target.value)}
onBlur={onTitleSubmit}
onKeyDown={(event) => {
if (event.key === "Enter") {
event.currentTarget.blur();
}
}}
/>
</div>
) : (
<button type="button" className="drawing-link" onClick={() => onSelect(drawing.id)}>
<span className="drawing-title">{drawing.title}</span>
</button>
)}
<button
type="button"
className="icon-button"
onClick={() => onDelete(drawing.id)}
aria-label={`Delete ${drawing.title}`}
>
×
</button>
</div>
))}
</div>
</aside>
</>
);
}