overlays
Dialog
A modal window that asks for a decision or a short task before people continue.
Native behaviorUses built-in HTML behavior, so you write no script.
Usage
A native <dialog> opened with commandfor and command="show-modal". No JavaScript of your own is needed.
<button class="ca-button ca-button--outline ca-button--md" type="button" commandfor="delete-project" command="show-modal">Delete project</button>
<dialog class="ca-dialog" id="delete-project" aria-labelledby="delete-project-title" aria-describedby="delete-project-description">
<h2 class="ca-dialog__title" id="delete-project-title">Delete “Spring campaign”?</h2>
<p class="ca-dialog__description" id="delete-project-description">The project and its 12 tasks are removed for everyone. You cannot undo this.</p>
<div class="ca-dialog__footer">
<button class="ca-button ca-button--ghost ca-button--md" type="button" commandfor="delete-project" command="close" autofocus>Keep project</button>
<button class="ca-button ca-button--primary ca-button--md" type="button" commandfor="delete-project" command="close" value="delete">Delete project</button>
</div>
</dialog>Examples
With a form
A form with method="dialog" closes the dialog on submit and keeps the button value as the result.
<button class="ca-button ca-button--primary ca-button--md" type="button" commandfor="rename-lesson" command="show-modal">Rename lesson</button>
<dialog class="ca-dialog" id="rename-lesson" aria-labelledby="rename-lesson-title">
<form method="dialog" class="grid gap-4">
<h2 class="ca-dialog__title" id="rename-lesson-title">Rename lesson</h2>
<div class="ca-field">
<label class="ca-field__label" for="lesson-name">Lesson name</label>
<input class="ca-input ca-input--md" id="lesson-name" name="lesson-name" type="text" value="Highway practice" />
</div>
<div class="ca-dialog__footer">
<button class="ca-button ca-button--ghost ca-button--md" type="submit" value="cancel" formnovalidate>Cancel</button>
<button class="ca-button ca-button--primary ca-button--md" type="submit" value="save">Save name</button>
</div>
</form>
</dialog>Guidance and accessibility
When to use
- Use a dialog when people must decide before they continue, such as confirming a deletion.
- Do not use a dialog for information that can live on the page. Every dialog interrupts.
- Name the action on the buttons: “Delete project” and “Keep project”, not “OK” and “Cancel”.
Accessibility
- The browser keeps focus inside the open dialog, closes it on Escape and makes the page behind it inert. Calaca adds the styles and locks page scrolling.
- Connect the title with
aria-labelledbyand the explanation witharia-describedby. - Put
autofocuson the safest action, so a quick Enter does not delete anything. - Older browsers without invoker commands need
ca-commands.js; it does nothing where the browser supports them natively.
Classes
Generated from the component contract. Parts use __, modifiers use --.
| Class | Kind | Use it for |
|---|---|---|
ca-dialog | Component | Centered modal surface; open state and backdrop. |
ca-dialog__title | Part | Heading of the dialog; connect it with aria-labelledby. |
ca-dialog__description | Part | Explains the consequence; connect it with aria-describedby. |
ca-dialog__footer | Part | Row of actions at the end of the dialog. |
Skins
The same markup, dressed by each skin. Structure and behavior stay the same; only the look changes.
Base skin
Neutral grayscale starting point; product skins extend it and change what differs.
Calaca skin
The Calaca UI brand: hueso paper and tinta ink, cempasúchil marigold, rosa and jade.
Proof skin
Pilot skin pushed far from base: square, heavy, offset shadows, larger targets.
Crossview skin
The CrossView proofing table: cool ground, bond-paper sheets, rule-grey hairlines, one red mark.
Framework notes
Link the prebuilt stylesheet of your skin next to your brand theme. No build step.
<link rel="stylesheet" href="theme.css" />
<link rel="stylesheet" href="ca-base.css" />In Astro, Vite and other Tailwind projects, import Calaca after Tailwind and your theme in your main stylesheet.
@import "tailwindcss";
@import "./theme.css";
@import "@calaca/ui/core.css";
@import "@calaca/ui/skins/base.css";Same stylesheet as above; write the classes in className.
<button className="ca-button ca-button--primary ca-button--md" type="button">Save changes</button>Add the commands polyfill once per page, for browsers without native invoker commands. In Astro or Next.js, import @calaca/ui/behavior/commands once in the layout.
<script type="module" src="ca-commands.js"></script>