/** * modal uses a as the backdrop and grid, with #modal and #modal-aside on top */ dialog { @apply grid fixed inset-0 m-0 p-0 pointer-events-none; @apply place-items-center bg-transparent opacity-0 invisible; @apply w-full h-full max-w-none max-h-none overflow-clip; background-color: rgba(26, 26, 26, 0.75); backdrop-filter: blur(0.25rem); overscroll-behavior: contain; scrollbar-gutter: auto; transition: background-color 150ms cubic-bezier(0,0,.2,1), opacity 150ms cubic-bezier(0,0,.2,1), visibility 150ms cubic-bezier(0,0,.2,1); z-index: 100; /* primary modal container */ #modal { @apply relative rounded-xl bg-white border-gray-200 p-0; @apply flex flex-col items-start col-start-1 translate-y-4 overflow-hidden; max-height: calc(100dvh - 5rem); width: 91.666667%; max-width: 36rem; transition: translate 150ms ease-in-out; box-shadow: 0 1.5rem 4rem -0.5rem rgba(0, 0, 0, 0.4); /* close button */ > .close-modal { @apply block absolute top-4 right-4 z-3; } /* content wrapper and content defaults */ > .modal-content { @apply grid w-full h-full overflow-hidden; /* set the grid based on which elements the content section has */ grid-template-rows: 1fr; &:has(header):has(footer) { grid-template-rows: auto minmax(0, 1fr) auto; } &:has(header):not(:has(footer)) { grid-template-rows: auto minmax(0, 1fr); } &:has(footer):not(:has(header)) { grid-template-rows: minmax(0, 1fr) auto; } /* modal header */ header { @apply sticky top-0 bg-white flex items-center px-6 min-h-20 h-20 z-2 pr-16; } /* main content wrapper */ section.modal-body { @apply flex flex-col px-6 pb-8 overflow-y-auto; &.no-margin { @apply p-0; } /* overlay gradient to signal scrollability */ &::after { @apply h-8 w-full absolute bottom-20 left-0 bg-scrollbar; content: ''; } } /* standard form with 1rem gap between rows */ form { @apply flex flex-col gap-4; /* paneled modals get different behavior */ &.settings:has(.tab-panels) { @apply flex-1 min-h-0 gap-0; } } /* footer */ footer { @apply sticky bottom-0 bg-white px-6 h-20 border-t-md border-gray-300 flex items-center justify-between; } /* event modal with a map */ &.with-map { header { background: linear-gradient(180deg,rgba(255, 255, 255, 0.67) 0%, rgba(255, 255, 255, 0) 100%); } } } /* wider version */ &.modal--wide { max-width: 48rem; } /* forced height on variable content modals */ &.modal--square { block-size: clamp(32rem, 72dvh, 54rem); max-block-size: calc(100dvh - 5rem); } /* event form modal with a natural language parser and enhanced interactions */ &.modal--event { header.input { @apply border-b border-gray-400; input { @apply w-full -ml-2 border-0 rounded-sm shadow-none; } /* if there are panels, move it down */ + section.modal-body .tabs, + section.modal-body .panels { @apply pt-4; } } } /* when the event-create natural language parser is collapsed */ &.natural-collapsed { @apply rounded-full; block-size: auto; header.input { @apply border-none; input { @apply rounded-full; } } > .modal-content { grid-template-rows: auto; } > .modal-content > section.modal-body, > .modal-content > footer { @apply hidden; } } } /* extra container over the backdrop below the modal */ #modal-aside { @apply justify-self-center pl-4 h-0 flex flex-row justify-between items-start gap-2; @apply translate-y-4 opacity-0 invisible; width: 91.666667%; max-width: 36rem; pointer-events: none; transition: translate 250ms ease-in-out, opacity 250ms ease-in-out, visibility 250ms ease-in-out; &.is-visible { @apply opacity-100 visible h-auto; pointer-events: auto; } .modal-aside-list { @apply list-none m-0 pt-3 flex flex-col justify-start items-start gap-2; li { @apply text-white rounded-full pl-9 pr-3 py-1 text-sm; background-color: rgba(0, 0, 0, 0.25); background-position: 0.75rem 50%; background-repeat: no-repeat; background-size: 1rem; &.is-visible { animation: modal-aside-list 250ms ease-in-out forwards; } &[data-aside-key="title"] { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 16v-4'/%3E%3Cpath d='M12 8h.01'/%3E%3C/svg%3E"); } &[data-aside-key="date"] { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 2v4'/%3E%3Cpath d='M16 2v4'/%3E%3Crect width='18' height='18' x='3' y='4' rx='2'/%3E%3Cpath d='M3 10h18'/%3E%3C/svg%3E"); } &[data-aside-key="location"] { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0'/%3E%3Ccircle cx='12' cy='10' r='3'/%3E%3C/svg%3E"); } &[data-aside-key="repeat"] { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m17 2 4 4-4 4'/%3E%3Cpath d='M3 11v-1a4 4 0 0 1 4-4h14'/%3E%3Cpath d='m7 22-4-4 4-4'/%3E%3Cpath d='M21 13v1a4 4 0 0 1-4 4H3'/%3E%3C/svg%3E"); } strong { @apply hidden; } } } .modal-aside-expand { @apply whitespace-nowrap bg-transparent border-none mt-1 text-sm underline; @apply text-white/90 hover:text-white cursor-pointer; } } /* reposition #modal and #aside when the #aside is used */ &:has(#modal-aside) { grid-template-rows: 1fr 0; } &:has(#modal-aside.is-visible) { grid-template-rows: 40dvh auto; #modal { @apply self-end; } #modal-aside { @apply self-start; } } /* hide backdrop before the modal is open */ &::backdrop { display: none; } /* open interactions */ &[open] { @apply opacity-100 visible; pointer-events: inherit; #modal { @apply translate-y-0; } #modal-aside.is-visible { @apply translate-y-0; } &::backdrop { @apply opacity-100; } } } /** * tabbed content panels in a modal */ .tab-panels { @apply grid items-start min-h-0 h-full gap-4; grid-template-columns: 12rem minmax(0, 1fr); .tabs { @apply sticky top-0 self-start; } .tabs--vertical { @apply pl-4; li { @apply rounded-r-none; &[aria-selected="true"] { button { @apply bg-cyan-200; } } } } .panels { @apply h-full min-h-0 pt-2 pr-6 pb-6 pl-1 overflow-y-auto; } } /** * animations */ @keyframes modal-aside-list { from { opacity: 0; transform: translateX(-1rem); } to { opacity: 100; transform: translateX(0); } }