Alert Dialog
A modal that asks for a decision.
<alertdialog.AlertDialog id="demo-alert" title="Delete this item?" description="This action cannot be undone.">
<:confirm><button.Button variant={button.Destructive}>Delete</button.Button></:confirm>
<:trigger><button.Button variant={button.Outline}>Delete</button.Button></:trigger>
</alertdialog.AlertDialog>Installation
Run the command in the app module.
gx add alert-dialogThe command also installs button.
The command writes these files.
| File | Path in the app |
|---|---|
AlertDialog.gx |
ui/alert-dialog/AlertDialog.gx |
AlertDialog.fixtures.go |
ui/alert-dialog/AlertDialog.fixtures.go |
styles.go |
ui/alert-dialog/styles.go |
Install button first.
Copy each file to its path in the app. Change each import of a registry package to the path of that package in the app.
package alertdialog
import "github.com/alternayte/gx/registry/button"
props {
// Id is the id of the dialog element.
// The trigger points at it, so it must be unique on the page.
Id string
// Title is the heading of the alert dialog. It states the question.
Title string
// Description is the text below the title. An empty value renders no description.
Description string = ""
// Size sets the maximum width and the layout: Md or Sm.
// Sm centres the text and puts the buttons side by side.
Size Size = Md
// Media is an icon or image shown in a tile next to the title. A nil value renders no tile.
Media gx.Node = nil
// Trigger is the control that opens the alert dialog.
Trigger gx.Node = nil
// Confirm is the control that confirms the action. It renders after the cancel button.
Confirm gx.Node = nil
// Cancel is the label of the cancel button, which closes the alert dialog.
// An empty value is Cancel.
Cancel string = "Cancel"
// Open renders the alert dialog open. The default is closed.
Open bool = false
// Class adds classes to the dialog element.
Class string = ""
// Children is the content of the alert dialog body, between the header and the buttons.
Children gx.Node = nil
// Attrs adds HTML attributes to the dialog element.
Attrs gx.Attrs = nil
}
<span class="contents">
if p.Trigger != nil {
<span data-gx-open={"#" + p.Id} class="contents">{p.Trigger}</span>
}
<dialog id={p.Id} open={p.Open} role="alertdialog" data-gx-dismiss="manual" data-gx-trap data-size={p.size()} class={gx.Cx("group/alert-dialog-content fixed inset-0 m-auto h-fit w-full max-w-[calc(100%-2rem)] gap-4 rounded-lg border border-border bg-background p-6 text-foreground shadow-lg outline-none open:grid data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg opacity-0 scale-95 transition-[opacity,scale,overlay,display] transition-discrete duration-200 open:opacity-100 open:scale-100 starting:open:opacity-0 starting:open:scale-95 motion-reduce:transition-none backdrop:bg-black/50 backdrop:opacity-0 backdrop:transition-[opacity,overlay,display] backdrop:transition-discrete backdrop:duration-200 open:backdrop:opacity-100 starting:open:backdrop:opacity-0 motion-reduce:backdrop:transition-none", p.Class)} {...p.Attrs}>
<div class="grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]">
if p.Media != nil {
<div data-slot="alert-dialog-media" class="mb-2 inline-flex size-16 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-8">{p.Media}</div>
}
<h2 class="text-lg font-semibold sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2">{p.Title}</h2>
if p.Description != "" {
<p class="text-sm text-muted-foreground">{p.Description}</p>
}
</div>
if p.Children != nil {
<div class="text-sm">{p.Children}</div>
}
<div class="flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end">
<button.Button variant={button.Outline} attrs={gx.Attrs{gx.Bool("data-gx-close", true)}}>{p.cancel()}</button.Button>
if p.Confirm != nil {
{p.Confirm}
}
</div>
</dialog>
</span>package alertdialog
import (
"github.com/alternayte/gx"
"github.com/alternayte/gx/registry/button"
)
var AlertDialogFixtures = gx.Fixtures[AlertDialogProps]{
"Default": {
Id: "demo-alert",
Title: "Delete this item?",
Description: "This action cannot be undone.",
Confirm: button.Button(button.ButtonProps{Variant: button.Destructive, Children: gx.Text("Delete")}),
Trigger: button.Button(button.ButtonProps{Variant: button.Outline, Children: gx.Text("Delete")}),
},
}package alertdialog
// Size is the width of an alert dialog.
type Size string
// The sizes of alertdialog.AlertDialog.
const (
Md Size = "default"
Sm Size = "sm"
)
// size returns the data-size value; a zero value is Md.
func (p AlertDialogProps) size() string {
if p.Size == "" {
return string(Md)
}
return string(p.Size)
}
// cancel returns the label of the cancel button; a zero value is Cancel.
func (p AlertDialogProps) cancel() string {
if p.Cancel == "" {
return "Cancel"
}
return p.Cancel
}The theme must define these tokens: --background, --foreground, --border, --muted, --muted-foreground, --ring.
Usage
<alertdialog.AlertDialog id="delete" title="Delete this item?" description="This action cannot be undone."
confirm={button.Button(button.ButtonProps{Variant: button.Destructive, Children: gx.Text("Delete")})}>
<:trigger><button.Button variant={button.Outline}>Delete</button.Button></:trigger>
</alertdialog.AlertDialog>Examples
Default
<alertdialog.AlertDialog id="demo-alert" title="Delete this item?" description="This action cannot be undone.">
<:confirm><button.Button variant={button.Destructive}>Delete</button.Button></:confirm>
<:trigger><button.Button variant={button.Outline}>Delete</button.Button></:trigger>
</alertdialog.AlertDialog>API reference
A tag sets a prop by its name with a lower-case first letter: Class is class.
alertdialog.AlertDialog
| Prop | Type | Default | Description |
|---|---|---|---|
Id |
string |
Required | Id is the id of the dialog element. The trigger points at it, so it must be unique on the page. |
Title |
string |
Required | Title is the heading of the alert dialog. It states the question. |
Description |
string |
"" |
Description is the text below the title. An empty value renders no description. |
Size |
Size |
Md |
Size sets the maximum width and the layout: Md or Sm. Sm centres the text and puts the buttons side by side. |
Media |
gx.Node |
nil |
Media is an icon or image shown in a tile next to the title. A nil value renders no tile. |
Trigger |
gx.Node |
nil |
Trigger is the control that opens the alert dialog. |
Confirm |
gx.Node |
nil |
Confirm is the control that confirms the action. It renders after the cancel button. |
Cancel |
string |
"Cancel" |
Cancel is the label of the cancel button, which closes the alert dialog. An empty value is Cancel. |
Open |
bool |
false |
Open renders the alert dialog open. The default is closed. |
Class |
string |
"" |
Class adds classes to the dialog element. |
Children |
gx.Node |
nil |
Children is the content of the alert dialog body, between the header and the buttons. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the dialog element. |
Do and do not
Do
- Follow the question with the two outcomes.
- Name the confirm button after the action.
Don't
- Do not close an alert dialog on an outside click.
- Do not use an alert dialog for a message with one outcome. Use a dialog.
Keyboard
| Key | Action |
|---|---|
| Enter, Space | Opens the alert dialog from the trigger. |
| Tab | Cycles through Cancel and Confirm. |
| Escape | Does not close the alert dialog. |