Refresh action dialog chrome.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Developing-Gamer 2026-05-27 12:31:14 -07:00
parent b4286aa2d6
commit 3ab5db90ad

View File

@ -2,11 +2,14 @@
import type { Icon as PhosphorIcon } from "@phosphor-icons/react";
import { InfoIcon, WarningCircleIcon } from "@phosphor-icons/react";
import {
DesignButton,
DesignDialog,
type DesignDialogSize,
} from "@stackframe/dashboard-ui-components";
import React, { Suspense, useId } from "react";
import { Alert } from "./alert";
import { Button } from "./button";
import { Checkbox } from "./checkbox";
import { Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./dialog";
import { Label } from "./label";
import { Skeleton } from "./skeleton";
@ -22,12 +25,12 @@ export type ActionDialogProps = {
okButton?: boolean | Readonly<{
label?: string,
onClick?: () => Promise<"prevent-close" | undefined | void>,
props?: Partial<React.ComponentProps<typeof Button>>,
props?: Partial<React.ComponentProps<typeof DesignButton>>,
}>,
cancelButton?: boolean | Readonly<{
label?: string,
onClick?: () => Promise<"prevent-close" | undefined | void>,
props?: Partial<React.ComponentProps<typeof Button>>,
props?: Partial<React.ComponentProps<typeof DesignButton>>,
}>,
confirmText?: string,
children?: React.ReactNode,
@ -43,6 +46,7 @@ export type ActionDialogProps = {
* (border, ring, bg, shadow, padding, rounded, etc.).
*/
contentClassName?: string,
size?: DesignDialogSize,
};
export function ActionDialog(props: ActionDialogProps) {
@ -62,75 +66,43 @@ export function ActionDialog(props: ActionDialogProps) {
const blockDismissOnOutside = !!(props.preventClose || props.keepOpenOnOutsideInteraction);
const onOpenChange = (open: boolean) => {
if (!open) {
const onOpenChange = (nextOpen: boolean) => {
if (!nextOpen) {
props.onClose?.();
setConfirmed(false);
} else {
setInvalidationCount(invalidationCount + 1);
}
setOpenState(open);
props.onOpenChange?.(open);
setOpenState(nextOpen);
props.onOpenChange?.(nextOpen);
};
const trigger = props.trigger != null && React.isValidElement(props.trigger)
? props.trigger
: undefined;
return (
<Dialog open={open} onOpenChange={onOpenChange} key={invalidationCount}>
{props.trigger && <DialogTrigger asChild>
{props.trigger}
</DialogTrigger>}
<DialogContent
onInteractOutside={blockDismissOnOutside ? (e) => e.preventDefault() : undefined}
onPointerDownOutside={blockDismissOnOutside ? (e) => e.preventDefault() : undefined}
onFocusOutside={blockDismissOnOutside ? (e) => e.preventDefault() : undefined}
className={[
props.preventClose ? "[&>button]:hidden" : "",
props.contentClassName ?? "",
].filter(Boolean).join(" ")}
>
<DialogHeader>
<DialogTitle className="flex items-center">
<TitleIcon className="h-4 w-4 mr-2"/>
{title}
</DialogTitle>
<DialogDescription>
{props.description}
</DialogDescription>
</DialogHeader>
<DialogBody className="pb-2">
<div>
<Suspense fallback={
<>
<Skeleton className='h-9 w-2/3 self-center' />
<Skeleton className='h-3 w-16 mt-8' />
<Skeleton className='h-9 w-full mt-1' />
<Skeleton className='h-3 w-24 mt-2' />
<Skeleton className='h-9 w-full mt-1' />
<Skeleton className='h-9 w-full mt-6' />
</>
}>
{props.children}
</Suspense>
</div>
{props.confirmText && <Alert>
<Label className="flex gap-4 items-center">
<Checkbox id={confirmId} checked={confirmed} onCheckedChange={(v) => setConfirmed(!!v)}/>
{props.confirmText}
</Label>
</Alert>}
</DialogBody>
{anyButton && <DialogFooter className="gap-2">
<DesignDialog
key={invalidationCount}
open={open}
onOpenChange={onOpenChange}
trigger={trigger}
size={props.size ?? "lg"}
icon={TitleIcon}
title={title}
description={props.description}
hideTopCloseButton={props.preventClose}
className={props.contentClassName}
contentProps={{
onInteractOutside: blockDismissOnOutside ? (e) => e.preventDefault() : undefined,
onPointerDownOutside: blockDismissOnOutside ? (e) => e.preventDefault() : undefined,
onFocusOutside: blockDismissOnOutside ? (e) => e.preventDefault() : undefined,
}}
footer={anyButton ? (
<div className="flex w-full flex-col-reverse gap-2 sm:flex-row sm:justify-end">
{cancelButton && (
<Button
<DesignButton
variant="secondary"
color="neutral"
onClick={async () => {
if (await cancelButton.onClick?.() !== "prevent-close") {
onOpenChange(false);
@ -139,10 +111,10 @@ export function ActionDialog(props: ActionDialogProps) {
{...cancelButton.props}
>
{cancelButton.label ?? "Cancel"}
</Button>
</DesignButton>
)}
{okButton && (
<Button
<DesignButton
disabled={okButtonDisabled}
variant={props.danger ? "destructive" : "default"}
onClick={async () => {
@ -153,10 +125,35 @@ export function ActionDialog(props: ActionDialogProps) {
{...okButtonProps}
>
{okButton.label ?? "OK"}
</Button>
</DesignButton>
)}
</DialogFooter>}
</DialogContent>
</Dialog>
</div>
) : undefined}
>
<Suspense fallback={
<>
<Skeleton className='h-9 w-2/3 self-center' />
<Skeleton className='h-3 w-16 mt-8' />
<Skeleton className='h-9 w-full mt-1' />
<Skeleton className='h-3 w-24 mt-2' />
<Skeleton className='h-9 w-full mt-1' />
<Skeleton className='h-9 w-full mt-6' />
</>
}>
{props.children}
</Suspense>
{props.confirmText && (
<Alert className="mt-4">
<Label className="flex gap-4 items-center">
<Checkbox id={confirmId} checked={confirmed} onCheckedChange={(v) => setConfirmed(!!v)}/>
{props.confirmText}
</Label>
</Alert>
)}
</DesignDialog>
);
}