first prototype

This commit is contained in:
2026-09-27 09:52:00 +02:00
parent 4635199a41
commit 6d011d474f
109 changed files with 6354 additions and 507 deletions
@@ -0,0 +1,55 @@
.backdrop {
position: fixed;
inset: 0;
z-index: 40;
display: grid;
place-items: center;
padding: 16px;
background: rgb(5 4 15 / 70%);
backdrop-filter: blur(3px);
}
.dialog {
width: min(460px, 100%);
max-height: calc(100dvh - 32px);
display: flex;
flex-direction: column;
background: var(--bg-elevated);
border: 1px solid var(--border);
border-radius: 16px;
box-shadow: var(--shadow);
}
.wide {
width: min(900px, 100%);
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px 0;
}
.title {
margin: 0;
font-size: 20px;
}
.close {
border: 0;
background: none;
color: var(--text-muted);
font-size: 28px;
line-height: 1;
cursor: pointer;
}
.close:hover {
color: var(--text);
}
.body {
padding: 16px 20px 20px;
overflow: auto;
}
@@ -0,0 +1,40 @@
import { useEffect, type ReactNode } from 'react'
import styles from './Modal.module.css'
interface ModalProps {
title: string
onClose?: () => void
children: ReactNode
wide?: boolean
}
export function Modal({ title, onClose, children, wide }: ModalProps) {
useEffect(() => {
if (!onClose) return
const onKey = (event: KeyboardEvent) => event.key === 'Escape' && onClose()
window.addEventListener('keydown', onKey)
return () => window.removeEventListener('keydown', onKey)
}, [onClose])
return (
<div className={styles.backdrop} onClick={onClose}>
<div
className={`${styles.dialog} ${wide ? styles.wide : ''}`}
role="dialog"
aria-modal="true"
aria-label={title}
onClick={(event) => event.stopPropagation()}
>
<header className={styles.header}>
<h2 className={styles.title}>{title}</h2>
{onClose && (
<button type="button" className={styles.close} onClick={onClose} aria-label="Close">
×
</button>
)}
</header>
<div className={styles.body}>{children}</div>
</div>
</div>
)
}