How to configure modals and toasts
Piko ships three built-in frontend modules (ModuleAnalytics, ModuleModals, ModuleToasts). A project opts into the modules it uses and configures them at bootstrap. Actions can then trigger modal and toast behaviour by adding response helpers. This guide covers the modal and toast modules. See the server actions reference for the helper mechanism and the bootstrap options reference for the surrounding API.
Enable the modules
Pass each module into WithFrontendModule. Some modules accept a typed config value:
ssr := piko.New(
piko.WithFrontendModule(piko.ModuleModals, piko.ModalsConfig{
DisableCloseOnEscape: false,
DisableCloseOnBackdrop: false,
}),
piko.WithFrontendModule(piko.ModuleToasts, piko.ToastsConfig{
Position: "top-right",
DefaultDuration: 5000,
MaxVisible: 5,
}),
)
WithFrontendModule accepts an optional typed config as the second argument. Omit it to take the module's defaults.
Modals configuration
piko.ModalsConfig:
| Field | Default | Behaviour |
|---|---|---|
DisableCloseOnEscape | false | When false, pressing Escape closes the modal. Set to true to require an explicit close. |
DisableCloseOnBackdrop | false | When false, clicking the backdrop closes the modal. Set to true to force the user to use a Close button. |
Toasts configuration
piko.ToastsConfig:
| Field | Default | Purpose |
|---|---|---|
Position | "bottom-right" | One of "top-right", "top-left", "bottom-right", "bottom-left", "top-centre", "bottom-centre". |
DefaultDuration | 5000 | Display time in milliseconds. Set per-toast with the fourth argument to showToast. |
MaxVisible | 5 | Maximum number of toasts visible at once; older ones dismiss. |
Trigger from an action
Use a.Response().AddHelper(...) to queue client-side calls that the frontend runtime interprets after the action returns:
func (a *CustomerSaveAction) Call(input CustomerSaveInput) (CustomerSaveResponse, error) {
customer, err := saveCustomer(a.Ctx(), input)
if err != nil {
a.Response().AddHelper("showToast", "Could not save customer", "error")
return CustomerSaveResponse{}, piko.NewError("save failed", err)
}
a.Response().AddHelper("showToast", "Customer saved", "success", 3000)
a.Response().AddHelper("closeModal")
a.Response().AddHelper("reloadPartial", "customer-list")
return CustomerSaveResponse{ID: customer.ID}, nil
}
showToast arguments
| Position | Type | Purpose |
|---|---|---|
| 1 | string | Message body. |
| 2 | string | Severity: "success", "error", "warning", "info". |
| 3 | number (optional) | Duration in milliseconds; overrides DefaultDuration for this toast. |
closeModal arguments
| Position | Type | Purpose |
|---|---|---|
| 1 | string (optional) | Modal name. Closes the modal whose modal="<name>" attribute matches. When omitted, the helper falls back to the nearest ancestor [modal] of the trigger element. |
updateModal arguments
| Position | Type | Purpose |
|---|---|---|
| 1 | string (optional) | Modal name, matched against the modal="<name>" attribute. When omitted, the helper updates the nearest ancestor [modal] of the trigger element. |
Calls the modal element's update() method, which refetches the modal body from the server and swaps it in. Use after a server action mutates the data the modal renders.
reloadPartial arguments
| Position | Type | Purpose |
|---|---|---|
| 1 | string | CSS selector for the partial element. |
The runtime finds the matching partial element in the DOM, refetches it from the server, and swaps it in without a full-page reload.
Trigger from client TypeScript
The names showToast, showModal, closeModal, updateModal, and reloadPartial are server-side helper identifiers. The frontend runtime registers them via pk.registerHelper(...), and they fire when the action response queues them through Response().AddHelper(...). They are not flat methods on the piko namespace, so calls such as piko.showModal(...) from client code are not the public API.
To open a modal programmatically from a PKC component, call pk.modal.open(...) with a ModalRequestOptions object:
await pk.modal.open({
selector: "#customer-edit-modal",
params: new Map([["customerId", "42"]]),
title: "Edit customer",
triggerElement: event.currentTarget as HTMLElement,
});
selector resolves to the modal element in the current DOM (typically rendered conditionally behind a p-if). triggerElement lets the runtime scope events and animations correctly. params flows through to the modal body request as query parameters.
To dispatch a toast from client code, fire the pk-show-toast custom event the toast extension listens for:
document.dispatchEvent(new CustomEvent("pk-show-toast", {
detail: { message: "Saved", variant: "success", duration: 5000 },
}));
To close a modal you already hold a reference to, call its close() method directly. The same applies to update() for refreshing the body and reload() on a partial element.
Style modals and toasts
Both modules ship default styles that match Piko's design tokens. Override them with CSS custom properties at the document root:
:root {
--piko-toast-background: #1f2937;
--piko-toast-color: #f9fafb;
--piko-toast-border-radius: 8px;
--piko-modal-backdrop: rgba(0, 0, 0, 0.6);
--piko-modal-border-radius: 12px;
}
The exact variable names ship with the modules. Inspect the rendered DOM to see which variables the current version uses.
See also
- Server actions reference for
Response().AddHelperand the full helper list. - Bootstrap options reference for
WithFrontendModuleandWithCustomFrontendModule. - How to forms for a form flow that triggers toasts after submission.