Modal
Displays content in a layer above the page. Uses native <dialog> styled by @primus/ui-core โ identical output in all three frameworks.
Codeโ
- HTML ยท @primus/ui-core
- React
- Angular
<div class="vstack" style="max-width:420px;width:100%">
<div role="alert" data-variant="info" style="font-size:0.8rem">In a real app this opens on button click. Shown inline here for preview.</div>
<div class="card" style="padding:1.25rem">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:0.75rem">
<h3 style="margin:0;font-size:1rem">Confirm Deletion</h3>
<button class="ghost icon small">โ</button>
</div>
<p style="font-size:0.875rem;color:var(--muted-foreground);margin:0 0 1rem">This action cannot be undone.</p>
<div style="display:flex;justify-content:flex-end;gap:0.5rem">
<button class="outline small">Cancel</button>
<button data-variant="danger" class="small">Delete</button>
</div>
</div>
</div>
import { PrimusModal } from 'primus-react-ui';
<button onClick={() => setOpen(true)}>Open Dialog</button>
<PrimusModal open={isOpen} title="Confirm Deletion" size="sm"
onClose={() => setIsOpen(false)}>
<p>This action cannot be undone.</p>
<div style={{ display:'flex', justifyContent:'flex-end', gap:'8px' }}>
<button className="outline small" onClick={() => setIsOpen(false)}>Cancel</button>
<button data-variant="danger" className="small" onClick={handleDelete}>Delete</button>
</div>
</PrimusModal>
<button (click)="isOpen = true">Open Dialog</button>
<primus-modal [open]="isOpen" title="Confirm Deletion" size="sm"
(onClose)="isOpen = false">
<p>This action cannot be undone.</p>
<div modal-footer>
<button class="outline small" (click)="isOpen = false">Cancel</button>
<button data-variant="danger" class="small" (click)="onDelete()">Delete</button>
</div>
</primus-modal>
Propsโ
| Prop | Type | Default | Description |
|---|---|---|---|
open / [open] | boolean | false | Controls visibility |
title | string | โ | Modal heading |
size | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Dialog width |
closeOnOverlayClick | boolean | true | Dismiss on backdrop click |
footer | ReactNode | โ | Custom footer content |
onClose / (onClose) | () => void | required | Called when modal should close |
Size widthsโ
| Size | Width |
|---|---|
sm | 22rem (352px) |
md | 32rem (512px) โ default |
lg | 48rem (768px) |
xl | 64rem (1024px) |
TypeScript interfacesโ
// React โ children + footer slot
<PrimusModal
open={isOpen}
title="Confirm deletion"
size="sm"
onClose={() => setIsOpen(false)}
footer={
<div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
<PrimusButton variant="outline" onClick={() => setIsOpen(false)}>
Cancel
</PrimusButton>
<PrimusButton variant="danger" onClick={handleDelete}>
Delete
</PrimusButton>
</div>
}
>
<p>This will permanently delete <strong>{record.name}</strong>. This cannot be undone.</p>
</PrimusModal>
// Angular โ content projection via modal-footer slot
// <primus-modal [open]="isOpen" title="Confirm" (onClose)="isOpen = false">
// <p>Content here.</p>
// <div modal-footer>
// <primus-button (clicked)="isOpen = false">Cancel</primus-button>
// <primus-button variant="danger" (clicked)="onConfirm()">Delete</primus-button>
// </div>
// </primus-modal>
Version history
See the Changelog for version history and breaking changes.