feat(design): dialogs open by purpose and keep their commit row pinned (E28 S3f1)

Modal takes a required initialFocus (field / close / action), a field that
loads late takes the focus while it still rests on the close button, and
ModalFooter portals a dialog's commit row under the scrolling body from any
depth. The header and footer fades follow the body's scroll timeline, and the
viewport's interactive-widget=resizes-content keeps the footer above an
on-screen keyboard.
This commit is contained in:
2026-09-27 01:33:37 +02:00
parent 4c63d6660d
commit 3ef2c38eb4
34 changed files with 505 additions and 113 deletions
+4 -2
View File
@@ -169,7 +169,9 @@ function C4() {
title="Dialog conventions"
rule="Modal takes an initialFocus by purpose (APG): a form focuses its first field, a confirm its least destructive button, anything else Close. The header and the footer are fixed, only the body scrolls, with the B9 fade at both edges, so Save stays one tap away with the keyboard up. Shown at a keyboard-up height."
>
<div className={`${SURFACE.panel} relative flex h-52 flex-col overflow-hidden`}>
<div
className={`${SURFACE.panel} relative flex h-52 flex-col overflow-hidden panel-scroll-scope`}
>
<div
className={clsx(
"relative z-base flex items-center justify-between px-3 py-2 text-sm font-semibold",
@@ -181,7 +183,7 @@ function C4() {
<X className={ico} />
</span>
</div>
<div className="min-h-0 flex-1 overflow-y-auto no-scrollbar">
<div className="min-h-0 flex-1 overflow-y-auto no-scrollbar panel-scroller">
<div className="flex flex-col gap-2 px-3 pb-3 pt-2">
<Field label="Title" value="Building a home lab" focused />
<Field label="Channel" value="Techno Tim" />