a55555983b
- FAVORITES section at the top collects pinned workspaces (removed from their group listing); a star toggle on each row pins/unpins via setWorkspaceMeta. - Drag-to-reorder within a section using raw pointer events (HTML5 DnD is unreliable in the macOS WKWebView), with a drop-line indicator; on drop the section's `order` is reassigned sequentially and persisted. Cross-section drops are ignored (group membership unchanged). - Trash icon on row hover opens a ConfirmDelete modal that shows the live terminal count and warns before terminating them, then calls close_workspace and re-points the active workspace. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
64 lines
2.6 KiB
TypeScript
64 lines
2.6 KiB
TypeScript
import { useEffect, useRef } from "react";
|
|
import { COLORS, FONT } from "./theme";
|
|
|
|
/** Confirmation modal for deleting a workspace. Warns when live terminals
|
|
* would be killed, but still allows the delete (per product decision). */
|
|
export function ConfirmDelete({
|
|
name,
|
|
activeCount,
|
|
onConfirm,
|
|
onCancel,
|
|
}: {
|
|
name: string;
|
|
activeCount: number;
|
|
onConfirm: () => void;
|
|
onCancel: () => void;
|
|
}) {
|
|
const confirmRef = useRef<HTMLButtonElement>(null);
|
|
useEffect(() => { confirmRef.current?.focus(); }, []);
|
|
|
|
function onKeyDown(e: React.KeyboardEvent) {
|
|
e.stopPropagation();
|
|
if (e.key === "Escape") { e.preventDefault(); onCancel(); }
|
|
else if (e.key === "Enter") { e.preventDefault(); onConfirm(); }
|
|
}
|
|
|
|
return (
|
|
<div
|
|
onMouseDown={onCancel}
|
|
style={{ position: "fixed", inset: 0, zIndex: 2000, background: "#000A", display: "flex", alignItems: "center", justifyContent: "center" }}
|
|
>
|
|
<div
|
|
onMouseDown={(e) => e.stopPropagation()}
|
|
onKeyDown={onKeyDown}
|
|
style={{ width: 420, background: COLORS.bgApp, border: `1px solid ${COLORS.borderStrong}`, borderRadius: 14, padding: 24, color: COLORS.textPrimary, fontFamily: FONT.ui }}
|
|
>
|
|
<div style={{ fontWeight: 700, fontSize: 16, marginBottom: 12 }}>Delete workspace</div>
|
|
<div style={{ fontSize: 13, color: COLORS.textSecondary, lineHeight: 1.5 }}>
|
|
Delete <span style={{ color: COLORS.textPrimary, fontWeight: 600 }}>{name}</span>? This removes the workspace and its layout.
|
|
</div>
|
|
{activeCount > 0 && (
|
|
<div style={{ marginTop: 12, padding: "8px 10px", borderRadius: 8, background: "#2A1414", border: `1px solid ${COLORS.stError}`, color: COLORS.stError, fontSize: 12, fontWeight: 600 }}>
|
|
{activeCount} active terminal{activeCount === 1 ? "" : "s"} will be terminated.
|
|
</div>
|
|
)}
|
|
<div style={{ display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 20 }}>
|
|
<button
|
|
onClick={onCancel}
|
|
style={{ padding: "7px 14px", background: COLORS.bgElevated, color: COLORS.textPrimary, border: `1px solid ${COLORS.borderStrong}`, borderRadius: 7, fontSize: 13, fontFamily: FONT.ui }}
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
ref={confirmRef}
|
|
onClick={onConfirm}
|
|
style={{ padding: "7px 14px", background: COLORS.stError, color: "#fff", border: "none", borderRadius: 7, fontSize: 13, fontWeight: 600, fontFamily: FONT.ui }}
|
|
>
|
|
Delete
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|