ConfirmButton
A button that asks first, in a dialog on the page, then submits its form, follows its link or calls back.
Demo
Get it
It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.
$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/confirm_button.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/confirm_button.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/confirm_button.qwe
component ConfirmButtonDemoLive() { state archived = false <div.demo-row> <ConfirmButton message="Archive this project? You can bring it back later." tone="accent" variant="soft" ok="Archive" on_confirm={() => { archived = true }}>Archive</ConfirmButton> <span.demo-note>{archived ? "Archived." : "Not archived."}</span> </div>}view ConfirmButtonDemo() = <div.demo-stack> <form.demo-row method="get" action="#confirm_button"> <ConfirmButton title="Delete project?" message="This deletes the project and all its files. It cannot be undone." ok="Delete" name="deleted" value="yes">Delete project</ConfirmButton> <span.demo-note>Submits its form on yes (here, reloading this page).</span> </form> <div.demo-row> <ConfirmButton href="#confirm_button" message="Leave this page?" tone="neutral" variant="outline" ok="Leave"> A link </ConfirmButton> </div> <ConfirmButtonDemoLive/> </div>Source
ui/confirm_button.qwe
// ConfirmButton: a button that asks "are you sure?" before it acts, in a// dialog on the page (the builtin `ask`). On yes it does what it would have// done: submits its form, follows its link, or calls on_confirm().//// <form method="post" action="/projects/7/delete">// <ConfirmButton message="This deletes the project and its files.">Delete project</ConfirmButton>// </form>// <ConfirmButton href="/logout" tone="accent" message="Sign out on this device?" ok="Sign out">Sign out</ConfirmButton>//// message: the question. title: a heading over it. ok ("Confirm") and cancel// ("Cancel"): the dialog's buttons. tone: "danger" (default: the dialog starts// on Cancel), "accent" or "neutral", for the button and the dialog.// In a form, on yes it submits the form with this button as the submitter, so// its name and value are sent. href: a link instead. on_confirm(): inside one// of your components, what yes does (then nothing is submitted).// variant: "solid" (default), "soft", "outline" or "ghost"; size: "sm", "md" or// "lg". It is styled as a Button when button_css is on the page.// confirm_button_css also styles `ask`'s dialog (its q- classes), at the lowest// specificity, so the page's own styles for it (or the Notices') win.import ui/theme.qwe use ui_clslet confirm_button_css = css`:where(.q-backdrop) { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 16px; background: var(--ui-overlay); opacity: 0; transition: opacity .15s;}:where(.q-backdrop.q-open) { opacity: 1; }:where(.q-dialog) { box-sizing: border-box; width: min(420px, 100%); padding: 20px 22px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); background: var(--ui-surface); color: var(--ui-fg); box-shadow: var(--ui-shadow-lg); font: 15px/1.5 var(--ui-font); transform: translateY(8px) scale(.98); transition: transform .15s;}:where(.q-open .q-dialog) { transform: none; }:where(.q-dialog .q-title) { margin: 0 0 6px; font-size: 17px; font-weight: 600; line-height: 1.3; }:where(.q-dialog .q-message) { margin: 0 0 20px; color: var(--ui-muted); }:where(.q-dialog .q-actions) { display: flex; justify-content: flex-end; gap: 8px; }:where(.q-dialog .q-actions button) { height: 36px; padding: 0 14px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius-sm); background: transparent; color: var(--ui-fg); font: 500 14px/1 var(--ui-font); cursor: pointer;}:where(.q-dialog .q-actions button:hover) { background: var(--ui-subtle); }:where(.q-dialog .q-actions .q-ok) { border-color: transparent; background: var(--ui-accent); color: var(--ui-accent-fg); }:where(.q-dialog.q-danger .q-actions .q-ok) { background: var(--ui-danger); color: #fff; }:where(.q-dialog .q-actions .q-ok:hover) { background: color-mix(in srgb, var(--ui-accent) 88%, var(--ui-fg)); }:where(.q-dialog.q-danger .q-actions .q-ok:hover) { background: color-mix(in srgb, var(--ui-danger) 88%, var(--ui-fg)); }:where(.q-dialog .q-actions button:focus-visible) { outline: none; box-shadow: var(--ui-focus); }@media (prefers-reduced-motion: reduce) { :where(.q-backdrop, .q-dialog) { transition: none; } }`component ConfirmButton(message: str, title: str? = null, ok: str = "Confirm", cancel: str = "Cancel", tone: str = "danger", href: str? = null, name: str? = null, value: str? = null, variant: str = "solid", size: str = "md", disabled: bool = false, on_confirm = null, class: str? = null, children) { style global confirm_button_css state el = null let cls = ui_cls(["ui-btn", `ui-btn-${variant}`, tone != "accent" && `ui-btn-${tone}`, size != "md" && `ui-btn-${size}`, "ui-confirm-btn", class]) let go = (e) => { e.preventDefault() if ask(message, { title, ok, cancel, tone }) { if on_confirm != null { on_confirm() } else if href != null { navigate(href) } else if el.form != null { el.form.requestSubmit(el) } } } href != null ? <a class={cls} href={href} aria-disabled={disabled ? "true" : null} aria-haspopup="dialog" @mount={(a) => { el = a }} @click={go}>{children}</a> : <button class={cls} type={on_confirm != null ? "button" : "submit"} name={name} value={value} disabled={disabled} aria-haspopup="dialog" @mount={(b) => { el = b }} @click={go}>{children}</button>}Related
PromptDialogA modal asking for one text value with OK and Cancel, on the browser's own <dialog>; Enter submits, Escape cancels.4 views · 5 downloadsActionBarA page's main action and a line about it, fixed to the bottom of the screen on a phone.13 views · 6 downloadsBookmarkButtonA save-for-later toggle whose bookmark fills when pressed, with or without its label.8 views · 8 downloadsButtonA button, or a link that looks like one: four variants, three tones, three sizes, loading.7 views · 7 downloadsButtonGroupButtons joined edge to edge into one control, or spaced in a row; across or upright.6 views · 6 downloadsFabA round floating action button fixed to a corner of the screen, with an icon and an optional label.5 views · 7 downloads
Thread
Thread 0 posts
On ConfirmButton: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.