Screenshots for reusable modal dialogs docs, plus just shots (#2958)

docs/shots.yml defines documentation screenshots for shot-scraper

"Just shots" runs them.
This commit is contained in:
Simon Willison 2026-09-24 15:06:57 -07:00 • committed by GitHub
commit cec5e6b2ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 157 additions and 41 deletions

View file

@ -0,0 +1,41 @@
// Demonstrates every shared modal CSS class, for images/modal-classes.webp
document.addEventListener("datasette_init", () => {
const openButton = document.createElement("button");
openButton.type = "button";
openButton.textContent = "Open export dialog";
openButton.setAttribute("aria-haspopup", "dialog");
openButton.setAttribute("aria-controls", "export-dialog");
const modal = DatasetteModal.create();
const dialog = modal.dialog;
dialog.id = "export-dialog";
dialog.setAttribute("aria-labelledby", "export-dialog-title");
dialog.innerHTML = `
<div class="modal-header">
<h2 class="modal-title" id="export-dialog-title">Export rows</h2>
<span class="modal-meta">3 selected</span>
</div>
<div class="modal-body">
<p>Export these rows from the <strong>plants</strong> table as CSV:</p>
<ul>
<li>Monstera deliciosa</li>
<li>Ficus lyrata</li>
<li>Pilea peperomioides</li>
</ul>
</div>
<div class="modal-footer">
<span class="footer-info">CSV, UTF-8</span>
<button type="button" class="modal-btn modal-btn-ghost">Cancel</button>
<button type="button" class="modal-btn modal-btn-primary">Export</button>
</div>`;
const [cancelButton, exportButton] = dialog.querySelectorAll(".modal-footer button");
cancelButton.addEventListener("click", () => modal.requestClose("cancel"));
exportButton.addEventListener("click", () => modal.close());
openButton.addEventListener("click", () => {
modal.show({ returnFocusTo: openButton, initialFocus: exportButton });
});
document.body.append(modal);
document.querySelector("section.content").append(openButton);
});

View file

@ -0,0 +1,38 @@
document.addEventListener("datasette_init", () => {
const openButton = document.createElement("button");
openButton.type = "button";
openButton.textContent = "Open example dialog";
// Indicate that this button opens a dialog:
openButton.setAttribute("aria-haspopup", "dialog");
// Identify which dialog it controls:
openButton.setAttribute("aria-controls", "my-plugin-dialog");
const modal = DatasetteModal.create();
const dialog = modal.dialog;
dialog.id = "my-plugin-dialog";
// Tell screenreaders the dialog is labelled by #my-plugin-dialog-title
dialog.setAttribute("aria-labelledby", "my-plugin-dialog-title");
dialog.innerHTML = `
<div class="modal-header">
<h2 class="modal-title" id="my-plugin-dialog-title">
Example dialog
</h2>
</div>
<div class="modal-body">
This dialog uses Datasette's shared styles and keyboard behavior.
</div>
<div class="modal-footer">
<button type="button" class="modal-btn modal-btn-ghost">Close</button>
</div>`;
const closeButton = dialog.querySelector("button");
closeButton.addEventListener("click", () => {
modal.requestClose("cancel");
});
openButton.addEventListener("click", () => {
modal.show({ returnFocusTo: openButton, initialFocus: closeButton });
});
document.body.append(modal);
document.querySelector("section.content").append(openButton);
});