2023-09-01 13:44:27 +02:00
|
|
|
;;;; accordion.lisp
|
|
|
|
;;;;
|
|
|
|
;;;; This file defines a package for generating Bootstrap accordion components
|
2023-09-09 08:20:17 +02:00
|
|
|
;;;; using Common Lisp macros.
|
2023-07-11 15:59:52 +02:00
|
|
|
|
2023-12-18 11:34:54 +01:00
|
|
|
(defpackage dev.metalisp.sbt/component/accordion
|
2023-09-01 15:20:45 +02:00
|
|
|
(:documentation "A package for generating Bootstrap accordions.")
|
2023-07-11 15:59:52 +02:00
|
|
|
(:use :cl)
|
|
|
|
(:export
|
|
|
|
:header
|
|
|
|
:collapse
|
|
|
|
:item
|
|
|
|
:accordion))
|
|
|
|
|
2023-12-18 11:34:54 +01:00
|
|
|
(in-package :dev.metalisp.sbt/component/accordion)
|
2023-07-11 15:59:52 +02:00
|
|
|
|
2023-09-01 09:51:00 +02:00
|
|
|
(defun header (target name show)
|
2023-07-11 15:59:52 +02:00
|
|
|
"This macro generates a Bootstrap header for an accordion item.
|
|
|
|
|
2023-09-01 09:51:00 +02:00
|
|
|
TARGET: The id of the collapse this header controls.
|
|
|
|
|
|
|
|
NAME: The text that will be displayed on this header.
|
|
|
|
|
|
|
|
SHOW: A boolean indicating whether the collapse controlled by this header
|
|
|
|
should be shown when the accordion first loads. If true, the 'aria-expanded'
|
|
|
|
attribute will be 'true'.
|
|
|
|
|
|
|
|
Example:
|
|
|
|
(header \"collapseOne\" \"Heading\" t)"
|
2023-09-01 16:42:26 +02:00
|
|
|
(let ((target-str (concatenate 'string "#" target))
|
|
|
|
(show-str (if (null show) "false" "true")))
|
2023-09-01 09:51:00 +02:00
|
|
|
(spinneret:with-html
|
|
|
|
(:h2 :class "accordion-header"
|
|
|
|
(:button :class "accordion-button"
|
|
|
|
:type "button"
|
|
|
|
:data-bs-toggle "collapse"
|
2023-09-01 16:42:26 +02:00
|
|
|
:data-bs-target target-str
|
|
|
|
:aria-expanded show-str
|
|
|
|
:aria-controls target-str
|
2023-09-01 09:51:00 +02:00
|
|
|
name)))))
|
2023-07-08 12:49:10 +02:00
|
|
|
|
2023-07-11 15:59:52 +02:00
|
|
|
(defmacro collapse (parent id show &body body)
|
|
|
|
"This macro generates a Bootstrap collapse for an accordion item.
|
|
|
|
|
2023-09-01 10:28:20 +02:00
|
|
|
PARENT: The id of the parent element that contains the collapse.
|
2023-07-13 21:43:34 +02:00
|
|
|
|
2023-09-01 10:28:20 +02:00
|
|
|
ID: The unique id for this collapse.
|
2023-07-11 15:59:52 +02:00
|
|
|
|
2023-09-01 10:28:20 +02:00
|
|
|
SHOW: A boolean indicating whether the collapse should be shown when the
|
|
|
|
accordion first loads. If true, 'show' will be added to the classes of the
|
|
|
|
collapse.
|
2023-07-11 15:59:52 +02:00
|
|
|
|
2023-09-01 10:28:20 +02:00
|
|
|
BODY: The contents of the collapse.
|
2023-07-11 15:59:52 +02:00
|
|
|
|
2023-09-01 10:28:20 +02:00
|
|
|
Example:
|
|
|
|
(collapse \"accordionExample\" \"collapseOne\" t \"Some content\")"
|
|
|
|
(let ((class (concatenate 'string "accordion-collapse collapse" (if (null show) nil " show")))
|
|
|
|
(parent (concatenate 'string "#" parent)))
|
|
|
|
`(spinneret:with-html
|
|
|
|
(:div :id ,id
|
|
|
|
:class ,class
|
|
|
|
:data-bs-parent ,parent
|
|
|
|
(:div :class "accordion-body"
|
|
|
|
,@body)))))
|
2023-07-08 22:09:06 +02:00
|
|
|
|
2023-07-11 15:59:52 +02:00
|
|
|
(defmacro item (&body body)
|
|
|
|
"This macro generates a Bootstrap accordion item.
|
|
|
|
|
2023-09-01 10:30:45 +02:00
|
|
|
BODY: The contents of the accordion item.
|
2023-07-11 15:59:52 +02:00
|
|
|
|
2023-09-01 10:30:45 +02:00
|
|
|
Example:
|
|
|
|
(item (header \"collapseOne\" \"Heading\" t) (collapse \"accordionExample\" \"collapseOne\" t \"Some content\"))"
|
2023-07-08 14:31:53 +02:00
|
|
|
`(spinneret:with-html
|
|
|
|
(:div :class "accordion-item"
|
|
|
|
,@body)))
|
2023-07-01 16:30:10 +02:00
|
|
|
|
2024-02-03 18:48:00 +01:00
|
|
|
(defmacro accordion-old (id &rest rest)
|
2023-07-11 15:59:52 +02:00
|
|
|
"This macro generates an accordion-style collapsible list with Bootstrap.
|
|
|
|
|
2023-09-01 10:30:45 +02:00
|
|
|
ID: Specifies a unique identifier for the accordion. Defaults to 'accordionExample'.
|
2023-07-11 15:59:52 +02:00
|
|
|
|
2023-09-01 10:30:45 +02:00
|
|
|
REST: Specifies a list of accordion items. Each item is a plist with the following keys:
|
|
|
|
- :target: Specifies a unique identifier for the accordion item.
|
|
|
|
- :name: Specifies the name of the accordion item.
|
|
|
|
- :show: Specifies whether the accordion item should be displayed by default.
|
|
|
|
- :content: Specifies the content of the accordion item.
|
2023-07-11 15:59:52 +02:00
|
|
|
|
2023-09-01 10:30:45 +02:00
|
|
|
Example:
|
2023-09-01 11:23:33 +02:00
|
|
|
(accordion \"accordionExample\"
|
|
|
|
(:target \"collapseOne\" :name \"Accordion Item #1\" :show t :content \"This is the first item's accordion body.\")
|
|
|
|
(:target \"collapseTwo\" :name \"Accordion Item #2\" :content \"This is the second item's accordion body.\")
|
|
|
|
(:target \"collapseThree\" :name \"Accordion Item #3\" :content \"This is the second item's accordion body.\"))"
|
2023-07-08 14:31:53 +02:00
|
|
|
`(spinneret:with-html
|
|
|
|
(:div :class "accordion"
|
|
|
|
:id ,id
|
|
|
|
,@(loop for item in rest
|
2023-07-08 22:09:06 +02:00
|
|
|
collect (destructuring-bind (&key target name show content) item
|
2023-07-11 15:59:52 +02:00
|
|
|
`(item (header ,target ,name ,show)
|
|
|
|
(collapse ,id ,target ,show ,content)))))))
|
2024-02-03 18:48:00 +01:00
|
|
|
|
|
|
|
(defmacro accordion ((&key id flush) &body body)
|
|
|
|
(let ((class (concatenate 'string "accordion" (when flush " accordion-flush"))))
|
2024-02-03 18:53:45 +01:00
|
|
|
`(spinneret:with-html
|
|
|
|
(:div :class ,class
|
|
|
|
:id ,id
|
|
|
|
,@(loop for (title . content) in body
|
|
|
|
collect `(:div :class "accordion-item"
|
|
|
|
(:h5 :class "accordion-header" ,title)
|
|
|
|
(:div :class "accordion-body" ,content)))))))
|