Modal
Modals are overlays used to display content on a layer above the page, preventing users from interacting with content behind the modal.
Variants
Basic
Basic modals contain a title, a body of content, and a footer with buttons.Destructive
Contain a title, a body of content, and a footer with buttons. The call to action button in the footer contain error styling to indicate that the action is destructive.
Header Icon
Modals can contain an icon in the header.
Header Image
Modals can contain a thumbnail image in the header.
Subheader
Modals can contain a subheader.
Footer
Modals contain a footer that can contain buttons and links
Footer Aside
The footer aside is a section of the footer that can contain additional buttons or links.
Scrollable Content
Modals can be configured to allow scrolling of content. This option is useful when the header and footer needs to visible contain actions.
Sizes
Modal widths can be configured to be extra small, small, medium, or large.
Fullscreen
Modals can be configured to take up the full screen.
Animated
Modals can be configured to animate in from the top, left, or right.
Asynchronous Modal Setup
- Use Case:
- Load modals asynchronously, ideal for scenarios like editing product details in a list.
- Setup:
- Include a
SageModal
stub in the view with an ID and configurations. - Utilize
remove_content_on_close: true
for best practices. - Add default content (e.g.,
SageLoader
) in theSageModal
stub. - Create an endpoint delivering modal content (wrapped by
SageModalContent
).
- Include a
- Trigger Configuration:
- In the main view, add clickable triggers (e.g., buttons).
- Configure triggers with:
data-js-modaltrigger="[modal-id]"
: ID of theSageModal
stub.data-js-remote-url="[url]"
: Endpoint delivering the content.
- Remote URLs:
- Set remote URLs on both the main
SageModal
stub and triggers. - Trigger's
remote_url
overrides the stub's, but stub's is used if trigger has none. - Default content inside
SageModal
is replaced by asynchronousremote_url
content.
- Set remote URLs on both the main
Remote URLs
- Modal A demonstrates
remote_url
prop usage onSageModal
- Modal B and C demonstrate usage of the
data-js-remote-url
key withinhtml_attributes
. The value of theasync_path()
equals the all content in this path residing withinSageModalContent
Events (monitor in browser console)
Use these events for hooking into modal functionality using JS event listeners.
Event name | Event type | Description |
---|---|---|
|
global |
Fires when any modal has been opened |
|
global |
Fires when any modal has been closed |
|
instance | Fires immediately when a modal has been opened |
|
instance |
Fires after a modal has loaded. If |
Sage Component
SageModal
<h2>Variants</h2>
<h3>Basic</h3>
Basic modals contain a title, a body of content, and a footer with buttons.
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Basic",
attributes: {
"data-js-modaltrigger": "cool-modal",
}
} %>
<%= sage_component SageModal, { id: "cool-modal"} do %>
<%= sage_component SageModalContent, {
title: "Modal title",
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<h3>Destructive</h3>
<p>Contain a title, a body of content, and a footer with buttons. The call to action button
in the footer contain error styling to indicate that the action is destructive.</p>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Destructive",
attributes: {
"data-js-modaltrigger": "cool-modal-destructive",
}
} %>
<%= sage_component SageModal, { id: "cool-modal-destructive" } do %>
<%= sage_component SageModalContent, {
title: "Delete item",
help_content: "<p>Are you sure you want to delete this item? This action cannot be undone.</p>",
help_link: {
href: "#",
name: "Link"
}
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Are you sure you want to delete this item? This action cannot be undone.</p>
<% content_for :sage_footer do %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "danger",
icon: { name: "trash", style: "left" },
value: "Delete",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<h3>Header Icon</h3>
<p>Modals can contain an icon in the header.</p>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Subheader",
attributes: {
"data-js-modaltrigger": "cool-modal-header-icon",
}
} %>
<%= sage_component SageModal, {id: "cool-modal-header-icon" } do %>
<%= sage_component SageModalContent, {
header_icon: {
name: "check-circle",
color: "sage-400"
},
title: "Modal header",
subheader: "This is subheader copy for your viewing pleasure",
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<h3>Header Image</h3>
<p>Modals can contain a thumbnail image in the header.</p>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Subheader",
attributes: {
"data-js-modaltrigger": "cool-modal-header-image",
}
} %>
<%= sage_component SageModal, {id: "cool-modal-header-image" } do %>
<%= sage_component SageModalContent, {
header_image: "avatar/joshua_wilson.png",
title: "Modal header",
subheader: "This is subheader copy for your viewing pleasure",
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<h3>Subheader</h3>
<p>Modals can contain a subheader.</p>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Subheader",
attributes: {
"data-js-modaltrigger": "cool-modal-subheader",
}
} %>
<%= sage_component SageModal, { allow_scroll: true, id: "cool-modal-subheader" } do %>
<%= sage_component SageModalContent, {
title: "Modal header",
subheader: "This is subheader copy for your viewing pleasure",
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<h3>Footer</h3>
<p>Modals contain a footer that can contain buttons and links</p>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Footer",
attributes: {
"data-js-modaltrigger": "cool-modal-footer",
}
} %>
<%= sage_component SageModal, { id: "cool-modal-footer" } do %>
<%= sage_component SageModalContent, {
title: "Modal Header",
help_content: "<p>Add a description of the content you're showing in the modal.</p>",
help_link: {
href: "#",
name: "Link"
}
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<% content_for :sage_footer_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Link",
attributes: { "data-js-modal": true }
} %>
<% end %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<h3>Footer Aside</h3>
<p>The footer aside is a section of the footer that can contain additional buttons or links.</p>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Footer Aside",
attributes: {
"data-js-modaltrigger": "cool-modal-footer-aside",
}
} %>
<%= sage_component SageModal, { id: "cool-modal-footer-aside" } do %>
<%= sage_component SageModalContent, {
title: "Modal Header",
help_content: "<p>Add a description of the content you're showing in the modal.</p>",
help_link: {
href: "#",
name: "Link"
}
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<% content_for :sage_footer_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Link",
attributes: { "data-js-modal": true }
} %>
<% end %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<h3>Scrollable Content</h3>
<p>Modals can be configured to allow scrolling of content. This option is useful when the header and footer needs to visible contain actions.</p>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Scrollable Content",
attributes: {
"data-js-modaltrigger": "cool-modal-scrolling",
}
} %>
<%= sage_component SageModal, { allow_scroll: true, id: "cool-modal-scrolling" } do %>
<%= sage_component SageModalContent, {
title: "Modal header",
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse urna leo, condimentum nec pellentesque finibus, ultricies pulvinar ante. Donec eu interdum ligula. Pellentesque aliquam ullamcorper orci, nec tempor libero tristique in. Aliquam vitae felis at leo condimentum placerat eget id libero. In dictum tortor ac accumsan aliquam. Donec sit amet tortor porttitor, tincidunt nisl at, egestas lacus. Integer metus augue, aliquet accumsan vulputate eget, tristique id erat. Donec a venenatis nibh, ac molestie risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus in orci vitae ex tempor ultrices in a leo. Sed purus magna, vulputate aliquet ligula eget, consectetur sagittis nunc.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse urna leo, condimentum nec pellentesque finibus, ultricies pulvinar ante. Donec eu interdum ligula. Pellentesque aliquam ullamcorper orci, nec tempor libero tristique in. Aliquam vitae felis at leo condimentum placerat eget id libero. In dictum tortor ac accumsan aliquam. Donec sit amet tortor porttitor, tincidunt nisl at, egestas lacus. Integer metus augue, aliquet accumsan vulputate eget, tristique id erat. Donec a venenatis nibh, ac molestie risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus in orci vitae ex tempor ultrices in a leo. Sed purus magna, vulputate aliquet ligula eget, consectetur sagittis nunc.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse urna leo, condimentum nec pellentesque finibus, ultricies pulvinar ante. Donec eu interdum ligula. Pellentesque aliquam ullamcorper orci, nec tempor libero tristique in. Aliquam vitae felis at leo condimentum placerat eget id libero. In dictum tortor ac accumsan aliquam. Donec sit amet tortor porttitor, tincidunt nisl at, egestas lacus. Integer metus augue, aliquet accumsan vulputate eget, tristique id erat. Donec a venenatis nibh, ac molestie risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus in orci vitae ex tempor ultrices in a leo. Sed purus magna, vulputate aliquet ligula eget, consectetur sagittis nunc.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse urna leo, condimentum nec pellentesque finibus, ultricies pulvinar ante. Donec eu interdum ligula. Pellentesque aliquam ullamcorper orci, nec tempor libero tristique in. Aliquam vitae felis at leo condimentum placerat eget id libero. In dictum tortor ac accumsan aliquam. Donec sit amet tortor porttitor, tincidunt nisl at, egestas lacus. Integer metus augue, aliquet accumsan vulputate eget, tristique id erat. Donec a venenatis nibh, ac molestie risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus in orci vitae ex tempor ultrices in a leo. Sed purus magna, vulputate aliquet ligula eget, consectetur sagittis nunc.</p>
<% content_for :sage_footer do %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<h3>Sizes</h3>
<p>Modal widths can be configured to be extra small, small, medium, or large.</p>
<%= sage_component SageButtonGroup, { gap: :sm, spacer: { bottom: :sm }} do %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Size xs",
attributes: {
"data-js-modaltrigger": "cool-modal-size-xs",
}
} %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Size sm",
attributes: {
"data-js-modaltrigger": "cool-modal-size-sm",
}
} %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Size md",
attributes: {
"data-js-modaltrigger": "cool-modal-size-md",
}
} %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Size lg",
attributes: {
"data-js-modaltrigger": "cool-modal-size-lg",
}
} %>
<% end %>
<%= sage_component SageModal, { id: "cool-modal-size-xs", size: "xs"} do %>
<%= sage_component SageModalContent, {
title: "Modal title",
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageModal, { id: "cool-modal-size-sm", size: "sm"} do %>
<%= sage_component SageModalContent, {
title: "Modal title",
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageModal, { id: "cool-modal-size-md", size: "md"} do %>
<%= sage_component SageModalContent, {
title: "Modal title",
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageModal, { id: "cool-modal-size-lg", size: "lg"} do %>
<%= sage_component SageModalContent, {
title: "Modal title",
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<%= sage_component SageButton, {
style: "secondary",
value: "Cancel",
} %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<h3>Fullscreen</h3>
<p>Modals can be configured to take up the full screen.</p>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Fullscreen",
attributes: {
"data-js-modaltrigger": "cool-modal-fullscreen",
}
} %>
<%= sage_component SageModal, {
id: "cool-modal-fullscreen",
fullscreen: true
} do %>
<%= sage_component SageModalContent, {
title: "Modal header"
} do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<h3>Animated</h3>
<p>Modals can be configured to animate in from the top, left, or right.</p>
<%= sage_component SageButtonGroup, { gap: :sm, spacer: { bottom: :sm }} do %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "Default",
attributes: {
"data-js-modaltrigger": "cool-modal-animate-default",
}
} %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "To top",
attributes: {
"data-js-modaltrigger": "cool-modal-animate-top",
}
} %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "To left (blur off)",
attributes: {
"data-js-modaltrigger": "cool-modal-animate-left",
}
} %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "To right (blur off)",
attributes: {
"data-js-modaltrigger": "cool-modal-animate-right",
}
} %>
<% end %>
<%# Animated Modals %>
<%= sage_component SageModal, { id: "cool-modal-animate-default", animate: true, css_classes: "custom-class-name-here" } do %>
<%= sage_component SageModalContent, { title: "Modal header" } do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<% content_for :sage_footer_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
attributes: { "data-js-modal": true }
} %>
<% end %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageModal, { id: "cool-modal-animate-top", animate: { direction: "top" } } do %>
<%= sage_component SageModalContent, { title: "Modal header" } do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<% content_for :sage_footer_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Link",
attributes: { "data-js-modal": true }
} %>
<% end %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageModal, { id: "cool-modal-animate-left", disable_background_blur: true, animate: { direction: "left" } } do %>
<%= sage_component SageModalContent, { title: "Modal header" } do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<% content_for :sage_footer_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Link",
attributes: { "data-js-modal": true }
} %>
<% end %>
<%= sage_component SageButton, {
style: "primary",
value: "Confirm",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageModal, { id: "cool-modal-animate-right", disable_background_blur: true, animate: { direction: "right" } } do %>
<%= sage_component SageModalContent, { title: "Modal header" } do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<% content_for :sage_footer_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Link",
attributes: { "data-js-modal": true }
} %>
<% end %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "check", style: "left" },
value: "Confirm"
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageDivider, {} %>
<%= md("
<h2>Asynchronous Modal Setup</h2>
1. Use Case:
- Load modals asynchronously, ideal for scenarios like editing product details in a list.
2. Setup:
- Include a `SageModal` stub in the view with an ID and configurations.
- Utilize `remove_content_on_close: true` for best practices.
- Add default content (e.g., `SageLoader`) in the `SageModal` stub.
- Create an endpoint delivering modal content (wrapped by `SageModalContent`).
3. Trigger Configuration:
- In the main view, add clickable triggers (e.g., buttons).
- Configure triggers with:
- `data-js-modaltrigger=\"[modal-id]\"`: ID of the `SageModal` stub.
- `data-js-remote-url=\"[url]\"`: Endpoint delivering the content.
4. Remote URLs:
- Set remote URLs on both the main `SageModal` stub and triggers.
- Trigger's `remote_url` overrides the stub's, but stub's is used if trigger has none.
- Default content inside `SageModal` is replaced by asynchronous `remote_url` content.
", use_sage_type: true) %>
<h3>Remote URLs</h3>
<ul>
<li>Modal A demonstrates <code>remote_url</code> prop usage on <code>SageModal</code></li>
<li>Modal B and C demonstrate usage of the <code>data-js-remote-url</code> key within <code>html_attributes</code>.
The value of the <code>async_path()</code> equals the all content in this path residing within <code>SageModalContent</code></li>
</ul>
<%= sage_component SageButtonGroup, { gap: :sm } do %>
<%= sage_component SageButton, {
html_attributes: {
"data-js-modaltrigger": "test-modal",
},
style: "primary",
value: "Open modal A",
} %>
<%= sage_component SageButton, {
html_attributes: {
"data-js-modaltrigger": "test-modal",
"data-js-remote-url": async_path("modal-demo-2"),
},
style: "primary",
value: "Open modal B",
} %>
<%= sage_component SageButton, {
html_attributes: {
"data-js-modaltrigger": "test-modal",
"data-js-remote-url": async_path("modal-demo-3"),
},
style: "primary",
value: "Open modal C",
} %>
<% end %>
<%= sage_component SageModal, { id: "test-modal", remote_url: async_path("modal-demo"), remove_content_on_close: true, } do %>
<%= sage_component SageModalContent, {} do %>
<%= sage_component SageLoader, { type: "spinner" } %>
<% end %>
<% end %>
<%= sage_component SagePanelStack, {} do %>
<h3 class="<%= SageClassnames::TYPE::HEADING_6 %>">Events (monitor in browser console)</h3>
<p>Use these events for hooking into modal functionality using JS event listeners.</p>
<%= sage_component SageTable, {
striped: true,
responsive: true,
headers: [
"Event name",
"Event type",
"Description"
],
rows: [
{
col_1: md("`sage.modal.active`"),
col_2: "global",
col_3: md("Fires when **any** modal has been opened")
},
{
col_1: md("`sage.modal.closeAll`"),
col_2: "global",
col_3: md("Fires when **any** modal has been closed")
},
{
col_1: md("`sage.modal.opening`"),
col_2: "instance",
col_3: "Fires immediately when a modal has been opened"
},
{
col_1: md("`sage.modal.open`"),
col_2: "instance",
col_3: md("Fires after a modal has loaded. If `animate` is enabled, this event will run upon completion of the modal\'s animation. Otherwise, this event will run immediately along with `sage.modal.opening`.")
},
]
} %>
<%= sage_component SageButtonGroup, { gap: :sm, spacer: { bottom: :sm }} do %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "'sage.modal.active'",
attributes: {
"data-js-modaltrigger": "cool-modal-event-active",
}
} %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "'sage.modal.opening'",
attributes: {
"data-js-modaltrigger": "cool-modal-event-opening",
}
} %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "launch", style: "right" },
value: "'sage.modal.open'",
attributes: {
"data-js-modaltrigger": "cool-modal-event-open",
}
} %>
<% end %>
<%# Event-enabled Modals %>
<%= sage_component SageModal, { id: "cool-modal-event-active", disable_background_blur: true, animate: true } do %>
<%= sage_component SageModalContent, { title: "Example 'Active' Event Modal" } do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<% content_for :sage_footer_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
attributes: { "data-js-modal": true }
} %>
<% end %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "check", style: "left" },
value: "Take An Action",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageModal, { id: "cool-modal-event-open", disable_background_blur: true, animate: true, css_classes: "custom-class-name-here" } do %>
<%= sage_component SageModalContent, { title: "Example 'Open' Event Modal" } do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<% content_for :sage_footer_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
attributes: { "data-js-modal": true }
} %>
<% end %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "check", style: "left" },
value: "Take An Action",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageModal, { id: "cool-modal-event-opening", disable_background_blur: true, animate: true } do %>
<%= sage_component SageModalContent, { title: "Example 'Opening' Event Modal" } do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<% content_for :sage_footer_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
attributes: { "data-js-modal": true }
} %>
<% end %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "check", style: "left" },
value: "Take An Action",
} %>
<% end %>
<% end %>
<% end %>
<%= sage_component SageModal, { id: "cool-modal-event-close", disable_background_blur: true, animate: true } do %>
<%= sage_component SageModalContent, { title: "Example 'CloseAll' Event Modal" } do %>
<% content_for :sage_header_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
icon: { name: "remove", style: "only" },
attributes: { "data-js-modal": true }
} %>
<% end %>
<p>Add a description of the content you're showing in the modal.</p>
<% content_for :sage_footer do %>
<% content_for :sage_footer_aside do %>
<%= sage_component SageButton, {
style: "secondary",
subtle: true,
value: "Close Modal",
attributes: { "data-js-modal": true }
} %>
<% end %>
<%= sage_component SageButton, {
style: "primary",
icon: { name: "check", style: "left" },
value: "Take An Action",
} %>
<% end %>
<% end %>
<% end %>
<% end %>
<script>
(function() {
const modalOpeningExample = document.querySelector("[data-js-modal=cool-modal-event-opening]");
const modalOpenExample = document.querySelector("[data-js-modal=cool-modal-event-open]");
document.addEventListener("sage.modal.active", function(e) {
console.info("sage.modal.active global event fired", e);
});
modalOpeningExample.addEventListener("sage.modal.opening", function(e) {
console.info("sage.modal.opening event fired", e);
});
modalOpenExample.addEventListener("sage.modal.open", function(e) {
console.info("sage.modal.open event fired", e);
});
document.addEventListener("sage.modal.closeAll", function(e) {
console.info("sage.modal.closeAll global event fired", e);
});
})();
</script>
Property | Description | Type | Default |
---|---|---|---|
|
Enabling this property will return the JS early to not initialize any handlers. |
Boolean |
|
|
When |
Boolean |
|
|
Outputs additional CSS classes as specified. |
String |
|
|
Sets the direction of the animation when |
String |
|
|
Disables the background blur filter, with a darkened background color. Recommended for increased animation performance when |
Boolean |
|
|
Enabling this property will return the JS early to not initialize any handlers. |
Boolean |
|
|
Enabling this property will return the JS early to not initialize any handlers. |
Boolean |
|
|
Toggles whether to use the fullscreen variant of the modal by attaching |
Boolean |
|
|
Unique identifier for component. Should match the |
String |
`nil |
|
Toggles whether to use the large variant of the modal by attaching |
Boolean |
|
|
Toggles whether to delete the |
Boolean |
|
|
Specify a url which from which to load the modal content on open. This will be requested & content replaced every time the modal is opened. |
String |
|
|
Presets a size for the modal. |
|
|
Modal Content | |||
|
When present, sets the icon with optional color in the header of the comoponent |
|
|
|
Sets the content for the Popover component |
String |
|
|
Array containing help link |
String |
|
|
Sets the title for the subheader Popover |
String |
|
|
Populates the |
String |
|
|
Optionally enforces either a |
|
|
|
Adds an optional subheader under the modal title. |
String |
|
Section: |
Populates the |
String |
|
Section: |
Populates the the page indicator in the header of standard modals. |
String |
|
Section: |
Populates the header of a fullscreen modal with a progress bar. |
String |
|
Section: |
Populates the |
String |
|
Section: |
Populates the |
String |
|
Events | |||
Global/window events | |||
|
This event is fired immediately when any modal has been opened. |
||
|
Fires on when a modal has been closed, either from actuating a button, |
||
Individual modal events | |||
|
This modal event is fired immediately when a modal has been opened. |
||
|
Fired after a modal has completed its loading animation. Note that if |
||
Sections |
|
||
|
When present, this will show containing |
|
|
|
This area holds the button that closes the modal. This resides in the header of the component. |
|
|
|
When present, sets the image in the header of the component |
|
|
|
This area holds the page indicator for the modal. This is to be used on multi-page modals. |
|
|
|
This can be used to provide custom header content, typically in lieue of the |
|
|
|
This area holds the cta buttons for the component. |
|
|
|
This area holds the cancel or close modal button in the footer of the component. |
|
- Be sure that the
<button>
'sdata-js-modaltrigger
and the modalid
match to establish the necessary link.
- DO NOT use the
remove_content_on_close
property if your modal's content is not populated using JavaScript. The modal will not have content the next time it's triggered