dev.metalisp.sbt/src/component/alert.lisp
2023-09-01 15:02:48 +02:00

87 lines
3 KiB
Common Lisp

;;;; alert.lisp
;;;;
;;;; This file defines a package for generating Bootstrap alert components
;;;; using Common Lisp macros.
(defpackage cl-sbt/alert
(:use :cl)
(:export
:btn
:alert
:alert-primary
:alert-secondary
:alert-success
:alert-danger
:alert-warning
:alert-info
:alert-light
:alert-dark
:alert-dismiss-primary
:alert-dismiss-secondary
:alert-dismiss-success
:alert-dismiss-danger
:alert-dismiss-warning
:alert-dismiss-info
:alert-dismiss-light
:alert-dismiss-dark))
(in-package :cl-sbt/alert)
(defmacro btn ()
"This macro generates the close button used in a Bootstrap alert when it is set to be dismissible."
`(spinneret:with-html
(:button :type "button"
:class "btn-close"
:data-bs-dismiss "alert"
:aria-label "Close")))
(defmacro alert ((&key (color "primary") (dismissible nil)) &body body)
"This macro generates a Bootstrap alert component.
COLOR: Specifies the alert type. Can be 'primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', or 'dark'. Defaults to 'primary'.
DISMISSIBLE: Specifies whether the alert is dismissible. If true, the alert includes a close button.
BODY: Specifies the content of the alert.
Example usage:
To create a basic alert of type 'danger':
(alert (:role \"danger\") \"This is a dangerous alert. Be careful!\")
To create a dismissible alert of type 'success':
(alert (:type \"success\" :dismissible t) \"Congratulations! You've successfully created a dismissible alert.\")"
`(spinneret:with-html
(:div :role "alert"
:class ,(concatenate 'string (format nil "alert alert-~a" color)
(if (null dismissible) nil " alert-dismissible"))
,(if (null dismissible) nil `(btn))
,@body)))
(defmacro define-alert (color &optional (dismissible nil))
"This macro defines a new macro for creating a Bootstrap alert of a specific type.
COLOR: The color of the alert (like 'primary', 'secondary', 'success', etc.).
DISMISSIBLE: (optional) Whether the alert should be dismissible.
The newly defined macro, when called, will generate HTML for a Bootstrap
alert of the specified type and dismissibility."
(let* ((macro-name (intern (string-upcase (concatenate 'string "ALERT-" (if (null dismissible) "" "DISMISS-") color)))))
`(defmacro ,macro-name (&body body)
`(alert (:color ,,color :dismissible ,,dismissible) ,@body))))
(defmacro define-alerts (colors)
"This macro generates specific alert macros based on the provided names.
COLORS: A list of alert type names. For each name in this list, a macro will
be generated: a non-dismissible alert and a dismissible alert of the
specified type."
`(progn
,@(loop for color in colors
for color-name = (string-downcase (string color))
collect `(progn
(define-alert ,color-name)
(define-alert ,color-name t)))))
(define-alerts (primary secondary success danger warning info light dark))