mirror of
https://github.com/hunvreus/basecoat.git
synced 2026-11-13 05:38:18 +00:00
Toast title, description and action labels were inserted into the page as HTML, so passing user input could inject markup or script. They are now escaped by default, and `html: true` keeps the old raw-HTML behaviour. The action href, onclick strings, category and duration are escaped as attribute values. `icon` stays raw markup. Documents the `html` and `icon` options, adds a warning about `html` and `onclick`, and notes that the Jinja and Nunjucks macros rely on template autoescaping. Co-authored-by: Maurits van Riezen <12109031+mousetail@users.noreply.github.com>
191 lines
7.2 KiB
Plaintext
191 lines
7.2 KiB
Plaintext
# Toast
|
|
|
|
<div id="toaster" class="toaster"></div>
|
|
|
|
<Preview class="max-w-md">
|
|
<button
|
|
class="btn" data-variant="outline"
|
|
hx-trigger="click"
|
|
hx-select="unset"
|
|
hx-get="/fragments/toast/success"
|
|
hx-target="#toaster"
|
|
hx-swap="beforeend"
|
|
hx-push-url="false"
|
|
>Toast from backend (with HTMX)</button>
|
|
</Preview>
|
|
|
|
<Preview class="max-w-md">
|
|
<button
|
|
class="btn" data-variant="outline"
|
|
onclick="document.getElementById('toaster').toast({
|
|
category: 'success',
|
|
title: 'Success',
|
|
description: 'A success toast called from the front-end.',
|
|
cancel: {
|
|
label: 'Dismiss'
|
|
}
|
|
})"
|
|
>Toast from front-end</button>
|
|
</Preview>
|
|
|
|
## Usage
|
|
|
|
<Callout title="Template macros available" icon="code" action={{ label: "More", href: "/templates#toast" }}>
|
|
This component ships `toaster()` and `toast()` macros for Jinja and Nunjucks.
|
|
</Callout>
|
|
|
|
<Steps>
|
|
<Step title="Include CSS">
|
|
|
|
Import Tailwind and one full Basecoat style bundle.
|
|
|
|
```css
|
|
@import "tailwindcss";
|
|
@import "basecoat-css/vega.css";
|
|
```
|
|
|
|
Or import only the base CSS, Toast component CSS, and one style pack.
|
|
|
|
```css
|
|
@import "tailwindcss";
|
|
@import "basecoat-css/base.css";
|
|
@import "basecoat-css/components/toast.css";
|
|
@import "basecoat-css/styles/vega.css";
|
|
```
|
|
|
|
Using CDN or bundler imports? See the [Installation page](/installation).
|
|
|
|
</Step>
|
|
<Step title="Include JavaScript">
|
|
|
|
Copy or serve the full Basecoat JavaScript bundle.
|
|
|
|
```html
|
|
<script src="/assets/js/all.min.js" defer></script>
|
|
```
|
|
|
|
Or copy or serve the Basecoat runtime and Toast script.
|
|
|
|
```html
|
|
<script src="/assets/js/basecoat.min.js" defer></script>
|
|
<script src="/assets/js/toast.min.js" defer></script>
|
|
```
|
|
|
|
Using CDN or bundler imports? See the [Installation page](/installation).
|
|
|
|
</Step>
|
|
<Step title="Add the toaster HTML">
|
|
|
|
Add one toaster near the end of your page body:
|
|
|
|
```html
|
|
<div id="toaster" class="toaster"></div>
|
|
```
|
|
|
|
Set `data-align="start"`, `data-align="center"`, or `data-align="end"` on the toaster to change placement.
|
|
|
|
</Step>
|
|
<Step title="Add your toasts">
|
|
|
|
Append server-rendered toast markup to the toaster, or create one from JavaScript with `toaster.toast(config)`.
|
|
|
|
```html
|
|
<div id="toaster" class="toaster">
|
|
<div class="toast" role="status" aria-atomic="true" aria-hidden="false" data-category="success">
|
|
<div class="toast-content"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></svg>
|
|
<section>
|
|
<h2>Success</h2>
|
|
<p>A success toast called from the front-end.</p>
|
|
</section>
|
|
<footer>
|
|
<button type="button" class="btn" data-toast-action>Dismiss</button>
|
|
</footer>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
```html
|
|
<button
|
|
class="btn" data-variant="outline"
|
|
onclick="document.getElementById('toaster').toast({
|
|
category: 'success',
|
|
title: 'Success',
|
|
description: 'A success toast called from the front-end.',
|
|
cancel: {
|
|
label: 'Dismiss'
|
|
}
|
|
})">Toast from front-end</button>
|
|
```
|
|
|
|
</Step>
|
|
</Steps>
|
|
|
|
### HTML structure
|
|
|
|
<dl>
|
|
<dt><code><div id="toaster" class="toaster"></code></dt>
|
|
<dd>Toast container. Optional <code>data-align</code> values are <code>start</code>, <code>center</code>, and <code>end</code>.</dd>
|
|
<dt><code><div class="toast"></code></dt>
|
|
<dd>
|
|
Toast item. Use <code>data-category="success|info|warning|error"</code> for category styling and <code>data-duration</code> to override the timeout in milliseconds. Use <code>data-duration="-1"</code> to keep it open.
|
|
<dl>
|
|
<dt><code><div class="toast-content"></code></dt>
|
|
<dd>
|
|
Content wrapper.
|
|
<dl>
|
|
<dt><code><svg aria-hidden="true"></code> <span class="badge" data-variant="secondary">Optional</span></dt>
|
|
<dd>Icon.</dd>
|
|
<dt><code><section></code></dt>
|
|
<dd>
|
|
Message region.
|
|
<dl>
|
|
<dt><code><h2></code></dt>
|
|
<dd>Title.</dd>
|
|
<dt><code><p></code> <span class="badge" data-variant="secondary">Optional</span></dt>
|
|
<dd>Description.</dd>
|
|
</dl>
|
|
</dd>
|
|
<dt><code><footer></code> <span class="badge" data-variant="secondary">Optional</span></dt>
|
|
<dd>Action buttons or links. Clicking a footer button or link closes the toast.</dd>
|
|
</dl>
|
|
</dd>
|
|
</dl>
|
|
</dd>
|
|
</dl>
|
|
|
|
### JavaScript API
|
|
|
|
| API | Type | Description |
|
|
| --- | --- | --- |
|
|
| `toaster.toast(config)` | Method | Creates a toast from a config object and returns the inserted `.toast` element. [See "Config object" below](#config-object). |
|
|
| `toaster.closeAll()` | Method | Closes every toast inside the toaster. |
|
|
| `toast.close()` | Method | Closes one initialized toast element. |
|
|
|
|
### Config object
|
|
|
|
<Callout type="warning" title="Text is escaped by default" icon="triangle-alert">
|
|
`title`, `description`, and action labels are inserted as plain text. With `html: true` they are inserted as HTML, so never pass untrusted user input with it. `onclick` is JavaScript code and must never contain user input. `icon` is always inserted as raw HTML (it is meant for SVG markup).
|
|
</Callout>
|
|
|
|
<dl>
|
|
<dt><code>duration</code> <span class="badge" data-variant="secondary">Optional</span></dt>
|
|
<dd>Timeout in milliseconds. Defaults to <code>3000</code>, or <code>5000</code> for error toasts. Use <code>-1</code> to keep it open.</dd>
|
|
<dt><code>category</code> <span class="badge" data-variant="secondary">Optional</span></dt>
|
|
<dd>Category of the toast, either <code>success</code>, <code>info</code>, <code>warning</code>, or <code>error</code>.</dd>
|
|
<dt><code>title</code></dt>
|
|
<dd>The title of the toast.</dd>
|
|
<dt><code>description</code> <span class="badge" data-variant="secondary">Optional</span></dt>
|
|
<dd>The description of the toast.</dd>
|
|
<dt><code>action</code> <span class="badge" data-variant="secondary">Optional</span></dt>
|
|
<dd>Primary action. Supports <code>label</code> with either <code>href</code> or <code>onclick</code>.</dd>
|
|
<dt><code>cancel</code> <span class="badge" data-variant="secondary">Optional</span></dt>
|
|
<dd>Secondary action. Supports <code>label</code> and optional <code>onclick</code>.</dd>
|
|
<dt><code>icon</code> <span class="badge" data-variant="secondary">Optional</span></dt>
|
|
<dd>Custom icon markup, usually an SVG. Inserted as raw HTML. Defaults to the category icon.</dd>
|
|
<dt><code>html</code> <span class="badge" data-variant="secondary">Optional</span></dt>
|
|
<dd>Set to <code>true</code> to insert <code>title</code>, <code>description</code>, and action labels as HTML instead of plain text. Defaults to <code>false</code>. Only use it with trusted content.</dd>
|
|
</dl>
|
|
|
|
The Jinja and Nunjucks `toast()` macros render on your server, so your template engine's autoescaping applies to `title`, `description`, and labels there when it is enabled. Nunjucks enables it by default. With Jinja, make sure your environment's `autoescape` setting covers the Basecoat template files (for example `.html.jinja`). `icon` is output with `safe`, and `onclick` is output as an attribute, so neither should contain user input.
|