For reactive frameworks (Eucalypt, etc.) where native <dialog> with .showModal() isn't practical. dialog-overlay provides the fixed backdrop, dialog-panel provides the content box with padding/gap/animation. Shared inner styles (dialog-header, dialog-body, dialog-footer) work with both native <dialog> and overlay-based patterns.
134 lines
3.2 KiB
CSS
134 lines
3.2 KiB
CSS
/* ── Shared dialog inner styles ───────────────────────────────────── */
|
|
/* Used by both native <dialog> and overlay-based .dialog-panel */
|
|
|
|
.dialog-header {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: var(--size-4);
|
|
}
|
|
|
|
.dialog-header h1,
|
|
.dialog-header h2,
|
|
.dialog-header h3,
|
|
.dialog-header h4,
|
|
.dialog-header h5,
|
|
.dialog-header h6 {
|
|
margin: 0;
|
|
}
|
|
|
|
.dialog-header p {
|
|
font-size: var(--font-sm);
|
|
color: var(--fg-2);
|
|
margin: 0;
|
|
}
|
|
|
|
.dialog-body {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--size-3);
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.dialog-body > *:first-child { margin-top: 0; }
|
|
.dialog-body > *:last-child { margin-bottom: 0; }
|
|
|
|
.dialog-footer {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: var(--size-2);
|
|
}
|
|
|
|
/* ── Native <dialog> ─────────────────────────────────────────────── */
|
|
|
|
.dialog {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 50;
|
|
width: min(100% - 2rem, 32rem);
|
|
max-height: 85vh;
|
|
margin: auto;
|
|
padding: 0;
|
|
background: var(--bg-0);
|
|
color: var(--fg-0);
|
|
border: var(--border-0);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-3);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.dialog[open] {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--size-3);
|
|
padding: var(--size-6);
|
|
}
|
|
|
|
.dialog::backdrop {
|
|
background: rgba(0, 0, 0, 0.5);
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* ── Overlay-based dialog ────────────────────────────────────────── */
|
|
|
|
.dialog-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 100;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: var(--size-4);
|
|
background: rgba(0, 0, 0, 0.3);
|
|
animation: dialog-overlay-in 0.15s ease;
|
|
}
|
|
|
|
@keyframes dialog-overlay-in {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
.dialog-panel {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--size-3);
|
|
width: 100%;
|
|
max-width: 28rem;
|
|
max-height: 85vh;
|
|
padding: var(--size-6);
|
|
background: var(--bg-1);
|
|
color: var(--fg-0);
|
|
border: var(--border-0);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-3);
|
|
overflow: hidden;
|
|
animation: dialog-panel-in 0.15s ease;
|
|
}
|
|
|
|
@keyframes dialog-panel-in {
|
|
from { opacity: 0; transform: scale(0.96) translateY(var(--size-2)); }
|
|
to { opacity: 1; transform: scale(1) translateY(0); }
|
|
}
|
|
|
|
/* ── Dark mode ───────────────────────────────────────────────────── */
|
|
|
|
[data-theme="dark"] .dialog-overlay {
|
|
background: rgba(0, 0, 0, 0.5);
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root:not([data-theme="light"]) .dialog-overlay {
|
|
background: rgba(0, 0, 0, 0.5);
|
|
}
|
|
}
|
|
|
|
/* ── Mobile ──────────────────────────────────────────────────────── */
|
|
|
|
@media (max-width: 768px) {
|
|
.dialog-panel {
|
|
max-width: none;
|
|
padding: var(--size-4);
|
|
}
|
|
}
|