Skip to content

Commit de98c12

Browse files
committed
fix(ui): constrain modal layouts to viewport
Add shared modal shell and panel constraints so dialogs keep top and bottom breathing room and scroll internally when content is taller than the window. Tests: bun run typecheck Codex: audited existing dialogs and applied shared viewport-safe modal classes
1 parent f2bb943 commit de98c12

9 files changed

Lines changed: 30 additions & 17 deletions

src/mainview/components/CloseConfirmDialog.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ export default function CloseConfirmDialog({ open, onDone }: Props) {
4242
if (!open) return null;
4343

4444
return (
45-
<div className="fixed inset-0 z-[100] flex items-center justify-center">
45+
<div className="modal-shell fixed inset-0 z-[100] flex items-center justify-center">
4646
<div className="absolute inset-0 bg-black/40 backdrop-blur-sm" onClick={onDone} />
47-
<div className="relative z-10 w-80 rounded-2xl glass-panel p-5 space-y-4 shadow-xl border border-border/50">
47+
<div className="modal-panel relative z-10 w-80 rounded-2xl glass-panel p-5 space-y-4 shadow-xl border border-border/50">
4848
<h2 className="text-sm font-[590]">{t("close.title")}</h2>
4949
<p className="text-xs text-muted-foreground leading-relaxed">
5050
{t("close.description")}

src/mainview/components/ImportWizard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ export default function ImportWizard({ mode, initialLocalPath, initialProjectPat
248248

249249
return (
250250
<div
251-
className="fixed inset-0 z-50 flex items-center justify-center bg-black/25 p-4 dark:bg-black/40 animate-backdrop-in"
251+
className="modal-shell fixed inset-0 z-50 flex items-center justify-center bg-black/25 dark:bg-black/40 animate-backdrop-in"
252252
role="presentation"
253253
onClick={busy ? undefined : handleClose}
254254
>
@@ -257,7 +257,7 @@ export default function ImportWizard({ mode, initialLocalPath, initialProjectPat
257257
tabIndex={-1}
258258
role="dialog"
259259
aria-modal="true"
260-
className="flex max-h-[calc(100dvh-2rem)] w-full max-w-lg flex-col overflow-hidden rounded-3xl p-6 space-y-4 outline-none animate-modal-in glass-elevated"
260+
className="modal-panel-flex flex w-full max-w-lg flex-col rounded-3xl p-6 space-y-4 outline-none animate-modal-in glass-elevated"
261261
onClick={(e) => e.stopPropagation()}
262262
>
263263
{/* Header */}

src/mainview/components/InstallToProjectPicker.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ export default function InstallToProjectPicker({ skillName, onInstall, onClose }
4444

4545
return (
4646
<div
47-
className="fixed inset-0 z-50 flex items-center justify-center bg-black/25 dark:bg-black/40 animate-backdrop-in"
47+
className="modal-shell fixed inset-0 z-50 flex items-center justify-center bg-black/25 dark:bg-black/40 animate-backdrop-in"
4848
onClick={onClose}
4949
>
5050
<div
5151
role="dialog"
5252
aria-modal="true"
53-
className="w-full max-w-md rounded-3xl p-6 space-y-4 outline-none animate-modal-in glass-elevated"
53+
className="modal-panel w-full max-w-md rounded-3xl p-6 space-y-4 outline-none animate-modal-in glass-elevated"
5454
onClick={(e) => e.stopPropagation()}
5555
>
5656
<div className="flex items-center justify-between">

src/mainview/components/OnboardingWizard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,13 @@ export default function OnboardingWizard({
124124

125125
return (
126126
<div
127-
className="fixed inset-0 z-50 flex items-center justify-center bg-black/25 dark:bg-black/40 animate-backdrop-in"
127+
className="modal-shell fixed inset-0 z-50 flex items-center justify-center bg-black/25 dark:bg-black/40 animate-backdrop-in"
128128
onClick={markDoneAndClose}
129129
>
130130
<div
131131
role="dialog"
132132
aria-modal="true"
133-
className="w-full max-w-xl rounded-3xl p-6 outline-none animate-modal-in glass-elevated"
133+
className="modal-panel w-full max-w-xl rounded-3xl p-6 outline-none animate-modal-in glass-elevated"
134134
onClick={(e) => e.stopPropagation()}
135135
>
136136
<StepDots current={step} />

src/mainview/components/ProjectSkillDetailModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export default function ProjectSkillDetailModal({ projectPath, skill, onClose }:
7373

7474
return (
7575
<div
76-
className="fixed inset-0 z-50 flex items-center justify-center bg-black/25 dark:bg-black/40 animate-backdrop-in"
76+
className="modal-shell fixed inset-0 z-50 flex items-center justify-center bg-black/25 dark:bg-black/40 animate-backdrop-in"
7777
onClick={() => {
7878
if (dirty) return;
7979
onClose();
@@ -82,7 +82,7 @@ export default function ProjectSkillDetailModal({ projectPath, skill, onClose }:
8282
<div
8383
role="dialog"
8484
aria-modal="true"
85-
className="flex h-[85vh] w-full max-w-3xl flex-col rounded-3xl outline-none animate-modal-in glass-elevated"
85+
className="modal-panel-flex flex h-[min(85dvh,calc(100dvh-2rem))] w-full max-w-3xl flex-col rounded-3xl outline-none animate-modal-in glass-elevated"
8686
onClick={(e) => e.stopPropagation()}
8787
>
8888
{/* Header */}

src/mainview/index.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,20 @@ html.skiller-macos-vibrancy.dark .glass-inset {
380380
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.14);
381381
}
382382

383+
.modal-shell {
384+
padding: 1rem;
385+
}
386+
387+
.modal-panel {
388+
max-height: calc(100dvh - 2rem);
389+
overflow-y: auto;
390+
}
391+
392+
.modal-panel-flex {
393+
max-height: calc(100dvh - 2rem);
394+
overflow: hidden;
395+
}
396+
383397
/* ─── Scrollbar (thin — WebKit/Electron) ─── */
384398
::-webkit-scrollbar {
385399
width: 3px;

src/mainview/pages/Dashboard.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ function InstallGuideModal({
514514
? `which ${agent.cli_command}`
515515
: "";
516516
return (
517-
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
517+
<div className="modal-shell fixed inset-0 z-50 flex items-center justify-center">
518518
<div
519519
className="absolute inset-0 bg-[rgba(0,0,0,0.85)] animate-backdrop-in"
520520
aria-hidden
@@ -526,7 +526,7 @@ function InstallGuideModal({
526526
role="dialog"
527527
aria-modal="true"
528528
aria-labelledby="install-guide-dialog-title"
529-
className="relative z-10 w-full max-w-lg rounded-3xl p-5 outline-none animate-modal-in glass-elevated"
529+
className="modal-panel relative z-10 w-full max-w-lg rounded-3xl p-5 outline-none animate-modal-in glass-elevated"
530530
>
531531
<div className="mb-3 flex items-center justify-between">
532532
<h3 id="install-guide-dialog-title" className="text-sm font-[590]">
@@ -604,4 +604,3 @@ function CommandBlock({
604604
</div>
605605
);
606606
}
607-

src/mainview/pages/Projects.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -829,13 +829,13 @@ function CopyFromInstalledPicker({
829829

830830
return (
831831
<div
832-
className="fixed inset-0 z-50 flex items-center justify-center bg-black/25 dark:bg-black/40 animate-backdrop-in"
832+
className="modal-shell fixed inset-0 z-50 flex items-center justify-center bg-black/25 dark:bg-black/40 animate-backdrop-in"
833833
onClick={onClose}
834834
>
835835
<div
836836
role="dialog"
837837
aria-modal="true"
838-
className="w-full max-w-lg rounded-3xl p-6 space-y-4 outline-none animate-modal-in glass-elevated"
838+
className="modal-panel w-full max-w-lg rounded-3xl p-6 space-y-4 outline-none animate-modal-in glass-elevated"
839839
onClick={(e) => e.stopPropagation()}
840840
>
841841
<div className="flex items-center justify-between">

src/mainview/pages/SkillsManager.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2118,9 +2118,9 @@ function SkillNameConfirmDialog({
21182118
const isUninstall = actionKind === "uninstall_all";
21192119

21202120
return (
2121-
<div className="fixed inset-0 z-[320] flex items-center justify-center">
2121+
<div className="modal-shell fixed inset-0 z-[320] flex items-center justify-center">
21222122
<div className="absolute inset-0 bg-black/40 backdrop-blur-sm" onClick={onCancel} />
2123-
<div className="relative z-10 w-[min(32rem,calc(100vw-2rem))] rounded-2xl glass-panel border border-border/50 p-5 shadow-xl">
2123+
<div className="modal-panel relative z-10 w-[min(32rem,calc(100vw-2rem))] rounded-2xl glass-panel border border-border/50 p-5 shadow-xl">
21242124
<div className="mb-2 flex items-center justify-between gap-2">
21252125
<h2 className="text-sm font-[590]">
21262126
{isUninstall ? t("skills.confirmUninstallTitle") : t("skills.confirmUnlinkTitle")}

0 commit comments

Comments
 (0)