Skip to content

Commit 85fd2e7

Browse files
michaelokolokof
andauthored
feat: add confirmation dialog when deleting a page (#5441)
## Description This pull request introduces a new feature that adds a confirmation dialog when deleting a page, helping prevent accidental deletions. Related issue: [#5418](#5418) ## Changes 1. Updated `page-settings.tsx` to include a new `DeleteConfirmationDialog` component. 2. The dialog prompts users to confirm or cancel before a page is deleted. 3. Enhances user safety and improves UX by preventing unintended deletions. (See the image below for a preview of the dialog.) ## How to Test 1. Open any project. 2. Add a new page. 3. Attempt to delete the page, the confirmation dialog should appear instead of immediately deleting. 4. Clicking Delete should remove the page; clicking Cancel should close the dialog without deleting. <img width="1283" height="855" alt="image" src="https://github.com/user-attachments/assets/d63afe08-75f4-4a53-9e17-50aed4f1330a" /> --------- Co-authored-by: Oleg Isonen <[email protected]>
1 parent 2752bcc commit 85fd2e7

File tree

1 file changed

+90
-16
lines changed

1 file changed

+90
-16
lines changed

apps/builder/app/builder/features/pages/page-settings.tsx

Lines changed: 90 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ import {
5757
TitleSuffixSpacer,
5858
FloatingPanelProvider,
5959
ProBadge,
60+
Dialog,
61+
DialogClose,
62+
DialogContent,
63+
DialogTitle,
6064
} from "@webstudio-is/design-system";
6165
import {
6266
ChevronsLeftIcon,
@@ -1477,6 +1481,9 @@ export const PageSettings = ({
14771481

14781482
const [unsavedValues, setUnsavedValues] = useState<Partial<Values>>({});
14791483

1484+
const [showDeleteConfirmation, setShowDeleteConfirmation] =
1485+
useState<boolean>(false);
1486+
14801487
const values: Values = {
14811488
...(page ? toFormValues(page, pages, isHomePage) : fieldDefaultValues),
14821489
...unsavedValues,
@@ -1532,6 +1539,10 @@ export const PageSettings = ({
15321539
updatePage(pageId, unsavedValues);
15331540
});
15341541

1542+
const handleRequestDelete = () => {
1543+
setShowDeleteConfirmation(true);
1544+
};
1545+
15351546
const hanldeDelete = () => {
15361547
updateWebstudioData((data) => {
15371548
deletePageMutable(pageId, data);
@@ -1544,27 +1555,90 @@ export const PageSettings = ({
15441555
}
15451556

15461557
return (
1547-
<PageSettingsView
1548-
onClose={onClose}
1549-
onDelete={values.isHomePage === false ? hanldeDelete : undefined}
1550-
onDuplicate={() => {
1551-
const newPageId = duplicatePage(pageId);
1552-
if (newPageId !== undefined) {
1553-
// In `canvas.tsx`, within `subscribeStyles`, we use `requestAnimationFrame` (RAF) for style recalculation.
1554-
// After `duplicatePage`, styles are not yet recalculated.
1555-
// To ensure they are properly updated, we use double RAF.
1556-
requestAnimationFrame(() => {
1557-
// At this tick styles are updating
1558+
<>
1559+
<PageSettingsView
1560+
onClose={onClose}
1561+
onDelete={values.isHomePage === false ? handleRequestDelete : undefined}
1562+
onDuplicate={() => {
1563+
const newPageId = duplicatePage(pageId);
1564+
if (newPageId !== undefined) {
1565+
// In `canvas.tsx`, within `subscribeStyles`, we use `requestAnimationFrame` (RAF) for style recalculation.
1566+
// After `duplicatePage`, styles are not yet recalculated.
1567+
// To ensure they are properly updated, we use double RAF.
15581568
requestAnimationFrame(() => {
1559-
// At this tick styles are updated
1560-
onDuplicate(newPageId);
1569+
// At this tick styles are updating
1570+
requestAnimationFrame(() => {
1571+
// At this tick styles are updated
1572+
onDuplicate(newPageId);
1573+
});
15611574
});
1562-
});
1575+
}
1576+
}}
1577+
>
1578+
<FormFields errors={errors} values={values} onChange={handleChange} />
1579+
</PageSettingsView>
1580+
{showDeleteConfirmation && page && (
1581+
<DeleteConfirmationDialog
1582+
page={page}
1583+
onClose={() => {
1584+
setShowDeleteConfirmation(false);
1585+
}}
1586+
onConfirm={() => {
1587+
setShowDeleteConfirmation(false);
1588+
hanldeDelete();
1589+
}}
1590+
/>
1591+
)}
1592+
</>
1593+
);
1594+
};
1595+
1596+
type DeleteConfirmationDialogProps = {
1597+
onClose: () => void;
1598+
onConfirm: () => void;
1599+
page: Page;
1600+
};
1601+
1602+
const DeleteConfirmationDialog = ({
1603+
onClose,
1604+
onConfirm,
1605+
page,
1606+
}: DeleteConfirmationDialogProps) => {
1607+
return (
1608+
<Dialog
1609+
open
1610+
onOpenChange={(isOpen) => {
1611+
if (isOpen === false) {
1612+
onClose();
15631613
}
15641614
}}
15651615
>
1566-
<FormFields errors={errors} values={values} onChange={handleChange} />
1567-
</PageSettingsView>
1616+
<DialogContent>
1617+
<Flex gap="3" direction="column" css={{ padding: theme.panel.padding }}>
1618+
<Text>{`Are you sure you want to delete "${page.name}"?`}</Text>
1619+
<Text>
1620+
You can undo it even if you delete the page as long as you don't
1621+
reload.
1622+
</Text>
1623+
<Flex direction="rowReverse" gap="2">
1624+
<DialogClose>
1625+
<Button
1626+
color="destructive"
1627+
onClick={() => {
1628+
onConfirm();
1629+
}}
1630+
>
1631+
Delete Page
1632+
</Button>
1633+
</DialogClose>
1634+
<DialogClose>
1635+
<Button color="ghost">Cancel</Button>
1636+
</DialogClose>
1637+
</Flex>
1638+
</Flex>
1639+
<DialogTitle>Delete Page</DialogTitle>
1640+
</DialogContent>
1641+
</Dialog>
15681642
);
15691643
};
15701644

0 commit comments

Comments
 (0)