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.
Structural attributes
Section titled “Structural attributes”| Attribute | Where it goes | Notes |
|---|---|---|
aa-modal-group | Outer fixed-position container | Bounds the feature; one group can contain multiple modals. |
aa-modal-group-status | Set by the lib on the group | "active" while any modal in the group is open, otherwise "not-active". |
aa-modal-name="<id>" | Each modal card | Unique within a group. Carries the card’s own aa-animate for the enter animation. |
aa-modal-status | Set by the lib on the card | "active" / "not-active". Use for CSS variants per-card. |
aa-modal-target="<id>" | Trigger button | Click opens the matching modal. Multiple triggers per modal are fine. |
aa-modal-close | Any descendant of the group | Click closes the active modal. Backdrop typically gets both aa-modal-backdrop and aa-modal-close. |
aa-modal-backdrop | Optional dim element | Fades 0 → 1 on open, 1 → 0 on close, independent of the card’s own animation. |
Config attributes
Section titled “Config attributes”| Attribute | Default | Notes |
|---|---|---|
aa-duration | (init) | Open duration in seconds. Read from the group, then overridden per card. Close runs at 2×. |
What you get for free
Section titled “What you get for free”- Scroll lock while any modal is open —
lenis.stop()if Lenis is on the page, elsebody.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-animateplays onmodal-activeand reverses onmodal-inactiveautomatically. Reverse runs at 2× forward speed (REVERSE_TIME_SCALE).
Required GSAP plugins
Section titled “Required GSAP plugins”gsap. Inner aa-animate elements bring their own plugin requirements (e.g. SplitText for text-*).
Inner-content scrolling with Lenis
Section titled “Inner-content scrolling with Lenis”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>Live demo — Centered modal
Section titled “Live demo — Centered modal”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.