Confirm

Confirm dialog for critical user actions.

import { Confirm } from 'ui-lab-components/confirm';
"use client";
 
import { Confirm } from 'ui-lab-components/confirm';
import { Flex } from 'ui-lab-components/flex';
import { toast, Toaster } from 'ui-lab-components/toast';
 
export default function Example() {
  return (
    <Flex justify-center w={120}>
      <Confirm mode="inline"
        severity="critical"
        labels={{
          trigger: "Delete",
          idle: { title: "Project Alpha", body: "12 files, 4 collaborators" },
          confirming: { title: "Are you sure?", body: "This action cannot be undone." },
          confirm: 'Delete',
          cancel: 'Cancel',
        }}
        onConfirm={() => {
          toast({ title: 'Deleted', variant: 'danger' });
        }}
      />
      <Toaster />
    </Flex>
  );
}
 

confirm/01-basic-confirm

A single button that swaps in place: Delete account, then Confirm, then Undo. No title or description.

Loading interactive preview
'use client';
 
import { useState } from 'react';
import { Icon } from 'ui-lab-components/icon';
import { Button } from 'ui-lab-components/button';
import { Flex } from 'ui-lab-components/flex';
 
type Step = 'idle' | 'confirming' | 'deleted';
 
const steps: Record<Step, { label: string; icon: React.ReactNode; next: Step }> = {
  idle: { label: 'Delete account', icon: <Icon id="trash" size="1em" />, next: 'confirming' },
  confirming: { label: 'Confirm', icon: <Icon id="check" size="1em" />, next: 'deleted' },
  deleted: { label: 'Undo', icon: <Icon id="restart" size="1em" />, next: 'idle' },
};
 
export default function Example() {
  const [step, setStep] = useState<Step>('idle');
  const { label, icon, next } = steps[step];
 
  return (
    <Flex justify-center w={160}>
      <Button icon={{ left: icon }} onPress={() => setStep(next)}>
        {label}
      </Button>
    </Flex>
  );
}
 

confirm/02-inline-row

A settings-row delete action. The row label stays put via labels.idle, and the warning copy only appears once the user commits, via labels.confirming.

Loading interactive preview
import { Confirm } from 'ui-lab-components/confirm';
import { Flex } from 'ui-lab-components/flex';
import { toast, Toaster } from 'ui-lab-components/toast';
 
export default function Example() {
  return (
    <>
      <Flex direction="column" gap="lg" className="p-5">
        <Confirm
          labels={{
            trigger: 'Remove',
            idle: {
              title: 'Two-factor authentication',
              body: 'Adds a second step when signing in.',
            },
            confirming: {
              title: 'Turn off two-factor authentication?',
              body: 'Your account will only be protected by your password.',
            },
            confirm: 'Turn off',
            cancel: 'Keep it on',
          }}
          severity="critical"
          onConfirm={() => {
            toast({ title: '2FA disabled', variant: 'warning' });
          }}
        />
 
        <div className="h-px bg-background-700/40" aria-hidden="true" />
 
        <Confirm
          labels={{
            trigger: 'Delete',
            confirming: {
              title: 'Delete this project?',
              body: 'All files and history are removed immediately.',
            },
            confirm: 'Delete',
            cancel: 'Cancel',
          }}
          severity="critical"
          onConfirm={() => {
            toast({ title: 'Project deleted', variant: 'danger' });
          }}
        />
      </Flex>
      <Toaster />
    </>
  );
}
 

confirm/03-dialog-mode

Same labels API as inline mode, switched to a modal for higher-stakes confirmations. labels.idle labels the row behind the trigger; labels.confirming becomes the dialog heading and body.

Loading interactive preview
import { Confirm } from 'ui-lab-components/confirm';
import { Flex } from 'ui-lab-components/flex';
import { toast, Toaster } from 'ui-lab-components/toast';
 
export default function Example() {
  return (
    <>
      <Flex align-center justify-between gap="xl" className="rounded-sm p-5">
        <Flex direction="column" gap="xs">
          <span className="text-sm font-medium text-foreground-100">acme-production</span>
          <span className="text-xs text-foreground-300">Deployed 3 hours ago</span>
        </Flex>
 
        <Confirm
          mode="dialog"
          labels={{
            trigger: 'Delete environment',
            confirming: {
              title: 'Delete acme-production?',
              body: 'This permanently removes the environment, its secrets, and deploy history.',
            },
            confirm: 'Delete environment',
            cancel: 'Cancel',
          }}
          destructive-action-warning="This action cannot be undone."
          requires-reason
          confirm-text="acme-production"
          severity="critical"
          onConfirm={() => {
            toast({ title: 'Environment deleted', description: 'acme-production is gone.', variant: 'danger' });
          }}
        />
      </Flex>
      <Toaster />
    </>
  );
}
 

confirm/04-confirm-with-details

A confirmation panel with a title and description explaining the consequences before the user commits.

Loading interactive preview
import { Flex } from 'ui-lab-components';
import { Confirm } from 'ui-lab-components/confirm';
import { toast, Toaster } from 'ui-lab-components/toast';
 
export default function Example() {
  return (
    <Flex justify-center w={160}>
      <Confirm
        labels={{
          trigger: 'Delete Account',
          confirming: {
            title: 'Are you sure?',
            body: 'This action cannot be undone. All your data will be permanently deleted.',
          },
          confirm: 'Delete',
          cancel: 'Cancel',
        }}
        severity="critical"
        onConfirm={() => {
          toast({ title: 'Account deleted', variant: 'danger' });
        }}
      />
      <Toaster />
    </Flex>
  );
}