Skip to content

modal

aa-modal-group is a fixed-position dialog container. Its descendants — [aa-modal-name] cards — open when a button with the matching aa-modal-target is clicked anywhere in the page. The card’s own aa-animate (e.g. fade-up, slide-left) handles its enter; everything inside the card with aa-animate plays automatically too via trigger inference, and reverses when the modal closes.

AttributeWhere it goesNotes
aa-modal-groupOuter fixed-position containerBounds the feature; one group can contain multiple modals.
aa-modal-group-statusSet by the lib on the group"active" while any modal in the group is open, otherwise "not-active".
aa-modal-name="<id>"Each modal cardUnique within a group. Carries the card’s own aa-animate for the enter animation.
aa-modal-statusSet by the lib on the card"active" / "not-active". Use for CSS variants per-card.
aa-modal-target="<id>"Trigger buttonClick opens the matching modal. Multiple triggers per modal are fine.
aa-modal-closeAny descendant of the groupClick closes the active modal. Backdrop typically gets both aa-modal-backdrop and aa-modal-close.
aa-modal-backdropOptional dim elementFades 0 → 1 on open, 1 → 0 on close, independent of the card’s own animation.
AttributeDefaultNotes
aa-duration(init)Open duration in seconds. Read from the group, then overridden per card. Close runs at 2×.
  • Scroll lock while any modal is open — lenis.stop() if Lenis is on the page, else body.aa-modal-locked { overflow: hidden }.
  • ESC key closes the active modal.
  • Focus trap — Tab/Shift+Tab cycles within the card.
  • Auto-focus the first focusable element after the open animation finishes.
  • Restore focus to the original trigger button when the modal closes.
  • Inner animations — anything inside the card with aa-animate plays on modal-active and reverses on modal-inactive automatically. Reverse runs at 2× forward speed (REVERSE_TIME_SCALE).

gsap. Inner aa-animate elements bring their own plugin requirements (e.g. SplitText for text-*).

Lenis hijacks page wheel events. When your modal card is taller than the viewport, wrap the scrollable inner section in data-lenis-prevent so wheel events scroll natively inside the card. No JavaScript needed — Lenis honors that attribute itself.

<div class="modal-card" aa-modal-name="x">
<div class="modal-scroll" data-lenis-prevent>
<!-- tall content -->
</div>
</div>

aa-modal-group wraps the dialog. The card has aa-animate="fade-up" with aa-duration="0.5". Inner heading runs text-blur on chars; paragraphs run text-slide-up with aa-split="lines mask". Click the close icon, the dim backdrop, or press Escape.

Live demo — Side panel from the right (full height)

Section titled “Live demo — Side panel from the right (full height)”

Same primitives, different layout. The card uses aa-animate="slide-left" (slides in from the right edge) and is positioned full-height on the right side of the viewport. The inner .modal-scroll is still data-lenis-prevent so wheel events scroll the panel natively while the body stays locked.

Live demo — Form modal (auto-focus first input)

Section titled “Live demo — Form modal (auto-focus first input)”

Same primitives, but with a small form inside. After the open animation finishes, the modal feature focuses the first focusable element — here the email input — so users can start typing immediately. Tab/Shift+Tab cycles between the form fields and the close button without leaving the modal.