Dialog
Lightweight imperative modal component for centered overlay content
You are reading the v1 docs. v2 renamed several props and replaced GeckoUIPortal with GeckoUIProvider. Read this page in v2.
Live examples are only rendered in the v2 docs.
Dialog
A lightweight, imperative modal component that renders content in a centered overlay. It serves as the foundational layer for more complex dialog patterns and automatically handles focus management, escape key dismissal, and click-outside behavior.
Installation
import { Dialog } from '@geckoui/geckoui';Basic Usage
import { Dialog, Button } from '@geckoui/geckoui';
function Example() {
const openDialog = () => {
Dialog.show({
content: ({ dismiss }) => (
<div>
<h2 className="text-xl font-semibold mb-4">Welcome!</h2>
<p className="text-gray-600 mb-6">
This is a simple dialog with custom content.
</p>
<Button onClick={dismiss}>Close</Button>
</div>
)
});
};
return <Button onClick={openDialog}>Open Dialog</Button>;
}API
Dialog.show(options)
Opens a dialog with the specified options.
| Option | Type | Default | Description |
|---|---|---|---|
content | ReactNode | FC<{ dismiss: () => void }> | - | Content to display in the dialog (required) |
className | string | - | CSS class for the dialog container |
dismissOnEsc | boolean | true | Dismiss dialog on Escape key press |
dismissOnOutsideClick | boolean | true | Dismiss dialog on backdrop click |
data-* | string | - | Data attributes for the dialog element |
Dialog.dismiss()
Programmatically closes the currently open dialog.
// Close dialog from anywhere
Dialog.dismiss();Examples
Image Lightbox
const openImageViewer = () => {
Dialog.show({
content: ({ dismiss }) => (
<div className="relative">
<img
src="/large-image.jpg"
alt="Preview"
className="max-w-4xl rounded-lg"
/>
<button
onClick={dismiss}
className="absolute top-4 right-4 size-8 flex items-center justify-center bg-black/50 text-white rounded-full"
>
✕
</button>
</div>
),
className: "bg-transparent shadow-none",
dismissOnEsc: true,
dismissOnOutsideClick: true
});
};Form Modal
import { Input, Label } from '@geckoui/geckoui';
const showUserForm = () => {
Dialog.show({
content: ({ dismiss }) => (
<div>
<h2 className="text-xl font-semibold mb-4">Edit Profile</h2>
<div className="space-y-4">
<div className="space-y-1">
<Label htmlFor="name">Name</Label>
<Input id="name" type="text" defaultValue="John Doe" />
</div>
<div className="space-y-1">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" defaultValue="[email protected]" />
</div>
<div className="flex gap-2 justify-end">
<Button variant="ghost" onClick={dismiss}>Cancel</Button>
<Button onClick={dismiss}>Save Changes</Button>
</div>
</div>
</div>
),
className: "max-w-2xl",
dismissOnEsc: false,
dismissOnOutsideClick: false
});
};Non-Dismissible Dialog
Dialog.show({
content: ({ dismiss }) => (
<div>
<h2 className="text-xl font-semibold mb-4">Important Notice</h2>
<p className="text-gray-600 mb-6">
This dialog can only be closed by clicking the button.
</p>
<Button onClick={dismiss}>I Understand</Button>
</div>
),
dismissOnEsc: false,
dismissOnOutsideClick: false
});Loading State
// Show loading dialog
Dialog.show({
content: () => (
<div className="flex flex-col items-center gap-4">
<Spinner />
<p>Processing payment...</p>
</div>
),
dismissOnEsc: false,
dismissOnOutsideClick: false
});
// Dismiss from anywhere after async operation
await processPayment();
Dialog.dismiss();Content Function Pattern
The content prop can receive a function that gets access to the dismiss callback:
Dialog.show({
content: ({ dismiss }) => {
const handleSave = async () => {
await saveData();
dismiss(); // Close after save
};
return (
<div>
<h2>Edit Item</h2>
<Button onClick={handleSave}>Save</Button>
<Button onClick={dismiss}>Cancel</Button>
</div>
);
}
});Behavior
Focus Management
- Automatically blurs the active element when dialog opens
- Prevents focus from leaving the dialog while open
- Restores focus appropriately when closed
Dismissal
- Escape Key: Closes dialog by default (disable with
dismissOnEsc={false}) - Click Outside: Closes dialog by default (disable with
dismissOnOutsideClick={false}) - Programmatic: Call
Dialog.dismiss()from anywhere
Portal Rendering
Dialog requires <GeckoUIPortal /> to be mounted in your app:
// app/layout.tsx
import { GeckoUIPortal } from '@geckoui/geckoui';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<GeckoUIPortal />
</body>
</html>
);
}Styling
GeckoUIDialog- Main containerGeckoUIDialog__backdrop- Background overlayGeckoUIDialog__dialog- Dialog content wrapper
Accessibility
- Click-outside detection
- Escape key support
- Focus management
- Backdrop prevents interaction with underlying content
Related Components
- ConfirmDialog - Pre-styled confirmation dialogs
- Drawer - Side panel alternative to centered dialogs