"use client"
import { useRender } from "@base-ui/react/use-render"
import { createContext, use } from "react"
import type { ComponentProps, CSSProperties } from "react"
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"
import * as stylex from "@stylexjs/stylex"
import type { StyleXStyles } from "@stylexjs/stylex"
import { clsx } from "clsx"
import { Button } from "@/components/ui/button"
import { stateStyles } from "@/lib/state-styles"
import { breakpoints } from "@/theme/breakpoints.stylex"
import { states } from "@/theme/states"
import {
color,
duration,
ease,
layer,
leading,
radius,
shadow,
space,
text,
} from "@/theme/tokens.stylex"
const styles = stylex.create({
overlayHidden: { opacity: 0 },
hidden: { opacity: 0, transform: "scale(0.95)" },
overlay: {
position: "fixed",
inset: 0,
zIndex: layer.popup,
backgroundColor: color.overlay,
backdropFilter: "blur(2px)",
transitionProperty: "opacity",
transitionDuration: {
default: duration.modal,
"@media (prefers-reduced-motion: reduce)": "0s",
},
transitionTimingFunction: ease.standard,
},
viewport: {
position: "fixed",
inset: 0,
zIndex: layer.popup,
display: "grid",
alignItems: "safe center",
justifyItems: "center",
overflow: "auto",
padding: space.s4,
},
content: {
display: "grid",
gap: space.s4,
width: "100%",
borderRadius: radius.xl,
padding: space.s5,
boxShadow: shadow.popupLifted,
fontSize: text.sm,
lineHeight: leading.sm,
transitionProperty: "opacity, transform",
transitionDuration: {
default: duration.modal,
"@media (prefers-reduced-motion: reduce)": "0s",
},
transitionTimingFunction: ease.standard,
},
header: { display: "grid", rowGap: space.s1_5, justifyItems: "center", textAlign: "center" },
headerInline: {
gridTemplateColumns: { default: null, [breakpoints.md]: "auto 1fr" },
justifyItems: { default: "center", [breakpoints.md]: "start" },
textAlign: { default: "center", [breakpoints.md]: "start" },
},
textColumn: { gridColumnStart: { default: null, [breakpoints.md]: 2 } },
media: {
width: space.s10,
height: space.s10,
marginBlockEnd: space.s2,
"--carbon-icon-size": space.s6,
},
mediaInline: {
gridColumnStart: { default: null, [breakpoints.md]: 1 },
gridRowStart: { default: null, [breakpoints.md]: "1" },
gridRowEnd: { default: null, [breakpoints.md]: "span 2" },
marginBlockEnd: { default: space.s2, [breakpoints.md]: 0 },
marginInlineEnd: { default: null, [breakpoints.md]: space.s4 },
},
title: { fontSize: text.base, lineHeight: leading.base, fontWeight: 500 },
description: { color: color.mutedForeground, textWrap: "balance" },
footer: {
display: "flex",
flexDirection: { default: "column-reverse", [breakpoints.md]: "row" },
justifyContent: { default: null, [breakpoints.md]: "flex-end" },
gap: space.s2,
marginInline: `calc(-1 * ${space.s5})`,
marginBlockStart: `calc(${space.s1} - ${radius.xl})`,
marginBlockEnd: `calc(-1 * ${space.s5})`,
borderEndStartRadius: radius.xl,
borderEndEndRadius: radius.xl,
},
footerSplit: { display: "grid", gridTemplateColumns: "1fr 1fr" },
})
const sizes = stylex.create({
default: { maxWidth: { default: "20rem", [breakpoints.md]: "24rem" } },
sm: { maxWidth: "20rem" },
})
const alertDialogStyles = { surface: states.popupSurface, base: styles.content, sizes }
type AlertDialogSize = keyof typeof sizes
const AlertDialogContext = createContext<{ size: AlertDialogSize }>({ size: "default" })
type Overrides = { xstyle?: StyleXStyles; className?: string }
type StateOverrides = Overrides & { style?: CSSProperties }
function AlertDialog<Payload>(props: AlertDialogPrimitive.Root.Props<Payload>) {
return <AlertDialogPrimitive.Root {...props} />
}
function AlertDialogTrigger(props: AlertDialogPrimitive.Trigger.Props) {
return <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
}
function AlertDialogPortal(props: AlertDialogPrimitive.Portal.Props) {
return <AlertDialogPrimitive.Portal {...props} />
}
type AlertDialogOverlayProps = Omit<AlertDialogPrimitive.Backdrop.Props, "className" | "style"> &
StateOverrides
function AlertDialogOverlay({ xstyle, className, style, ...props }: AlertDialogOverlayProps) {
return (
<AlertDialogPrimitive.Backdrop
data-slot="alert-dialog-overlay"
{...props}
{...stateStyles(
(state) => [
styles.overlay,
(state.transitionStatus === "starting" || state.transitionStatus === "ending") &&
styles.overlayHidden,
xstyle,
],
{ className, style },
)}
/>
)
}
type AlertDialogViewportProps = Omit<AlertDialogPrimitive.Viewport.Props, "className"> & Overrides
function AlertDialogViewport({ xstyle, className, ...props }: AlertDialogViewportProps) {
const sx = stylex.props(styles.viewport, xstyle)
return (
<AlertDialogPrimitive.Viewport
data-slot="alert-dialog-viewport"
{...sx}
{...props}
className={clsx(sx.className, className)}
/>
)
}
type AlertDialogContentProps = Omit<AlertDialogPrimitive.Popup.Props, "className" | "style"> &
StateOverrides & {
size?: AlertDialogSize
overlayProps?: AlertDialogOverlayProps
viewportProps?: AlertDialogViewportProps
}
function AlertDialogContent({
xstyle,
className,
style,
size = "default",
overlayProps,
viewportProps,
children,
...props
}: AlertDialogContentProps) {
return (
<AlertDialogPortal>
<AlertDialogOverlay {...overlayProps} />
<AlertDialogViewport {...viewportProps}>
<AlertDialogPrimitive.Popup
data-slot="alert-dialog-content"
data-size={size}
{...props}
{...stateStyles(
(state) => [
states.popupSurface,
styles.content,
sizes[size],
(state.transitionStatus === "starting" || state.transitionStatus === "ending") &&
styles.hidden,
xstyle,
],
{ className, style },
)}
>
<AlertDialogContext value={{ size }}>{children}</AlertDialogContext>
</AlertDialogPrimitive.Popup>
</AlertDialogViewport>
</AlertDialogPortal>
)
}
function AlertDialogHeader({
render,
ref,
style,
xstyle,
className,
...props
}: useRender.ComponentProps<"div"> & Overrides) {
const { size } = use(AlertDialogContext)
const sx = stylex.props(styles.header, size === "default" && styles.headerInline, xstyle)
return useRender({
defaultTagName: "div",
render,
ref,
props: {
"data-slot": "alert-dialog-header",
...sx,
...props,
className: clsx(sx.className, className),
style: { ...sx.style, ...style },
},
})
}
function AlertDialogMedia({
render,
ref,
style,
xstyle,
className,
...props
}: useRender.ComponentProps<"div"> & Overrides) {
const { size } = use(AlertDialogContext)
const sx = stylex.props(
states.iconTile,
styles.media,
size === "default" && styles.mediaInline,
xstyle,
)
return useRender({
defaultTagName: "div",
render,
ref,
props: {
"data-slot": "alert-dialog-media",
...sx,
...props,
className: clsx("carbon-icons", sx.className, className),
style: { ...sx.style, ...style },
},
})
}
function AlertDialogTitle({
xstyle,
className,
...props
}: AlertDialogPrimitive.Title.Props & Overrides) {
const { size } = use(AlertDialogContext)
const sx = stylex.props(styles.title, size === "default" && styles.textColumn, xstyle)
return (
<AlertDialogPrimitive.Title
data-slot="alert-dialog-title"
{...sx}
{...props}
className={clsx(sx.className, className)}
/>
)
}
function AlertDialogDescription({
xstyle,
className,
...props
}: AlertDialogPrimitive.Description.Props & Overrides) {
const { size } = use(AlertDialogContext)
const sx = stylex.props(styles.description, size === "default" && styles.textColumn, xstyle)
return (
<AlertDialogPrimitive.Description
data-slot="alert-dialog-description"
{...sx}
{...props}
className={clsx(sx.className, className)}
/>
)
}
function AlertDialogFooter({
render,
ref,
style,
xstyle,
className,
...props
}: useRender.ComponentProps<"div"> & Overrides) {
const { size } = use(AlertDialogContext)
const sx = stylex.props(
states.trayFooter,
styles.footer,
size === "sm" && styles.footerSplit,
xstyle,
)
return useRender({
defaultTagName: "div",
render,
ref,
props: {
"data-slot": "alert-dialog-footer",
...sx,
...props,
className: clsx(sx.className, className),
style: { ...sx.style, ...style },
},
})
}
function AlertDialogAction(props: ComponentProps<typeof Button>) {
return <Button data-slot="alert-dialog-action" {...props} />
}
type AlertDialogCancelProps = AlertDialogPrimitive.Close.Props &
Pick<ComponentProps<typeof Button>, "variant" | "size" | "xstyle">
function AlertDialogCancel({
variant = "secondary",
size,
xstyle,
...props
}: AlertDialogCancelProps) {
return (
<AlertDialogPrimitive.Close
data-slot="alert-dialog-cancel"
render={<Button variant={variant} size={size} xstyle={xstyle} />}
{...props}
/>
)
}
export {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogMedia,
AlertDialogOverlay,
AlertDialogPortal,
alertDialogStyles,
AlertDialogTitle,
AlertDialogTrigger,
AlertDialogViewport,
type AlertDialogSize,
}