rename web/ to admin/, along with the web-named build and cli identifiers

This commit is contained in:
2026-08-16 00:17:58 +02:00
parent 5b3d1cd65c
commit 1e97c80f6b
136 changed files with 196 additions and 196 deletions
+113
View File
@@ -0,0 +1,113 @@
/**
* The destructive-action confirmation (milestone 23, ruling 5), which replaces
* every `window.confirm` call in the app.
*
* `role="alertdialog"` rather than `dialog`: the message is the reason the
* dialog exists, so it is announced with the dialog instead of after it. The
* overlay is deliberately not dismissable — a delete needs an explicit answer,
* and a stray outside click is not one. Escape still cancels.
*/
import * as stylex from "@stylexjs/stylex";
import { Dialog as AriaDialog, Heading, Modal, ModalOverlay } from "react-aria-components";
import { colors } from "./tokens.stylex";
import { styles as shared } from "./styles";
interface Props {
isOpen: boolean;
title: string;
/** The full sentence the operator reads before confirming; names the entity. */
message: string;
confirmLabel: string;
onConfirm: () => void;
onCancel: () => void;
}
const styles = stylex.create({
overlay: {
position: "fixed",
inset: 0,
zIndex: 50,
display: "flex",
alignItems: "center",
justifyContent: "center",
padding: "1rem",
backgroundColor: "rgba(0, 0, 0, 0.4)",
},
panel: {
width: "100%",
maxWidth: "26rem",
borderRadius: "0.5rem",
borderWidth: 1,
borderStyle: "solid",
borderColor: colors.dangerBorder,
backgroundColor: colors.surfaceRaised,
color: colors.text,
padding: "1.5rem",
boxShadow: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
},
body: {
outlineStyle: "none",
},
title: {
fontSize: "1.125rem",
lineHeight: "1.75rem",
fontWeight: 600,
},
message: {
marginTop: "0.5rem",
fontSize: "0.875rem",
lineHeight: "1.25rem",
color: colors.textMuted,
},
actions: {
display: "flex",
justifyContent: "flex-end",
gap: "0.5rem",
marginTop: "1.5rem",
},
dangerButton: {
borderRadius: "0.25rem",
borderStyle: "none",
backgroundColor: colors.danger,
color: colors.primaryText,
paddingInline: "0.75rem",
paddingBlock: "0.375rem",
fontSize: "0.875rem",
lineHeight: "1.25rem",
fontWeight: 500,
},
});
export default function ConfirmDialog({ isOpen, title, message, confirmLabel, onConfirm, onCancel }: Props) {
return (
<ModalOverlay
isOpen={isOpen}
onOpenChange={(open) => {
if (!open) onCancel();
}}
className={() => stylex.props(styles.overlay).className ?? ""}
>
<Modal className={() => stylex.props(styles.panel).className ?? ""}>
<AriaDialog role="alertdialog" {...stylex.props(styles.body)}>
<Heading slot="title" level={2} {...stylex.props(styles.title)}>
{title}
</Heading>
<p {...stylex.props(styles.message)}>{message}</p>
<div {...stylex.props(styles.actions)}>
<button type="button" onClick={onCancel} {...stylex.props(shared.button, shared.focusRing)}>
Cancel
</button>
<button
type="button"
onClick={onConfirm}
{...stylex.props(styles.dangerButton, shared.focusRing)}
>
{confirmLabel}
</button>
</div>
</AriaDialog>
</Modal>
</ModalOverlay>
);
}