c2-modal wraps a native <dialog> opened with showModal(), so focus is trapped and restored, the page behind is inert and covered by a backdrop, and Escape closes. Open it with the open attribute or show(); close it with close(returnValue), the built-in × button, a backdrop click or Escape, each of which hide-close, no-backdrop-close and no-escape can turn off. Put the heading in the title slot (it labels the dialog; use label when there is none), the content in the default slot (it scrolls past --c2-modal--max-height) and the actions in footer. close fires with detail.returnValue, open after showing. The page stops scrolling while a modal is open unless no-scroll-lock is set.
Installation
npm install @c2n/modal
Usage
Invite your teamInvite your teamInvite your team
Share the link below with your teammates. They will be added with the Member role.
CancelCancel
Copy linkCopy linkInvite your team
Share the link below with your teammates. They will be added with the Member role.
CancelCancel
Copy linkCopy link
Delete workspaceDelete workspaceDelete workspace?
This removes all projects and members. This action cannot be undone.
CancelCancel
DeleteDeleteDelete workspace?
This removes all projects and members. This action cannot be undone.
CancelCancel
DeleteDelete
Terms of serviceTerms of serviceTerms of service
1. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
2. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
3. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
4. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
5. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.
6. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores.
7. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.
AcceptAcceptTerms of service
1. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
2. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
3. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
4. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
5. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.
6. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores.
7. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.
AcceptAccept
Bottom sheetBottom sheet
Margins, width, radius and the enter transform are tokens, so a sheet is a few variables away.
Share
Margins, width, radius and the enter transform are tokens, so a sheet is a few variables away.
Share
Frosted backdropFrosted backdrop
The backdrop is blurred and Escape is ignored: use × or click outside.
Frosted
The backdrop is blurred and Escape is ignored: use × or click outside.
Frosted
Import
import '@c2n/modal'
Markup
<style> .modal p { margin: 0; } .ghost { --c2-button__container--background-color: transparent; --c2-button__container--color: #18181b; --c2-button__container--border: 1px solid #d4d4d8; --c2-button__container__hover--background-color: #f4f4f5; } .danger { --c2-button__container--background-color: #dc2626; --c2-button__container__hover--background-color: #b91c1c; } .sheet { --c2-modal--margin-bottom: 0; --c2-modal--width: 100vw; --c2-modal--border-bottom-left-radius: 0px; --c2-modal--border-bottom-right-radius: 0px; --c2-modal--enter-transform: translateY(100%); } .glass { --c2-modal__backdrop--background: rgba(255, 255, 255, 0.4); --c2-modal__backdrop--backdrop-filter: blur(6px); }</style><div data-label="Basic"> <c2-button onclick="document.getElementById('md-basic').show()">Invite your team</c2-button> <c2-modal id="md-basic" class="modal"> <span slot="title">Invite your team</span> <p>Share the link below with your teammates. They will be added with the Member role.</p> <c2-button slot="footer" class="ghost" onclick="this.closest('c2-modal').close('cancel')">Cancel</c2-button> <c2-button slot="footer" onclick="this.closest('c2-modal').close('copied')">Copy link</c2-button> </c2-modal></div><div data-label="Confirm"> <c2-button class="danger" onclick="document.getElementById('md-confirm').show()">Delete workspace</c2-button> <c2-modal id="md-confirm" class="modal" hide-close no-backdrop-close> <span slot="title">Delete workspace?</span> <p>This removes all projects and members. This action cannot be undone.</p> <c2-button slot="footer" class="ghost" onclick="this.closest('c2-modal').close('cancel')">Cancel</c2-button> <c2-button slot="footer" class="danger" onclick="this.closest('c2-modal').close('delete')">Delete</c2-button> </c2-modal></div><div data-label="Scrolling body"> <c2-button class="ghost" onclick="document.getElementById('md-terms').show()">Terms of service</c2-button> <c2-modal id="md-terms" class="modal" style="--c2-modal--max-height: 360px"> <span slot="title">Terms of service</span> <p>1. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>2. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> <p>3. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p> <p>4. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> <p>5. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.</p> <p>6. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores.</p> <p>7. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.</p> <c2-button slot="footer" onclick="this.closest('c2-modal').close('accepted')">Accept</c2-button> </c2-modal></div><div data-label="Bottom sheet and frosted"> <c2-button class="ghost" onclick="document.getElementById('md-sheet').show()">Bottom sheet</c2-button> <c2-modal id="md-sheet" class="modal sheet"> <span slot="title">Share</span> <p>Margins, width, radius and the enter transform are tokens, so a sheet is a few variables away.</p> </c2-modal> <c2-button class="ghost" onclick="document.getElementById('md-glass').show()">Frosted backdrop</c2-button> <c2-modal id="md-glass" class="modal glass" no-escape> <span slot="title">Frosted</span> <p>The backdrop is blurred and Escape is ignored: use × or click outside.</p> </c2-modal></div>
c2-modal wraps a native <dialog> opened with showModal(), so focus is trapped and restored, the page behind is inert and covered by a backdrop, and Escape closes. Open it with the open attribute or show(); close it with close(returnValue), the built-in × button, a backdrop click or Escape, each of which hide-close, no-backdrop-close and no-escape can turn off. Put the heading in the title slot (it labels the dialog; use label when there is none), the content in the default slot (it scrolls past --c2-modal--max-height) and the actions in footer. close fires with detail.returnValue, open after showing. The page stops scrolling while a modal is open unless no-scroll-lock is set.
Installation
npm install @c2n/modal
Usage
Invite your teamInvite your teamInvite your team
Share the link below with your teammates. They will be added with the Member role.
CancelCancel
Copy linkCopy linkInvite your team
Share the link below with your teammates. They will be added with the Member role.
CancelCancel
Copy linkCopy link
Delete workspaceDelete workspaceDelete workspace?
This removes all projects and members. This action cannot be undone.
CancelCancel
DeleteDeleteDelete workspace?
This removes all projects and members. This action cannot be undone.
CancelCancel
DeleteDelete
Terms of serviceTerms of serviceTerms of service
1. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
2. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
3. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
4. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
5. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.
6. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores.
7. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.
AcceptAcceptTerms of service
1. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
2. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
3. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
4. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
5. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.
6. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores.
7. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.
AcceptAccept
Bottom sheetBottom sheet
Margins, width, radius and the enter transform are tokens, so a sheet is a few variables away.
Share
Margins, width, radius and the enter transform are tokens, so a sheet is a few variables away.
Share
Frosted backdropFrosted backdrop
The backdrop is blurred and Escape is ignored: use × or click outside.
Frosted
The backdrop is blurred and Escape is ignored: use × or click outside.
Frosted
Import
import '@c2n/modal'
Markup
<style> .modal p { margin: 0; } .ghost { --c2-button__container--background-color: transparent; --c2-button__container--color: #18181b; --c2-button__container--border: 1px solid #d4d4d8; --c2-button__container__hover--background-color: #f4f4f5; } .danger { --c2-button__container--background-color: #dc2626; --c2-button__container__hover--background-color: #b91c1c; } .sheet { --c2-modal--margin-bottom: 0; --c2-modal--width: 100vw; --c2-modal--border-bottom-left-radius: 0px; --c2-modal--border-bottom-right-radius: 0px; --c2-modal--enter-transform: translateY(100%); } .glass { --c2-modal__backdrop--background: rgba(255, 255, 255, 0.4); --c2-modal__backdrop--backdrop-filter: blur(6px); }</style><div data-label="Basic"> <c2-button onclick="document.getElementById('md-basic').show()">Invite your team</c2-button> <c2-modal id="md-basic" class="modal"> <span slot="title">Invite your team</span> <p>Share the link below with your teammates. They will be added with the Member role.</p> <c2-button slot="footer" class="ghost" onclick="this.closest('c2-modal').close('cancel')">Cancel</c2-button> <c2-button slot="footer" onclick="this.closest('c2-modal').close('copied')">Copy link</c2-button> </c2-modal></div><div data-label="Confirm"> <c2-button class="danger" onclick="document.getElementById('md-confirm').show()">Delete workspace</c2-button> <c2-modal id="md-confirm" class="modal" hide-close no-backdrop-close> <span slot="title">Delete workspace?</span> <p>This removes all projects and members. This action cannot be undone.</p> <c2-button slot="footer" class="ghost" onclick="this.closest('c2-modal').close('cancel')">Cancel</c2-button> <c2-button slot="footer" class="danger" onclick="this.closest('c2-modal').close('delete')">Delete</c2-button> </c2-modal></div><div data-label="Scrolling body"> <c2-button class="ghost" onclick="document.getElementById('md-terms').show()">Terms of service</c2-button> <c2-modal id="md-terms" class="modal" style="--c2-modal--max-height: 360px"> <span slot="title">Terms of service</span> <p>1. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>2. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> <p>3. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p> <p>4. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> <p>5. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.</p> <p>6. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores.</p> <p>7. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.</p> <c2-button slot="footer" onclick="this.closest('c2-modal').close('accepted')">Accept</c2-button> </c2-modal></div><div data-label="Bottom sheet and frosted"> <c2-button class="ghost" onclick="document.getElementById('md-sheet').show()">Bottom sheet</c2-button> <c2-modal id="md-sheet" class="modal sheet"> <span slot="title">Share</span> <p>Margins, width, radius and the enter transform are tokens, so a sheet is a few variables away.</p> </c2-modal> <c2-button class="ghost" onclick="document.getElementById('md-glass').show()">Frosted backdrop</c2-button> <c2-modal id="md-glass" class="modal glass" no-escape> <span slot="title">Frosted</span> <p>The backdrop is blurred and Escape is ignored: use × or click outside.</p> </c2-modal></div>
escAccordionConnected, animated panels with shared borders and single or multiple expansion.LayoutAvatarImage, initials or icon for a person, with status dot and badge.Data displayBadgeTinted pill for status text, counts and dots, optionally pinned to a corner of another element.Data displayBreadcrumbNavigation trail of link buttons with separators, a current page and optional collapsing.NavigationButtonThemeable button with slots for text, prefix, suffix and running icons.ButtonsButton GroupAttached buttons with shared borders, optionally a segmented control with single or multiple selection.ButtonsCardGroups related content and actions on a single bordered surface.LayoutChat InputAuto-growing message box with a send button for chat interfaces.ChatChat MessageOne chat bubble with avatar, title, timestamp and message body.ChatCheckboxNative checkbox behaviour in a quiet, themeable box with an opt-in hover layer.InputsCode ViewerSyntax-highlighted code with line numbers, copy button and dark mode, powered by shiki.Data displayColor AreaTwo-dimensional area for picking saturation and value of a colour.InputsColor SelectColour swatch that opens a full picker built from area and slider.InputsColor SliderHorizontal slider for choosing a hue from 0 to 360.InputsCopy ButtonButton that copies text to the clipboard — the element it sits in, another element by id, or a literal string.ButtonsDetailsCollapsible disclosure built on native details and summary.LayoutIcon ButtonRound, hoverable button wrapping a slotted SVG icon.ButtonsKbdKeyboard key label for shortcuts and command hints, with the semantics of the native kbd element.Data displayLabelCaption that names and activates the control referenced by its for attribute, with a required marker.InputsLink ButtonText-styled control for link and navigation actions, rendered as a real anchor or a button.NavigationListVertical list container with single or multiple selection.Data displayList ItemSelectable row with icon slots, used on its own or as the option of list and select.Data displayMenuCommands, links, checkboxes and submenus in a popover anchored to a trigger.NavigationModalDialog built on the native dialog element: focus trap, backdrop, Escape, title, body and footer.FeedbackNavigation MenuSite navigation bar whose triggers open panels of links below the header.NavigationOverlayAnchored popup built on the browser Popover API, positioned with floating-ui.FeedbackPaginationPage navigation in three layouts: numbered pages, a simple page status, or a table-footer row with rows-per-page.NavigationProgressLinear progress bar, indeterminate or filling to a value, with an optional label and count.FeedbackRadioRadio options built on native inputs, grouped into one value with keyboard navigation.InputsSelectDropdown that pairs a themeable trigger with an anchored list of c2-list-item options.InputsSeperatorHorizontal or vertical rule with an optional label, for dividing content and toolbars.LayoutSheetDialog pinned to an edge of the screen, for content that complements the page rather than interrupting it.FeedbackSide NavResponsive navigation drawer beside the page: pushes the content on large screens, slides over it with a backdrop on small ones.NavigationSkeletonPlaceholder block standing in for content that has not arrived, in three shapes and three animations.FeedbackSliderRange input with a themeable track, thumb, step ticks and value bubble.InputsSpinnerCircular progress indicator, indeterminate or showing a value, with optional text.FeedbackSwitchOn/off toggle on a native switch input, with label, description and thumb icons.InputsTableVirtualized data grid with declarative columns, sorting, selection, pinning and resizing.Data displayTabsTab strip that shows one content panel at a time.NavigationText FieldSingle-line input with icon slots, clear button, helper and error text, and a character counter.InputsTextareaMultiline text input with resizing, helper and error text, and a character counter.InputsToastNotification cards and a manager for stacked, queued notifications with independent lifetimes.FeedbackTooltipContextual hint shown when its target is hovered or focused, rendered in the top layer.FeedbackFeather Icons287 open-source Feather icons, one web component each.IconsMat Icon2,234 Material Icons ligatures rendered through a single element.IconsPhosphor Icons1,512 flexible icons in six weights, one web component each.IconsThemingTheme every c2n component from a handful of design tokens with @c2n/theme, or reach for any component variable directly.GuideUsing c2n in an applicationThe workflow behind every c2n app: load the theme once, use c2-* tags directly, and turn every repeated pattern into a small variant or composed component.Guide