From c3181e6dbe54cfd6fb768b37bebaa35692ca9c35 Mon Sep 17 00:00:00 2001 From: Ismail9k Date: Wed, 14 Oct 2026 21:08:33 +0300 Subject: [PATCH 1/2] feat(modal): add an `after` slot under the dialog's card 9k.school wants "Forgot your password?" under its sign-in dialog, on the backdrop, as its /login page has the link under the card. A native modal shows only what is inside it, so the slot renders inside the (top layer, focus order, above the backdrop) but after the card. To make room for it, the card's look (border, radius, background, shadow) moves from the to .i9k-modal__surface, and the becomes a transparent flex column while open, so the card shrinks and its body still scrolls when the slot is there. Without the slot nothing changes visually. Co-Authored-By: Claude Opus 5.5 --- showcase/registry/I9kModal.ts | 2 ++ src/components/I9kModal.vue | 35 ++++++++++++++++++++++++++++------- stories/I9kModal.stories.ts | 20 ++++++++++++++++++++ tests/I9kModal.test.ts | 18 ++++++++++++++++++ 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/showcase/registry/I9kModal.ts b/showcase/registry/I9kModal.ts index b531e0e..187c9a8 100644 --- a/showcase/registry/I9kModal.ts +++ b/showcase/registry/I9kModal.ts @@ -24,6 +24,7 @@ Emits: Slots: - default — the dialog body; it scrolls when taller than the viewport. - footer — actions such as Cancel and Save, aligned to the end. +- after — under the dialog's card, on the backdrop, centred: a way out of the dialog's task, such as "Forgot your password?" under a sign-in form. It is inside the , so it is reachable by keyboard while the modal is open. Behavior: the parent owns \`open\`. The close button and Escape only request a close by emitting update:open(false); the modal closes when the parent sets \`open\` to false, and focus returns to the element that was focused when it opened. @@ -50,6 +51,7 @@ Usage: 'Set `dismissible` to false while saving; Escape is then ignored and the close button is disabled.', 'The body and footer render only while open, so a form inside remounts on every opening; put `autofocus` on its first field.', 'The footer renders outside the body, so a submit button there needs `form=""` pointing at the form in the body.', + 'The `after` slot sits on the backdrop, not on the card: keep it to a short link, which reads on the dimmed page.', ], demos: [ { diff --git a/src/components/I9kModal.vue b/src/components/I9kModal.vue index 405a0e4..8acff8e 100644 --- a/src/components/I9kModal.vue +++ b/src/components/I9kModal.vue @@ -145,25 +145,36 @@ onBeforeUnmount(() => { the page's toaster does, above the backdrop. --> + +