From 9868fc29d037a815128f832f0d15ac6c90984f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Thu, 12 Mar 2026 10:51:37 +0100 Subject: [PATCH 1/2] add confirm action modal --- .../pages/PlaygroundPage/PlaygroundPage.tsx | 25 +++++ web/src/routes/_authorized.tsx | 2 + .../ConfirmActionModal/ConfirmActionModal.tsx | 100 ++++++++++++++++++ .../modals/ConfirmActionModal/style.scss | 25 +++++ .../shared/hooks/modalControls/modalTypes.ts | 6 ++ web/src/shared/hooks/modalControls/types.ts | 15 +++ 6 files changed, 173 insertions(+) create mode 100644 web/src/shared/components/modals/ConfirmActionModal/ConfirmActionModal.tsx create mode 100644 web/src/shared/components/modals/ConfirmActionModal/style.scss diff --git a/web/src/pages/PlaygroundPage/PlaygroundPage.tsx b/web/src/pages/PlaygroundPage/PlaygroundPage.tsx index fcc148e4ef..aeb4560c8c 100644 --- a/web/src/pages/PlaygroundPage/PlaygroundPage.tsx +++ b/web/src/pages/PlaygroundPage/PlaygroundPage.tsx @@ -47,12 +47,37 @@ import { formChangeLogic } from '../../shared/formLogic'; import { openModal } from '../../shared/hooks/modalControls/modalsSubjects'; import { ModalName } from '../../shared/hooks/modalControls/modalTypes'; import { getLicenseInfoQueryOptions } from '../../shared/query'; +import { delay } from '../../shared/utils/delay'; import { FoldableRadioSection } from '../FoldableRadioSection/FoldableRadioSection'; import testIconSrc from './assets/actionable-test1.png'; export const PlaygroundPage = () => { return (
+ +
+ + + ); +}; diff --git a/web/src/shared/components/modals/ConfirmActionModal/style.scss b/web/src/shared/components/modals/ConfirmActionModal/style.scss new file mode 100644 index 0000000000..d8aa7ee77f --- /dev/null +++ b/web/src/shared/components/modals/ConfirmActionModal/style.scss @@ -0,0 +1,25 @@ +#action-modal .markdown-render { + display: flex; + flex-flow: column; + row-gap: var(--spacing-sm); + + p, + span, + ul, + li { + font: var(--t-body-sm-400); + color: var(--fg-default); + } + + ul { + margin-left: 0; + + li { + margin-left: var(--spacing-md); + + &:not(:last-child) { + margin-bottom: var(--spacing-sm); + } + } + } +} diff --git a/web/src/shared/hooks/modalControls/modalTypes.ts b/web/src/shared/hooks/modalControls/modalTypes.ts index 9d9122314d..b52673c342 100644 --- a/web/src/shared/hooks/modalControls/modalTypes.ts +++ b/web/src/shared/hooks/modalControls/modalTypes.ts @@ -11,6 +11,7 @@ import type { OpenCEGroupModal, OpenCEOpenIdClientModal, OpenCEWebhookModal, + OpenConfirmActionModal, OpenDeleteAliasDestinationBlockedModal, OpenDeleteAliasDestinationConfirmModal, OpenDeleteGatewayModal, @@ -74,6 +75,7 @@ export const ModalName = { AddNewDevice: 'addNewDevice', AssignUserIP: 'assignUserIP', AssignUserDeviceIP: 'assignUserDeviceIP', + ConfirmAction: 'confirmAction', } as const; export type ModalNameValue = (typeof ModalName)[keyof typeof ModalName]; @@ -239,6 +241,10 @@ const modalOpenArgsSchema = z.discriminatedUnion('name', [ name: z.literal(ModalName.AssignUserDeviceIP), data: z.custom(), }), + z.object({ + name: z.literal(ModalName.ConfirmAction), + data: z.custom(), + }), ]); export type ModalOpenEvent = z.infer; diff --git a/web/src/shared/hooks/modalControls/types.ts b/web/src/shared/hooks/modalControls/types.ts index a08d495163..beadff12f5 100644 --- a/web/src/shared/hooks/modalControls/types.ts +++ b/web/src/shared/hooks/modalControls/types.ts @@ -1,3 +1,5 @@ +import type { QueryKey } from '@tanstack/react-query'; +import type { HTMLProps } from 'react'; import type { AvailableLocationIpResponse, Device, @@ -13,6 +15,19 @@ import type { User, Webhook, } from '../../api/types'; +import type { ButtonProps } from '../../defguard-ui/components/Button/types'; + +export interface OpenConfirmActionModal { + title: string; + contentMd: string; + actionPromise: () => Promise; + invalidateKeys?: QueryKey[]; + cancelProps?: ButtonProps; + submitProps?: ButtonProps; + contentContainerProps?: HTMLProps; + onSuccess?: () => void; + onError?: () => void; +} export interface OpenEditDeviceModal { device: Device; From aa02cad0034a974113bbffb74a82a43049a9df50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Thu, 12 Mar 2026 10:56:05 +0100 Subject: [PATCH 2/2] Update ConfirmActionModal.tsx --- .../components/modals/ConfirmActionModal/ConfirmActionModal.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/web/src/shared/components/modals/ConfirmActionModal/ConfirmActionModal.tsx b/web/src/shared/components/modals/ConfirmActionModal/ConfirmActionModal.tsx index bfc735639b..eb3aaeaf76 100644 --- a/web/src/shared/components/modals/ConfirmActionModal/ConfirmActionModal.tsx +++ b/web/src/shared/components/modals/ConfirmActionModal/ConfirmActionModal.tsx @@ -1,3 +1,4 @@ +import './style.scss'; import { useMutation } from '@tanstack/react-query'; import { useEffect, useState } from 'react'; import { m } from '../../../../paraglide/messages';