kithkin/resources/css/lib/modal.css

244 lines
6.5 KiB
CSS

/**
* modal uses a <dialog> 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 cubic-bezier(0,0,.2,1);
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;
&.no-margin {
@apply p-0;
}
}
/* 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 py-4 border-t-md border-gray-300 flex 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 w-11/12 max-w-3xl justify-self-center px-4 h-0;
@apply flex flex-row justify-between items-start gap-2 translate-y-4;
@apply opacity-0 invisible;
pointer-events: none;
transition:
translate 350ms cubic-bezier(0,0,.2,1),
opacity 150ms cubic-bezier(0,0,.2,1),
visibility 150ms cubic-bezier(0,0,.2,1);
&.is-visible {
@apply opacity-100 visible h-auto;
pointer-events: auto;
}
.modal-aside-list {
@apply list-none m-0 pt-3 flex flex-wrap justify-start gap-2;
li {
@apply text-white rounded-full px-3 py-1 text-sm;
background: rgba(0, 0, 0, 0.25);
strong {
@apply font-semibold;
}
}
}
.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;
}
}