V-/Srcv0.1.0beta

// dialog

Dialog

A modal glass pane over a dimmed page.

// install
npx shadcn add @vsrc/dialog

Props

Only the vsrc surface is documented here. Everything else passes through to Radix Dialog.

// DialogContent

proptypedefaultnotes
glass"subtle" | "regular" | "heavy" | LiquidGlassOptions | falseOptics override for the modal pane. A preset name replaces the tuned values, an object merges over them, `false` disables refraction entirely.
showCloseButtonbooleantrueHide the corner close affordance when the footer carries the only valid exits.

Optics

Forwards `glass` to GlassSurface — engine defaults. The pane animates in once (animate-glass-in) and then holds still; the map is generated after mount, so the entrance never smears.

Accessibility

  • Radix modal contract: focus trap, aria-modal, labelled by DialogTitle, escape closes, focus returns to the trigger.
  • The close button carries aria-label="Close".

Source

The exact file the CLI copies into your project — you own it after install.

// registry/vsrc/ui/dialog.tsx
"use client";

import * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import type { GlassPreset, LiquidGlassOptions } from "vsrc/react";

import { GlassSurface } from "@/registry/vsrc/ui/glass-surface";
import { cn } from "@/lib/utils";

const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger;
const DialogClose = DialogPrimitive.Close;

function DialogOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
  return (
    <DialogPrimitive.Overlay
      data-slot="dialog-overlay"
      className={cn("animate-glass-in fixed inset-0 z-50 bg-background/70", className)}
      {...props}
    />
  );
}

function DialogContent({
  className,
  children,
  glass,
  showCloseButton = true,
  ...props
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
  glass?: LiquidGlassOptions | GlassPreset | false;
  /** The corner ✕. Off for surfaces that own their own chrome (e.g. the command palette). */
  showCloseButton?: boolean;
}) {
  return (
    <DialogPrimitive.Portal>
      <DialogOverlay />
      <GlassSurface asChild glass={glass}>
        <DialogPrimitive.Content
          data-slot="dialog-content"
          className={cn(
            "animate-glass-in fixed top-1/2 left-1/2 z-50 w-full max-w-md -translate-x-1/2 -translate-y-1/2",
            "flex flex-col gap-4 p-8 text-foreground outline-none",
            className,
          )}
          {...props}
        >
          {children}
          {showCloseButton && (
            <DialogPrimitive.Close
              aria-label="Close"
              className={cn(
                "absolute top-4 right-4 rounded-full p-1.5 text-muted-foreground transition-colors",
                "outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring",
              )}
            >
              <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" className="size-4">
                <path d="M4 4l8 8M12 4l-8 8" />
              </svg>
            </DialogPrimitive.Close>
          )}
        </DialogPrimitive.Content>
      </GlassSurface>
    </DialogPrimitive.Portal>
  );
}

function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
  return <div data-slot="dialog-header" className={cn("flex flex-col gap-1.5", className)} {...props} />;
}

function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
  return (
    <DialogPrimitive.Title
      data-slot="dialog-title"
      className={cn("font-display text-2xl leading-tight", className)}
      {...props}
    />
  );
}

function DialogDescription({
  className,
  ...props
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
  return (
    <DialogPrimitive.Description
      data-slot="dialog-description"
      className={cn("text-sm leading-relaxed text-muted-foreground", className)}
      {...props}
    />
  );
}

function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div data-slot="dialog-footer" className={cn("flex justify-end gap-3 pt-2", className)} {...props} />
  );
}

export {
  Dialog,
  DialogTrigger,
  DialogClose,
  DialogOverlay,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
};