Rask
Rask
v0.23.1-alpha.0.642

Components

Confirm

The dialog an action's .Confirm("…") asks in, in place of the browser's own confirm and prompt. Place Ui.Confirm in the layout once and every .Confirm on every page asks through it. Not one of Flux UI's components: the kit's own, a Ui.Modal drawn as Flux's confirmation.

Confirm an action

This tab's layout places a Ui.Confirm, so the button asks in it. heading: is the question's own title; No, the close button, Escape and a press outside call the delete off, and Yes lets the same press go.

ConfirmExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

// This tab's layout places Ui.Confirm once, so every .Confirm("…") on its pages asks in that dialog. heading: is
// this question's own title, and the question is the sentence beneath it.
public sealed partial class ConfirmExample : Component
{
    private string _project = "Rask";

    protected override Component? Render() =>
        Div.Class("flex flex-wrap items-center gap-4")[
            Ui.Button.Danger.Id("uc-delete")
                .OnClick(() => _project = "")
                .Confirm("You're about to delete this project. This action cannot be reversed.", heading: "Delete project?")["Delete project"],
            Ui.Button.Ghost.Id("uc-restore").OnClick(() => _project = "Rask")["Restore"],
            Ui.Text.Id("uc-state")[_project.Length > 0 ? $"The {_project} project is still there." : "You deleted the project."]
        ];
}
Live result

The Rask project is still there.

Type to confirm

With expect: the dialog shows a field, and Yes waits until the answer is typed exactly, case and all. Livewire's wire:confirm.prompt.

ConfirmExpectExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

// expect: shows a field in the dialog, and Yes waits until the answer is typed exactly, case and all.
public sealed partial class ConfirmExpectExample : Component
{
    private readonly List<string> _partners = ["Acme", "Globex", "Initech"];

    protected override Component? Render() =>
        Div.Class("space-y-3")[
            Ul.Class("max-w-sm divide-y divide-zinc-800/10 dark:divide-white/20")[
                _partners.Select(name => Li.Key(name).Class("flex items-center gap-2 py-2")[
                    Ui.Text.Class("grow")[name],
                    Ui.Button.Sm.Danger.Id($"uc-wipe-{name}")
                        .OnClick(() => _partners.Remove(name))
                        .Confirm($"Type {name} to delete it.", expect: name, heading: "Delete partner?")["Delete"]
                ])
            ],
            Ui.Text.Id("uc-left")[$"{_partners.Count} partners"]
        ];
}
Live result
  • Acme

  • Globex

  • Initech

3 partners

On a form

On a form it asks before the submit, and the form is held only once Yes lets it go. On a submit button it asks before the submit that button makes.

ConfirmFormExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

// On a form, .Confirm asks before the submit, and the form is held only once Yes lets it go.
public sealed partial class ConfirmFormExample : Component
{
    private readonly Order _order = new();
    private string? _sent;

    protected override Component? Render() =>
        Div.Class("space-y-3")[
            Form.Model(_order).OnSubmit(Send).Id("uc-form").Class("flex flex-wrap items-end gap-4")
                .Confirm("The kitchen starts cooking as soon as it arrives.", heading: "Send the order?")[
                Ui.Input.Bind(() => _order.Dish).Label("Dish").Id("uc-dish").Class("max-w-xs"),
                Ui.Button.Primary.Submit.Id("uc-send")["Send order"]
            ],
            Ui.Text.Id("uc-sent")[_sent is null ? "Nothing sent yet." : "Sent: " + _sent]
        ];

    private void Send(Order order) => _sent = order.Dish;

    public sealed class Order
    {
        public string Dish { get; set; } = "Pancakes";
    }
}
Live result

Nothing sent yet.

Your own words

Heading, No and Yes are the layout's, for every question on the page; a question with heading: brings its own title. A layout of its own, framed, because a page holds one dialog.

ConfirmWordsExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

// A layout of your own places the dialog once, in your words: the title a question without heading: gets, and
// the two buttons.
public sealed partial class ConfirmWordsExample : Component
{
    private int _companies = 3;

    protected override Component? Render() =>
    [
        Ui.Main.Class("flex min-h-dvh items-center justify-center")[
            Div.Class("flex flex-wrap items-center gap-4")[
                Ui.Button.Danger.Id("uc-words-delete")
                    .OnClick(() => _companies--)
                    .Confirm("Biztosan törli a céget?", heading: "Cég törlése")["Törlés"],
                Ui.Button.Id("uc-words-archive")
                    .OnClick(() => _companies--)
                    .Confirm("Archiválja a céget?")["Archiválás"],
                Ui.Text.Id("uc-words-left")[$"{_companies} cég"]
            ]
        ],
        Ui.Confirm.Heading("Megerősítés").No("Nem").Yes("Igen")
    ];
}
Live result

Behaviour

Placed once

Ui.Confirm goes in the layout, beside Ui.Toast, and every .Confirm("…") under it asks in that dialog. The call sites do not change: .Confirm is a step on every element, a plain Button, a Ui.Button, a Form, a submit button and a Ui.MenuItem alike.

Without it the same .Confirm asks in the browser's own window.confirm, or window.prompt for expect:, and heading: is not shown.

No, and yes

Only Yes lets the action go: the same press, or the same submit by the same button. The page may render while the reader is asked; Yes presses the button as the page stands then, and one that is gone runs nothing. Focus goes back to the control that was pressed.

The reader
What happens
presses No, the close button or Escape, or presses outsideThe action is called off. Nothing is sent.
presses YesThe click or the submit goes, and a form is held only now.
types into the expect: fieldYes stays disabled until the answer matches exactly; then Enter is Yes.

Asked in the browser

The dialog is rendered closed and the runtime writes the question into it and opens it (data-rask-confirm, data-rask-confirm-expect), so opening, typing and closing send the server nothing, on both hosts. A cancelled action sends nothing either: not the click, and not the bound fields waiting to go with it.

The expected answer is written into the page, so it guards against a slip, never a secret.

Its words

Heading, No and Yes default from the string catalog (ConfirmHeading, ConfirmNo, ConfirmYes), so a localized app needs no step at all. A question's heading: replaces the title for that question alone.

Drawn as Flux's confirmation: min-w-[22rem], a ghost button that says no and a danger button that says yes. The answer field, and a Yes that is no submit button, are its two departures.

Reference

Ui.Confirm

not in Flux UI

The dialog every .Confirm("…") under its layout asks in, in place of the browser's confirm and prompt. One per page.

Step
Takes
What it does
.Heading(…)stringThe short title above the question. "Confirm" when unset; a question's own heading: replaces it.
.No(…)stringThe label of the button that calls the action off. "No" when unset.
.Yes(…)stringThe label of the button that lets the action go. "Yes" when unset.

Confirm