From 1a4d2924376cdb64c0de6db4731cf96bbc4fda66 Mon Sep 17 00:00:00 2001 From: Ronan Berder Date: Wed, 7 May 2025 14:57:30 +0800 Subject: [PATCH] Documentation finished --- docs/css/custom.css | 15 ++ docs/src/_includes/layouts/base.njk | 3 + docs/src/_includes/layouts/layout.njk | 5 +- .../_includes/partials/kitchen-sink/toast.njk | 9 +- docs/src/assets/styles.css | 167 +++--------- docs/src/components/alert-dialog.njk | 14 +- docs/src/components/breadcrumb.njk | 14 +- docs/src/components/combobox.njk | 14 +- docs/src/components/dialog.njk | 16 +- docs/src/components/dropdown-menu.njk | 15 ++ docs/src/components/popover.njk | 14 +- docs/src/components/select.njk | 14 +- docs/src/components/sidebar.njk | 16 ++ docs/src/components/tabs.njk | 14 +- docs/src/components/toast.njk | 243 +++++++++++++++++- docs/src/fragments/toast/error.njk | 13 +- docs/src/fragments/toast/info.njk | 11 +- docs/src/fragments/toast/success.njk | 13 +- docs/src/fragments/toast/warning.njk | 11 +- docs/src/index.njk | 2 +- src/css/basecoat.css | 11 - src/js/toast.js | 7 +- src/nunjucks/toast.njk | 191 ++++++++------ 23 files changed, 536 insertions(+), 296 deletions(-) diff --git a/docs/css/custom.css b/docs/css/custom.css index 882d322..ef75d05 100644 --- a/docs/css/custom.css +++ b/docs/css/custom.css @@ -1,3 +1,15 @@ +/* HTMX */ +.htmx-indicator { + @apply invisible opacity-0 transition-discrete transition-all; +} +.htmx-indicator:not(.htmx-request) { + @apply hidden; +} +.htmx-request, +.htmx-request.htmx-indicator { + @apply visible opacity-100; +} + .content { > h2 { @apply mt-16 mb-6 scroll-m-22 border-b pb-4 text-xl font-semibold tracking-tight first:mt-0; @@ -5,6 +17,9 @@ > h3 { @apply mt-8 mb-6 scroll-m-22 text-lg font-semibold tracking-tight; } + > h4 { + @apply my-6 scroll-m-22 font-semibold tracking-tight; + } .prose { @apply my-6; diff --git a/docs/src/_includes/layouts/base.njk b/docs/src/_includes/layouts/base.njk index 463868d..171328f 100644 --- a/docs/src/_includes/layouts/base.njk +++ b/docs/src/_includes/layouts/base.njk @@ -97,5 +97,8 @@ {{ content | safe }} + +{% from "toast.njk" import toaster %} +{{ toaster() }} \ No newline at end of file diff --git a/docs/src/_includes/layouts/layout.njk b/docs/src/_includes/layouts/layout.njk index c3eecbe..4cc5832 100644 --- a/docs/src/_includes/layouts/layout.njk +++ b/docs/src/_includes/layouts/layout.njk @@ -12,7 +12,4 @@ layout: layouts/base.njk
{{ content | safe }}
- - -{% from "toast.njk" import toaster %} -{{ toaster() }} \ No newline at end of file + \ No newline at end of file diff --git a/docs/src/_includes/partials/kitchen-sink/toast.njk b/docs/src/_includes/partials/kitchen-sink/toast.njk index 4dd5e3d..35445c6 100644 --- a/docs/src/_includes/partials/kitchen-sink/toast.njk +++ b/docs/src/_includes/partials/kitchen-sink/toast.njk @@ -8,19 +8,18 @@
- - - - -
\ No newline at end of file diff --git a/docs/src/assets/styles.css b/docs/src/assets/styles.css index 05f9d82..1e7684a 100644 --- a/docs/src/assets/styles.css +++ b/docs/src/assets/styles.css @@ -56,7 +56,6 @@ --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; - --font-weight-bold: 700; --tracking-tighter: -0.05em; --tracking-tight: -0.025em; --tracking-normal: 0em; @@ -258,9 +257,6 @@ .invisible { visibility: hidden; } - .visible { - visibility: visible; - } .sr-only { position: absolute; width: 1px; @@ -302,9 +298,6 @@ .right-3 { right: calc(var(--spacing) * 3); } - .left-1\/2 { - left: calc(1/2 * 100%); - } .left-2 { left: calc(var(--spacing) * 2); } @@ -344,27 +337,15 @@ .my-6 { margin-block: calc(var(--spacing) * 6); } - .mt-2 { - margin-top: calc(var(--spacing) * 2); - } .mt-4 { margin-top: calc(var(--spacing) * 4); } - .mt-6 { - margin-top: calc(var(--spacing) * 6); - } .mt-8 { margin-top: calc(var(--spacing) * 8); } .mr-auto { margin-right: auto; } - .mb-1 { - margin-bottom: calc(var(--spacing) * 1); - } - .mb-2 { - margin-bottom: calc(var(--spacing) * 2); - } .mb-4 { margin-bottom: calc(var(--spacing) * 4); } @@ -414,10 +395,6 @@ width: calc(var(--spacing) * 2); height: calc(var(--spacing) * 2); } - .size-2\.5 { - width: calc(var(--spacing) * 2.5); - height: calc(var(--spacing) * 2.5); - } .size-3\.5 { width: calc(var(--spacing) * 3.5); height: calc(var(--spacing) * 3.5); @@ -464,27 +441,9 @@ .h-14 { height: calc(var(--spacing) * 14); } - .h-18 { - height: calc(var(--spacing) * 18); - } - .h-20 { - height: calc(var(--spacing) * 20); - } - .h-24 { - height: calc(var(--spacing) * 24); - } - .h-48 { - height: calc(var(--spacing) * 48); - } .max-h-64 { max-height: calc(var(--spacing) * 64); } - .max-h-\[150px\] { - max-height: 150px; - } - .max-h-\[200px\] { - max-height: 200px; - } .max-h-\[612px\] { max-height: 612px; } @@ -572,19 +531,12 @@ .min-w-56 { min-width: calc(var(--spacing) * 56); } - .min-w-\[8rem\] { - min-width: 8rem; - } .flex-1 { flex: 1; } .shrink-0 { flex-shrink: 0; } - .-translate-x-1\/2 { - --tw-translate-x: calc(calc(1/2 * 100%) * -1); - translate: var(--tw-translate-x) var(--tw-translate-y); - } .-translate-y-1\/2 { --tw-translate-y: calc(calc(1/2 * 100%) * -1); translate: var(--tw-translate-x) var(--tw-translate-y); @@ -614,8 +566,8 @@ .list-decimal { list-style-type: decimal; } - .grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); + .grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); } .grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); @@ -662,9 +614,6 @@ .gap-4 { gap: calc(var(--spacing) * 4); } - .gap-5 { - gap: calc(var(--spacing) * 5); - } .gap-6 { gap: calc(var(--spacing) * 6); } @@ -674,13 +623,6 @@ .gap-10 { gap: calc(var(--spacing) * 10); } - .space-y-1 { - :where(& > :not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse))); - } - } .space-y-2 { :where(& > :not(:last-child)) { --tw-space-y-reverse: 0; @@ -702,9 +644,6 @@ margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse))); } } - .gap-x-1\.5 { - column-gap: calc(var(--spacing) * 1.5); - } .gap-x-2 { column-gap: calc(var(--spacing) * 2); } @@ -754,9 +693,6 @@ .rounded { border-radius: 0.25rem; } - .rounded-\[2px\] { - border-radius: 2px; - } .rounded-full { border-radius: calc(infinity * 1px); } @@ -791,12 +727,6 @@ .border-amber-50 { border-color: var(--color-amber-50); } - .border-border\/50 { - border-color: var(--color-border); - @supports (color: color-mix(in lab, red, red)) { - border-color: color-mix(in oklab, var(--color-border) 50%, transparent); - } - } .border-muted { border-color: var(--color-muted); } @@ -951,10 +881,6 @@ --tw-leading: var(--leading-tight); line-height: var(--leading-tight); } - .font-bold { - --tw-font-weight: var(--font-weight-bold); - font-weight: var(--font-weight-bold); - } .font-medium { --tw-font-weight: var(--font-weight-medium); font-weight: var(--font-weight-medium); @@ -1022,26 +948,16 @@ .underline-offset-4 { text-underline-offset: 4px; } - .opacity-0 { - opacity: 0%; - } .opacity-50 { opacity: 50%; } .opacity-60 { opacity: 60%; } - .opacity-100 { - opacity: 100%; - } .shadow-none { --tw-shadow: 0 0 #0000; box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); } - .shadow-xl { - --tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 8px 10px -6px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); - box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - } .shadow-xs { --tw-shadow: 0 1px 2px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.05)); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); @@ -1075,10 +991,6 @@ --tw-duration: 200ms; transition-duration: 200ms; } - .duration-400 { - --tw-duration: 400ms; - transition-duration: 400ms; - } .outline-none { --tw-outline-style: none; outline-style: none; @@ -1097,17 +1009,6 @@ visibility: visible; } } - .peer-checked\:border { - &:is(:where(.peer):checked ~ *) { - border-style: var(--tw-border-style); - border-width: 1px; - } - } - .peer-checked\:border-blue-500 { - &:is(:where(.peer):checked ~ *) { - border-color: var(--color-blue-500); - } - } .peer-checked\:border-primary { &:is(:where(.peer):checked ~ *) { border-color: var(--color-primary); @@ -1171,13 +1072,6 @@ } } } - .hover\:bg-accent { - &:hover { - @media (hover: hover) { - background-color: var(--color-accent); - } - } - } .hover\:bg-accent\/50 { &:hover { @media (hover: hover) { @@ -1212,13 +1106,6 @@ } } } - .hover\:text-accent-foreground { - &:hover { - @media (hover: hover) { - color: var(--color-accent-foreground); - } - } - } .hover\:text-foreground { &:hover { @media (hover: hover) { @@ -1226,13 +1113,6 @@ } } } - .hover\:text-muted-foreground { - &:hover { - @media (hover: hover) { - color: var(--color-muted-foreground); - } - } - } .hover\:text-zinc-50 { &:hover { @media (hover: hover) { @@ -1397,6 +1277,11 @@ line-height: var(--tw-leading, var(--text-4xl--line-height)); } } + .lg\:grid-cols-2 { + @media (width >= 64rem) { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + } .xl\:block { @media (width >= 80rem) { display: block; @@ -1843,21 +1728,6 @@ [x-cloak] { display: none !important; } - .htmx-indicator { - visibility: hidden; - opacity: 0%; - transition-property: all; - transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); - transition-duration: var(--tw-duration, var(--default-transition-duration)); - transition-behavior: allow-discrete; - } - .htmx-indicator:not(.htmx-request) { - display: none; - } - .htmx-request, .htmx-request.htmx-indicator { - visibility: visible; - opacity: 100%; - } } @layer components { .alert, .alert-destructive { @@ -4296,6 +4166,21 @@ } } } +.htmx-indicator { + visibility: hidden; + opacity: 0%; + transition-property: all; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + transition-behavior: allow-discrete; +} +.htmx-indicator:not(.htmx-request) { + display: none; +} +.htmx-request, .htmx-request.htmx-indicator { + visibility: visible; + opacity: 100%; +} .content { > h2 { margin-top: calc(var(--spacing) * 16); @@ -4325,6 +4210,14 @@ --tw-tracking: var(--tracking-tight); letter-spacing: var(--tracking-tight); } + > h4 { + margin-block: calc(var(--spacing) * 6); + scroll-margin: calc(var(--spacing) * 22); + --tw-font-weight: var(--font-weight-semibold); + font-weight: var(--font-weight-semibold); + --tw-tracking: var(--tracking-tight); + letter-spacing: var(--tracking-tight); + } .prose { margin-block: calc(var(--spacing) * 6); a { diff --git a/docs/src/components/alert-dialog.njk b/docs/src/components/alert-dialog.njk index e999a5c..389b0c1 100644 --- a/docs/src/components/alert-dialog.njk +++ b/docs/src/components/alert-dialog.njk @@ -62,8 +62,18 @@ document.addEventListener('alpine:init', () => { {% from "tabs.njk" import tabs %} diff --git a/docs/src/components/breadcrumb.njk b/docs/src/components/breadcrumb.njk index e2024c1..2f28cef 100644 --- a/docs/src/components/breadcrumb.njk +++ b/docs/src/components/breadcrumb.njk @@ -76,8 +76,18 @@ document.addEventListener('alpine:init', () => { {% from "tabs.njk" import tabs %} diff --git a/docs/src/components/combobox.njk b/docs/src/components/combobox.njk index 84c8680..4b13fc1 100644 --- a/docs/src/components/combobox.njk +++ b/docs/src/components/combobox.njk @@ -72,8 +72,18 @@ document.addEventListener('alpine:init', () => {
- Components with Javascript {% lucide "arrow-right" %} - Use the CLI {% lucide "arrow-right" %} + + Components with Javascript + {% lucide "arrow-right" %} + + + Use the CLI + {% lucide "arrow-right" %} + + + Individual JS file (select.js) + {% lucide "arrow-right" %} +
{% from "tabs.njk" import tabs %} diff --git a/docs/src/components/dialog.njk b/docs/src/components/dialog.njk index 5f17cb8..f19b2b8 100644 --- a/docs/src/components/dialog.njk +++ b/docs/src/components/dialog.njk @@ -60,7 +60,7 @@ document.addEventListener('alpine:init', () => { {% endset %} -{{ code_preview("dialog", code_html | prettyHtml) }} +{{ code_preview("dialog", code_script | prettyHtml ~ code_html | prettyHtml) }}

Usage

@@ -90,8 +90,18 @@ document.addEventListener('alpine:init', () => {
- Components with Javascript {% lucide "arrow-right" %} - Use the CLI {% lucide "arrow-right" %} + + Components with Javascript + {% lucide "arrow-right" %} + + + Use the CLI + {% lucide "arrow-right" %} + + + Individual JS file (dialog.js) + {% lucide "arrow-right" %} +
{% from "tabs.njk" import tabs %} diff --git a/docs/src/components/dropdown-menu.njk b/docs/src/components/dropdown-menu.njk index 6fe94c3..ad5b206 100644 --- a/docs/src/components/dropdown-menu.njk +++ b/docs/src/components/dropdown-menu.njk @@ -114,6 +114,21 @@ document.addEventListener('alpine:init', () => {

You can include the Javascript code provided below, load it as an individual file or use the CLI. Some Alpine.js properties are also required on certain elements (e.g. x-bind, x-data, @click).

+
+ + Components with Javascript + {% lucide "arrow-right" %} + + + Use the CLI + {% lucide "arrow-right" %} + + + Individual JS file (dropdown-menu.js) + {% lucide "arrow-right" %} + +
+ {% from "tabs.njk" import tabs %} {% set tabsets = [ { tab: "HTML", panel: code_block(code_html | prettyHtml, class="") }, diff --git a/docs/src/components/popover.njk b/docs/src/components/popover.njk index 1584830..38809a4 100644 --- a/docs/src/components/popover.njk +++ b/docs/src/components/popover.njk @@ -92,8 +92,18 @@ document.addEventListener('alpine:init', () => {
- Components with Javascript {% lucide "arrow-right" %} - Use the CLI {% lucide "arrow-right" %} + + Components with Javascript + {% lucide "arrow-right" %} + + + Use the CLI + {% lucide "arrow-right" %} + + + Individual JS file (popover.js) + {% lucide "arrow-right" %} +
{% from "tabs.njk" import tabs %} diff --git a/docs/src/components/select.njk b/docs/src/components/select.njk index 12850bb..2e549a6 100644 --- a/docs/src/components/select.njk +++ b/docs/src/components/select.njk @@ -107,8 +107,18 @@ document.addEventListener('alpine:init', () => {
- Components with Javascript {% lucide "arrow-right" %} - Use the CLI {% lucide "arrow-right" %} + + Components with Javascript + {% lucide "arrow-right" %} + + + Use the CLI + {% lucide "arrow-right" %} + + + Individual JS file (select.js) + {% lucide "arrow-right" %} +
{% from "tabs.njk" import tabs %} diff --git a/docs/src/components/sidebar.njk b/docs/src/components/sidebar.njk index e21245a..6731393 100644 --- a/docs/src/components/sidebar.njk +++ b/docs/src/components/sidebar.njk @@ -43,6 +43,21 @@ toc:

You can include the Javascript code provided below, load it as an individual file or use the CLI. Some Alpine.js properties are also required on certain elements (e.g. x-bind, x-data, @click).

+
+ + Components with Javascript + {% lucide "arrow-right" %} + + + Use the CLI + {% lucide "arrow-right" %} + + + Individual JS file (sidebar.js) + {% lucide "arrow-right" %} + +
+ {% set code_html %} {% set icon_square_terminal %}{% lucide "square-terminal" %}{% endset %} {% set icon_bot %}{% lucide "bot" %}{% endset %} @@ -69,6 +84,7 @@ toc: menu=menu ) }}
+

Content

{% endset %} diff --git a/docs/src/components/tabs.njk b/docs/src/components/tabs.njk index d61a107..bfcb198 100644 --- a/docs/src/components/tabs.njk +++ b/docs/src/components/tabs.njk @@ -110,8 +110,18 @@ document.addEventListener('alpine:init', () => {
- Components with Javascript {% lucide "arrow-right" %} - Use the CLI {% lucide "arrow-right" %} + + Components with Javascript + {% lucide "arrow-right" %} + + + Use the CLI + {% lucide "arrow-right" %} + + + Individual JS file (tabs.js) + {% lucide "arrow-right" %} +
{% from "tabs.njk" import tabs %} diff --git a/docs/src/components/toast.njk b/docs/src/components/toast.njk index c56a335..30baf29 100644 --- a/docs/src/components/toast.njk +++ b/docs/src/components/toast.njk @@ -2,35 +2,252 @@ layout: layouts/page.njk title: Toast description: A succinct message that is displayed temporarily. +toc: + - label: Usage + id: usage + children: + - label: HTML + Javascript + id: usage-default + children: + - label: Append a toast + id: usage-append-toast + - label: Use $toast() + id: usage-use-magic-method + - label: Jinja and Nunjucks + id: usage-macro --- +{% from "toast.njk" import toaster, toast %} {% from "macros/code_preview.njk" import code_preview %} -{% set code %} -
{% endset %} -{{ code_preview("toast-htmx", code, "max-w-md") }} + Toast from backend (with HTMX) +{% endset %} +{{ code_preview("toast-htmx", code_htmx, "max-w-md") }} -{% from "macros/code_preview.njk" import code_preview %} -{% set code %} {% endset %} -{{ code_preview("toast-alpine", code, "max-w-md") }} \ No newline at end of file +{{ code_preview("toast-alpine", code_alpine, "max-w-md") }} + +

Usage

+ +

HTML + Javascript

+ +
+ {% lucide "circle-alert" %} +

This component requires Javascript.

+
+ +
+

To use toasts, you will first need to set up the toaster code to the end of your <body> (see HTML below).

+ +

The <template id="toast-template"> bit is only required if you plan on using the $toast() method (see below).

+ +

You will also need to include the Javascript code provided below, load it as an individual file or use the CLI. Some Alpine.js properties are also required on certain elements (e.g. x-bind, x-data, @click).

+
+ +
+ + Components with Javascript + {% lucide "arrow-right" %} + + + Use the CLI + {% lucide "arrow-right" %} + + + Individual JS file (toast.js) + {% lucide "arrow-right" %} + +
+ + +{% set code_script %} + +{% endset %} + +{% set code_html_toaster %}{{ toaster() }}{% endset %} + +{% from "tabs.njk" import tabs %} +{% set tabsets = [ + { tab: "HTML", panel: code_block(code_html_toaster | prettyHtml, class="") }, + { tab: "Javascipt (Alpine.js)", panel: code_block(code_script | prettyHtml, class="") } +] %} +{{ tabs(id="popover", tabsets=tabsets) }} + +
+

Once that's in place, we can do one of two things:

+ + +
+ +

Append a toast

+ +
+

To display a toast, just append the following to the toaster:

+
+ +{% set code_toast_simple %}
+
+

This is a toast.

+
+
{% endset %} + +{{ code_block(code_toast_simple | prettyHtml, "html") }} + +
+

You can implement the layout you want within the toast, but here is the standard format used in the examples above:

+
+ +{% set code_toast %}{{ toast( + category="success", + title="Success", + description="A success toast called from the front-end.", + action={ + label: "Dismiss", + click: "close()" + } +) }}{% endset %} +{{ code_block(code_toast | prettyHtml, "html") }} + +
+

When setting up x-data, you can pass a config object with `category` (e.g. "success", "error", "info", "warning") and `duration` (in milliseconds). By default, the duration will be 3 seconds, and 5 seconds for errors.

+ +

This approach is used in the first example with HTMX: when the button is clicked, we retrieve the a fragment that contains the markup for the toast and append it to #toaster.

+
+ +{% set code_htmx %}{% endset %} + +

Use $toast()

+ +
+

If you want to display a toast directly from the front-end, you can use the $toast() Alpine.js magic method. This is what we're doing in the second example above:

+
+ +{% set code_magic_method %} +{% endset %} +{{ code_block(code_magic_method, "html") }} + +
+

The $toast() method accepts a config object with the following properties:

+ + +
+ +

Jinja and Nunjucks

+ +
+

You can use the toaster() and toast() Nunjucks or Jinja macros for this component.

+
+ +
+ + Use Nunjucks or Jinja macros + {% lucide "arrow-right" %} + + + Jinja macro + {% lucide "arrow-right" %} + + + Nunjucks macro + {% lucide "arrow-right" %} + +
+ +{% set raw_code_toaster %}{% raw %}{% from "toast.njk" import toaster %} +{{ toaster( + toasts=[ + { + type: "success", + title: "Success", + description: "A success toast called from the front-end.", + action: { label: "Dismiss", click: "close()" } + }, + { + type: "info", + title: "Info", + description: "An info toast called from the front-end.", + action: { label: "Dismiss", click: "close()" } + } + ] +) }}{% endraw %}{% endset%} + +{% set raw_code_toast %}{% raw %}{% from "toast.njk" import toast %} +{{ toast( + title="Event has been created", + description="Sunday, December 03, 2023 at 9:00 AM", + cancel={ label: "Undo", click: "close()" } +) }}{% endraw %}{% endset %} + +{% from "tabs.njk" import tabs %} +{% set tabsets = [ + { tab: "toaster()", panel: code_block(raw_code_toaster, "jinja", class="") }, + { tab: "toast()", panel: code_block(raw_code_toast, "jinja", class="") } +] %} +{{ tabs(id="macros", tabsets=tabsets) }} \ No newline at end of file diff --git a/docs/src/fragments/toast/error.njk b/docs/src/fragments/toast/error.njk index 18c59b1..23aee0a 100644 --- a/docs/src/fragments/toast/error.njk +++ b/docs/src/fragments/toast/error.njk @@ -1,7 +1,6 @@ -{% from "toast.njk" import toaster %} -{% set toasts = [{ - category: "error", - title: "Event has not been created", - cancel: { label: "Dismiss", click: "close()" } -}] %} -{{ toaster(toasts=toasts, is_fragment=true) }} \ No newline at end of file +{% from "toast.njk" import toast %} +{{ toast( + category="error", + title="Event has not been created", + cancel={ label: "Dismiss", click: "close()" } +) }} \ No newline at end of file diff --git a/docs/src/fragments/toast/info.njk b/docs/src/fragments/toast/info.njk index b4a9d33..fe5450f 100644 --- a/docs/src/fragments/toast/info.njk +++ b/docs/src/fragments/toast/info.njk @@ -1,6 +1,5 @@ -{% from "toast.njk" import toaster %} -{% set toasts = [{ - category: "info", - title: "Be at the area 10 minutes before the event time" -}] %} -{{ toaster(toasts=toasts, is_fragment=true) }} \ No newline at end of file +{% from "toast.njk" import toast %} +{{ toast( + category="info", + title="Be at the area 10 minutes before the event time" +) }} diff --git a/docs/src/fragments/toast/success.njk b/docs/src/fragments/toast/success.njk index 4fca35d..8dedd4a 100644 --- a/docs/src/fragments/toast/success.njk +++ b/docs/src/fragments/toast/success.njk @@ -1,7 +1,6 @@ -{% from "toast.njk" import toaster %} -{% set toasts = [{ - title: "Event has been created", - description: "Sunday, December 03, 2023 at 9:00 AM", - cancel: { label: "Undo", click: "close()" } -}] %} -{{ toaster(toasts=toasts, is_fragment=true) }} \ No newline at end of file +{% from "toast.njk" import toast %} +{{ toast( + title="Event has been created", + description="Sunday, December 03, 2023 at 9:00 AM", + cancel={ label: "Undo", click: "close()" } +) }} \ No newline at end of file diff --git a/docs/src/fragments/toast/warning.njk b/docs/src/fragments/toast/warning.njk index 8c890d4..8b3b020 100644 --- a/docs/src/fragments/toast/warning.njk +++ b/docs/src/fragments/toast/warning.njk @@ -1,6 +1,5 @@ -{% from "toast.njk" import toaster %} -{% set toasts = [{ - category: "warning", - title: "Event start time cannot be earlier than 8am" -}] %} -{{ toaster(toasts=toasts, is_fragment=true) }} \ No newline at end of file +{% from "toast.njk" import toast %} +{{ toast( + category="warning", + title="Event start time cannot be earlier than 8am" +) }} \ No newline at end of file diff --git a/docs/src/index.njk b/docs/src/index.njk index 5df0416..bec77d1 100644 --- a/docs/src/index.njk +++ b/docs/src/index.njk @@ -16,7 +16,7 @@ layout: layouts/layout.njk -
+
diff --git a/src/css/basecoat.css b/src/css/basecoat.css index 64f355e..f9f6099 100644 --- a/src/css/basecoat.css +++ b/src/css/basecoat.css @@ -150,17 +150,6 @@ [x-cloak] { display: none !important; } - /* HTMX */ - .htmx-indicator { - @apply invisible opacity-0 transition-discrete transition-all; - } - .htmx-indicator:not(.htmx-request) { - @apply hidden; - } - .htmx-request, - .htmx-request.htmx-indicator { - @apply visible opacity-100; - } } /* Alert */ diff --git a/src/js/toast.js b/src/js/toast.js index 0580453..a66bebe 100644 --- a/src/js/toast.js +++ b/src/js/toast.js @@ -36,6 +36,11 @@ window.basecoat.registerToast = function(Alpine) { this.open = false; this.$el.blur(); }, + executeAction(actionString) { + if (actionString) { + Alpine.evaluate(this.$el, actionString); + } + }, $toastBindings: { ['@mouseenter']() { this.$store.toaster.isPaused = true }, @@ -50,7 +55,7 @@ window.basecoat.registerToast = function(Alpine) { const template = document.getElementById('toast-template'); if (!toaster) { - console.error(`Toaster container with id #${targetId} not found.`); + console.error(`Toaster container with id #${toasterId} not found.`); return; } if (!template) { diff --git a/src/nunjucks/toast.njk b/src/nunjucks/toast.njk index 152e1f0..10e9e8a 100644 --- a/src/nunjucks/toast.njk +++ b/src/nunjucks/toast.njk @@ -3,17 +3,7 @@ Can render the initial container or be used with htmx OOB swaps to add toasts dynamically. @param id {string} [optional] [default="toaster"] - Unique identifier for the toaster container. - @param toasts {array} [optional] - An array of toast objects to render initially. - Each toast object can have: - - category {string} [optional]: Type of toast ('success', 'error', 'info', 'warning'). Determines icon and ARIA role. - - title {string} [optional]: The main title text of the toast. - - description {string} [optional]: The secondary description text. - - duration {number} [optional] [default=5000]: Duration in milliseconds before the toast auto-dismisses. - - action {object} [optional]: Defines an action button. - - label {string}: Button text. - - click {string}: JavaScript code to execute on click (e.g., '$dispatch(\'custom-event\')'). - - url {string}: URL for an anchor link button. - - cancel {object} [optional]: Defines a cancel/dismiss button (similar structure to action). + @param toasts {array} [optional] - An array of toast objects to render initially. See the toast() macro for more details. @param main_attrs {object} [optional] - Additional HTML attributes for the main toaster container div. @param is_fragment {boolean} [optional] [default=false] - If true, renders only the toast elements with hx-swap-oob="beforeend", suitable for htmx responses. Skips script and template inclusion. #} @@ -23,13 +13,6 @@ main_attrs=None, is_fragment=false ) %} -{% set icons = { - 'success': '', - 'error': '', - 'info': '', - 'warning': '' -} %} -
-{% for toast in toasts %} -
-
-
- {% if toast.category in ["error", "success", "info", "warning"] %} - {{ icons[toast.category] | safe }} - {% endif %} -
- {% if toast.title %} -

{{ toast.title }}

- {% endif %} - {% if toast.description %} -

{{ toast.description }}

- {% endif %} -
- {% if toast.action or toast.cancel %} -
- {% if toast.action %} - {% if toast.action.click %} - - {% elif toast.action.url %} - {{ toast.action.label }} - {% endif %} - {% endif %} - {% if toast.cancel %} - {% if toast.cancel.click %} - - {% elif toast.cancel.url %} - {{ toast.cancel.label }} - {% endif %} - {% endif %} -
- {% endif %} -
-
-
+{% for item in toasts %} + {{ toast( + category=item.category, + title=item.title, + description=item.description, + action=item.action, + cancel=item.cancel + ) }} {% endfor %}
@@ -113,16 +46,16 @@
@@ -153,7 +86,7 @@ @@ -165,9 +98,101 @@ > +
{% endif %} -{% endmacro %} \ No newline at end of file +{% endmacro %} + +{# + Renders a single toast message. + + @param category {string} [optional] [default="success"] - Type of toast ('success', 'error', 'info', 'warning'). Determines icon and ARIA role. + @param title {string} [optional] - The main title text of the toast. + @param description {string} [optional] - The secondary description text. + @param action {object} [optional] - Defines an action button. + - label {string}: Button text. + - click {string}: JavaScript code to execute on click (e.g., '$dispatch(\'custom-event\')'). + - url {string}: URL for an anchor link button. + @param cancel {object} [optional] - Defines a cancel/dismiss button (similar structure to action). + - label {string}: Button text. + - click {string}: JavaScript code to execute on click (e.g., '$dispatch(\'custom-event\')'). + - url {string}: URL for an anchor link button. +#} +{% macro toast( + category="success", + title="", + description="", + action=None, + cancel=None +) %} +
+
+
+ {% if category in ["error", "success", "info", "warning"] %} + {{ toast_icons[category] | safe }} + {% endif %} +
+ {% if title %} +

{{ title }}

+ {% endif %} + {% if description %} +

{{ description }}

+ {% endif %} +
+ {% if action or cancel %} +
+ {% if action %} + {% if action.click %} + + {% elif action.url %} + {{ action.label }} + {% endif %} + {% endif %} + {% if cancel %} + {% if cancel.click %} + + {% elif cancel.url %} + {{ toast.cancel.label }} + {% endif %} + {% endif %} +
+ {% endif %} +
+
+
+{% endmacro %} + +{% set toast_icons = { + 'success': '', + 'error': '', + 'info': '', + 'warning': '' +} %} \ No newline at end of file