NUIv3.0.7

Dialog

A composable, accessible Dialog component for modern React applications.

tsx
import { Dialog } from '@nofinite/nui';

Interactive Preview


Global infrastructure component responsible for orchestrating imperative dialogs and toast bridging across the application.

[!TIP] Programmatic API (nui.*): Looking for nui.confirm(), nui.alert(), or zero-JSX imperative modals? See the dedicated Programmatic API (nui.*) documentation.


Usage

Provider Setup

Place once at application root.

tsx
import { DialogProvider } from '@nofinite/nui';

export default function RootLayout({ children }) {
  return (
    <>
      {children}
      <DialogProvider />
    </>
  );
}

Confirm dialog (destructive flow)

tsx
'use client';
import { nui, Button } from '@nofinite/nui';

const handleDelete = async () => {
  const isConfirmed = await nui.confirm(
    'Are you absolutely sure? All data will be permanently removed.',
    {
      title: 'Delete Account',
      confirmText: 'Yes, Delete',
      isDanger: true,
    }
  );

  if (!isConfirmed) {
    nui.toast('Action cancelled.');
    return;
  }

  nui.success('Account deleted successfully.');
};

<Button variant="danger" onClick={handleDelete}>
  Delete Account
</Button>;

Alert dialog

tsx
await nui.alert('You must accept the terms before proceeding.', {
  title: 'Terms of Service',
  confirmText: 'I Understand',
});

Toast bridge usage

tsx
nui.warn('Saving changes...', { duration: 2000 });
nui.success('Settings saved successfully!');
nui.error('Operation failed');

Behavior

  • Uses external store subscription via useSyncExternalStore
  • Dialog resolves promise through resolve callback
  • Automatically renders Modal
  • Bridges toast events from emitter to ToastProvider
  • Confirm dialogs disable click-outside close
  • Alert dialogs auto-resolve true on modal close
  • Supports destructive styling via isDanger


Dialog Types

TypeDescription
alertInformational dialog with single confirmation
confirmDecision dialog with confirm + cancel
destructive confirmConfirm dialog with danger styling

States

  • Closed
  • Open (alert)
  • Open (confirm)
  • Resolving promise
  • Toast dispatch state

Keyboard Interaction

KeyBehavior
TabFocus cycles within modal
Shift + TabReverse focus trap
EnterActivates primary action
EscapeCloses alert dialog (confirm disabled click outside)

Accessibility

  • Uses Modal focus trap for keyboard navigation
  • Semantic dialog structure via Modal
  • Prevents accidental dismissal for confirm flows
  • Ensures destructive intent visibility via danger styling
  • Toast announcements handled by ToastProvider
  • Promise-based resolution prevents accidental state mismatch

Architecture Notes

External store pattern

The provider subscribes to a centralized store enabling:

  • framework-agnostic API
  • imperative dialog invocation
  • decoupled rendering
  • cross-tree dialog orchestration

Promise resolution pattern

ts
const result = await nui.confirm(...)

Benefits:

  • Linear async control flow
  • Eliminates callback nesting
  • Simplifies destructive flow logic
  • Enables transactional UX

Toast bridge pattern

Flow:

  1. Developer calls nui.success() in vanilla JS
  2. toastEmitter publishes event
  3. DialogProvider subscribes
  4. Event forwarded to ToastProvider show()

This enables headless toast invocation with React rendering.



Best Practices

Do

  • Mount provider once globally
  • Use confirm dialogs for destructive operations
  • Use alert dialogs for acknowledgement flows
  • Use promise resolution for transactional actions
  • Combine confirm + toast for robust feedback loops

Don’t

  • Mount multiple providers
  • Use confirm dialogs for non-critical actions
  • Bypass toast bridge for imperative notifications
  • Trigger dialogs during render phase
  • Depend on modal close for confirm resolution

API Reference

No props found for Dialog.