Skip to content

Commit eb78841

Browse files
committed
feat: AFCL Dialog in Hairline style with a bottom sheet on phones, Scrim token for dialog, filter and sidebar backdrops AdminForth/2005
1 parent 5d1e0d5 commit eb78841

11 files changed

Lines changed: 131 additions & 26 deletions

File tree

‎adminforth/design/adoption.md‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ Which packages follow the [design concepts](./system-concepts.md): tokens instea
4949
- `afcl/Tooltip.vue` uses the flowbite `Tooltip`, `afcl/DatePicker.vue` and `components/CustomDateRangePicker.vue` use `flowbite-datepicker`.
5050
- The Tooltip import is the last place where core loads `flowbite`, and loading it also runs flowbite's auto-init of `data-*` attributes (`data-tooltip-target`, `data-dropdown-toggle`, …) on page load. Apps and plugins may rely on it (foreign-inline-list uses `data-tooltip-target`), so a native Tooltip has to come together with moving those usages to AFCL.
5151
- Palette classes instead of tokens in `views/PageNotFound.vue`, `views/LoginView.vue`, `views/ListView.vue` (action badge), `renderers/URL.vue`, `afcl/BarChart.vue` (axis labels), the HTML in `utils/utils.ts` and a commented line in `components/Sidebar.vue`.
52-
- Backdrops of `afcl/Modal.vue`, `components/Filters.vue` and `App.vue` use `bg-zinc-900/30…40`, the design has one `--scrim` for them.
5352

5453
## Targets
5554

‎adminforth/design/system-concepts.md‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Rules for the AdminForth UI (the "Hairline" theme). States and variants of every
66

77
- Colors, shadows, radius and fonts are tokens in `adminforth/modules/styles.ts` (`light*` / `dark*` pairs, `alias:` points one token to another). Apps override them via `customization.styles`, so token names are a public contract: change values, never rename or remove tokens.
88
- Components color themselves with tokens (`bg-lightListTableHeading dark:bg-darkListTableHeading`). Tailwind palette colors (`text-gray-400`, `bg-red-50`, `border-emerald-200`, `zinc-*`, …) are not used in core and plugins at all: they ignore `customization.styles` and drift from the theme. `black` and `white` appear only as a translucent tint over any surface (`hover:bg-black/5`), and only where no token fits.
9-
- Keep the token list short. Reuse a token with the same role before adding one: muted icons and secondary text `InputIconColor`, faint text and empty values (`-`) `InputPlaceholderText`, subtle fill `SecondaryDarken` / `SecondaryLighten`, a softer variant of a token is its opacity modifier (`stroke-lightPrimary/50`). Add a token for a new role, not for a new component, always as a `light*` / `dark*` pair.
9+
- Keep the token list short. Reuse a token with the same role before adding one: muted icons and secondary text `InputIconColor`, faint text and empty values (`-`) `InputPlaceholderText`, subtle fill `SecondaryDarken` / `SecondaryLighten`, page dimming behind dialogs, modals and drawers `Scrim` (a photo lightbox stays `bg-black/*`, it is dark in both themes), a softer variant of a token is its opacity modifier (`stroke-lightPrimary/50`). Add a token for a new role, not for a new component, always as a `light*` / `dark*` pair.
1010
- Statuses use `Success`, `Warning` and `Danger` tokens: the base one for text and icons, `*Soft` for the background, `*Border` for the border. Badges, alerts, toasts and diffs take them, e.g. `bg-lightSuccessSoft text-lightSuccess border-lightSuccessBorder`.
1111
- Gray ground, white surfaces, 1px hairline borders. Shadows only on layers that float above the page: popovers, menus, dialogs.
1212
- One ink (near-black) primary button for the main action of a screen, everything else is `secondary`, destructive actions are `danger`. The accent color is the `primary` token: links, focus rings, selection, active states.
@@ -29,6 +29,10 @@ Apps restyle and test AdminForth by `af-*` and `afcl-*` classes. A restyle never
2929

3030
A disabled control gets the native `disabled` attribute (`aria-disabled` on a link, which then has no `href`), not `pointer-events-none`: the attribute also blocks the keyboard and form submit, is announced by screen readers and does not pass the click to a parent. Hover styles are left out for a disabled control.
3131

32+
## Dialogs on phones
33+
34+
Below `sm` (640px) a Dialog or Modal docks to the bottom edge as a sheet: full width, 16px top corners, actions stacked full width with the last (main) one on top. Width classes an app passes (`class="w-96"`) apply from `sm` up. The panel and footer classes live in `afcl/dialogStyles.ts`, so an overlay built on `Modal` gets the sheet without extra code.
35+
3236
## Lucide icons
3337

3438
- Use Lucide: `@iconify-prerendered/vue-lucide` in components (`IconPencil`, `IconTrash2`), `lucide:<name>` in config (`icon: 'lucide:download'`).

‎adminforth/design/system.html‎

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,11 @@
476476
:where(#afcl-feedback) .mini-main{flex:1;padding:12px;display:flex;flex-direction:column;gap:8px}
477477
:where(#afcl-feedback) .mini-main span{height:8px;border-radius:4px;background:var(--surface-3)}
478478
:where(#afcl-feedback) .mini-scrim{position:absolute;inset:0;background:var(--scrim);display:flex;align-items:center;justify-content:center;padding:16px}
479+
:where(#afcl-feedback) .mini-phone{position:relative;width:240px;max-width:100%;height:400px;border-radius:24px;overflow:hidden;border:1px solid var(--border-strong);background:var(--bg)}
480+
:where(#afcl-feedback) .mini-phone .mini-main{height:100%;padding:36px 12px 12px}
481+
:where(#afcl-feedback) .mini-scrim-dock{align-items:flex-end;padding:0}
482+
:where(#afcl-feedback) .dlg-sheet{width:100%;border-radius:16px 16px 0 0}
483+
:where(#afcl-feedback) .dlg-sheet .dlg-foot{flex-direction:column-reverse;padding:0 20px 20px;border-top:0;background:none}
479484
:where(#afcl-feedback) .tip-wrap{display:flex;flex-direction:column;align-items:center;gap:0}
480485
:where(#afcl-feedback) .arrow{width:8px;height:8px;transform:rotate(45deg);margin-top:-4px;background:var(--ink)}
481486
:where(#afcl-feedback) .arrow-up{margin-top:0;margin-bottom:-4px}
@@ -671,6 +676,7 @@ <h1 style="font-size: 32px; line-height: 38px; font-weight: 600; letter-spacing:
671676
<div class="map"><div><code>accent</code></div><div><code>lightPrimary · lightCheckboxBgChecked · lightToggleBgActive · lightInputFocusBorder · lightProgressBarFilledColor · lightDatePickerCalendarDateActiveButtonBackground</code></div></div>
672677
<div class="map"><div><code>ring</code></div><div><code>lightFocusRing · lightInputFocusRing · lightButtonFocusRing · lightToggleRing (accent at 26%)</code></div></div>
673678
<div class="map"><div><code>danger</code></div><div><code>lightAcceptModalConfirmButtonBackground · lightInputErrorColor · lightRequiredIconColor</code></div></div>
679+
<div class="map"><div><code>scrim</code></div><div><code>lightScrim</code></div></div>
674680
</div>
675681
</section>
676682
</div>
@@ -2460,7 +2466,7 @@ <h1 style="font-size: 32px; line-height: 38px; font-weight: 600; letter-spacing:
24602466
</div>
24612467

24622468
<section class="sec">
2463-
<div class="sec-head"><span class="sec-name">&lt;Dialog&gt;</span><span class="t-sm t-muted">confirm · destructive · form</span></div>
2469+
<div class="sec-head"><span class="sec-name">&lt;Dialog&gt;</span><span class="t-sm t-muted">confirm · destructive · form · sheet on phones</span></div>
24642470
<div class="grid3">
24652471
<div class="tile">
24662472
<div class="tile-stage stage-dlg">
@@ -2500,6 +2506,30 @@ <h1 style="font-size: 32px; line-height: 38px; font-weight: 600; letter-spacing:
25002506
</div>
25012507
</div>
25022508
<div class="grid2">
2509+
<div class="tile">
2510+
<div class="tile-stage stage-dlg">
2511+
<div class="dlg" role="dialog" aria-label="Dialog without header" style="width: 100%; max-width: 360px">
2512+
<div class="dlg-body" style="padding-top: 20px; display: flex; flex-direction: column; gap: 12px"><p>This is the first paragraph of dialog content.</p><p>And this is the second paragraph.</p></div>
2513+
<div class="dlg-foot"><button class="btn btn-secondary" type="button">Close</button></div>
2514+
</div>
2515+
</div>
2516+
<div class="tile-cap"><b>No header, built-in Close</b><code>secondary</code></div>
2517+
</div>
2518+
<div class="tile">
2519+
<div class="tile-stage stage-dlg">
2520+
<div class="mini-phone">
2521+
<div class="mini-main"><span style="width: 40%"></span><span></span><span></span><span style="width: 70%"></span><span></span><span></span></div>
2522+
<div class="mini-scrim mini-scrim-dock">
2523+
<div class="dlg dlg-sheet" role="dialog" aria-label="Approve listings on a phone">
2524+
<div class="dlg-head"><h3 class="t-h2">Approve 2 listings?</h3><button class="btn btn-ghost btn-icon btn-sm" type="button" aria-label="Close"><svg class="i" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18"></path><path d="m6 6 12 12"></path></svg></button></div>
2525+
<div class="dlg-body">Aether Nimbus S and Cinder Kiln Coupe will become visible on the public site.</div>
2526+
<div class="dlg-foot"><button class="btn btn-secondary" type="button">Cancel</button><button class="btn btn-primary" type="button">Approve</button></div>
2527+
</div>
2528+
</div>
2529+
</div>
2530+
</div>
2531+
<div class="tile-cap"><b>Phone sheet</b><code>below sm, main action on top</code></div>
2532+
</div>
25032533
</div>
25042534
</section>
25052535

‎adminforth/modules/styles.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ export const styles = () => ({
248248
lightVerticalTabsBackgroundActive: "#ECECEE",
249249
lightVerticalTabsSlotText: "#3F3F46",
250250

251+
lightScrim: "rgba(24, 24, 27, 0.32)", // page dimming behind dialogs, modals and drawers
251252
lightDialogBackgorund: "#FFFFFF",
252253
lightDialogBreakLine: "#E4E4E7",
253254
lightDialogHeaderText: "#18181B",
@@ -613,6 +614,7 @@ export const styles = () => ({
613614
darkVerticalTabsBackgroundActive: "#27272B",
614615
darkVerticalTabsSlotText: "#D4D4D8",
615616

617+
darkScrim: "rgba(0, 0, 0, 0.6)",
616618
darkDialogBackgorund: "#151517",
617619
darkDialogBreakLine: "#29292E",
618620
darkDialogHeaderText: "#F4F4F5",

‎adminforth/spa/src/App.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144

145145
<div v-if="sideBarOpen"
146146
@click="hideSidebar"
147-
drawer-backdrop="" class="bg-zinc-900/30 dark:bg-black/60 fixed inset-0 z-20">
147+
drawer-backdrop="" class="bg-lightScrim dark:bg-darkScrim fixed inset-0 z-20">
148148
</div>
149149

150150
<component

‎adminforth/spa/src/afcl/Dialog.vue‎

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<template>
22
<Modal
33
ref="modalRef"
4+
class="afcl-dialog"
5+
:aria-labelledby="header ? titleId : undefined"
46
v-bind="$attrs"
57
:closeByClickOutside="clickToCloseOutside || closeByClickOutside"
68
:closeByEsc="closeByEsc || closable"
@@ -18,35 +20,41 @@
1820
<!-- Modal header -->
1921
<div
2022
v-if="header"
21-
class="flex items-center justify-between px-5 py-4 border-b rounded-t-xl dark:border-darkDialogBreakLine border-lightDialogBreakLine"
23+
class="afcl-dialog-header flex items-start justify-between gap-3 px-5 pt-[18px] pb-1.5"
2224
>
23-
<h3 class="text-base font-semibold text-lightDialogHeaderText dark:text-darkDialogHeaderText">
25+
<h3 :id="titleId" class="text-base font-semibold tracking-[-0.01em] text-lightDialogHeaderText dark:text-darkDialogHeaderText">
2426
{{ header }}
2527
</h3>
26-
<button
28+
<Button
2729
v-if="headerCloseButton"
2830
type="button"
29-
class="text-lightDialogCloseButton bg-transparent hover:bg-lightDialogCloseButtonHoverBackground hover:text-lightDialogCloseButtonHover rounded-default text-sm w-7 h-7 ms-auto inline-flex justify-center items-center focus:outline-none focus-visible:ring-[3px] focus-visible:ring-lightFocusRing dark:focus-visible:ring-darkFocusRing dark:text-darkDialogCloseButton dark:hover:bg-darkDialogCloseButtonHoverBackground dark:hover:text-darkDialogCloseButtonHover"
31+
variant="ghost"
32+
size="sm"
33+
iconOnly
34+
class="-mt-0.5 -me-1.5 text-lightDialogCloseButton hover:text-lightDialogCloseButtonHover hover:bg-lightDialogCloseButtonHoverBackground dark:text-darkDialogCloseButton dark:hover:text-darkDialogCloseButtonHover dark:hover:bg-darkDialogCloseButtonHoverBackground"
35+
:aria-label="t('Close Modal')"
3036
@click="tryToCancelModal"
3137
>
32-
<IconX class="w-4 h-4" aria-hidden="true" />
33-
<span class="sr-only">{{ t('Close Modal') }}</span>
34-
</button>
38+
<IconX aria-hidden="true" />
39+
</Button>
3540
</div>
3641
<!-- Modal body -->
37-
<div class="px-5 py-4 text-sm text-lightDialogBodyText dark:text-darkDialogBodyText">
42+
<div
43+
class="afcl-dialog-body px-5 pb-[18px] text-sm text-lightDialogBodyText dark:text-darkDialogBodyText"
44+
:class="header ? 'pt-1.5' : 'pt-5'"
45+
>
3846
<slot></slot>
3947
</div>
4048
<!-- Modal footer -->
4149
<div
4250
v-if="buttons.length"
43-
class="flex items-center justify-end flex-wrap gap-y-2 px-5 py-3 border-t border-lightDialogBreakLine rounded-b-xl bg-lightFormHeading dark:bg-darkFormHeading dark:border-darkDialogBreakLine"
51+
class="afcl-dialog-footer"
52+
:class="dialogFooterClasses"
4453
>
4554
<Button
4655
v-for="(button, buttonIndex) in buttons"
4756
:key="buttonIndex"
4857
v-bind="button.options"
49-
:class="{ 'ms-2': buttonIndex > 0 }"
5058
@click="button.onclick(dialog)"
5159
:mode="button.options?.mode || 'primary'"
5260
>
@@ -59,8 +67,9 @@
5967
<script setup lang="ts">
6068
import Button from "./Button.vue";
6169
import { IconX } from '@iconify-prerendered/vue-lucide';
62-
import { ref, computed, type Ref } from 'vue';
70+
import { ref, computed, useId, type Ref } from 'vue';
6371
import { Modal } from '@/afcl'
72+
import { dialogFooterClasses } from './dialogStyles';
6473
import { useI18n } from "vue-i18n";
6574
6675
const { t } = useI18n();
@@ -78,6 +87,7 @@ interface DialogButton {
7887
}
7988
8089
const modalRef = ref();
90+
const titleId = useId();
8191
8292
const props = withDefaults(defineProps<DialogProps>(), {
8393
header: '',
@@ -104,7 +114,7 @@ const buttons = computed<DialogButton[]>(() => {
104114
onclick: (dialog: any) => {
105115
tryToHideModal();
106116
},
107-
options: {}
117+
options: { variant: 'secondary' }
108118
}
109119
];
110120
});

‎adminforth/spa/src/afcl/Modal.vue‎

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,29 @@
66
<slot name="trigger"></slot>
77
</div>
88
<Teleport to="body">
9+
<Transition
10+
enter-from-class="af-modal-hidden opacity-0"
11+
enter-active-class="transition-opacity duration-150 ease-out motion-reduce:transition-none"
12+
leave-active-class="transition-opacity duration-100 ease-in motion-reduce:transition-none"
13+
leave-to-class="af-modal-hidden opacity-0"
14+
>
915
<div
1016
v-show="isModalOpen"
1117
v-if="!removeFromDom"
1218
@click="backdropClick"
13-
class="bg-zinc-900/40 dark:bg-black/60 overflow-y-auto overscroll-contain overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full h-full md:inset-0 h-1rem max-h-full flex"
19+
class="afcl-modal-backdrop group/modal fixed inset-0 z-50 flex justify-center overflow-y-auto overflow-x-hidden overscroll-contain bg-lightScrim dark:bg-darkScrim max-sm:pt-12"
1420
:class="props.backgroundCustomClasses"
1521
>
1622
<!-- Modal content -->
17-
<div v-bind="$attrs" class="relative bg-lightDialogBackgorund rounded-xl shadow-popover dark:shadow-darkPopover dark:bg-darkDialogBackgorund mx-4 sm:mx-0">
23+
<div
24+
ref="panelRef"
25+
role="dialog"
26+
aria-modal="true"
27+
tabindex="-1"
28+
v-bind="$attrs"
29+
class="afcl-modal focus:outline-none transition-transform duration-150 ease-out motion-reduce:transition-none group-[.af-modal-hidden]/modal:translate-y-1 group-[.af-modal-hidden]/modal:scale-[.98] max-sm:group-[.af-modal-hidden]/modal:translate-y-full max-sm:group-[.af-modal-hidden]/modal:scale-100"
30+
:class="dialogPanelClasses"
31+
>
1832

1933
<!-- Modal body -->
2034
<div class="text-lightDialogBodyText dark:text-darkDialogBodyText">
@@ -24,13 +38,21 @@
2438
<!-- Confirmation Modal -->
2539
<div
2640
v-if="showConfirmationOnClose"
27-
class="fixed inset-0 flex items-center justify-center bg-zinc-900/40 dark:bg-black/60 z-[60]"
41+
class="fixed inset-0 z-[60] flex justify-center overflow-y-auto bg-lightScrim dark:bg-darkScrim max-sm:pt-12"
2842
:class="props.modalCustomClasses"
2943
>
30-
<div class="bg-lightDialogBackgorund dark:bg-darkDialogBackgorund p-5 rounded-xl shadow-popover dark:shadow-darkPopover max-w-sm w-full">
31-
<h2 class="text-base font-semibold mb-2 text-lightDialogHeaderText dark:text-darkDialogHeaderText">{{ t('Confirm Close') }}</h2>
32-
<p class="mb-5 text-sm text-lightDialogBodyText dark:text-darkDialogBodyText">{{ props.closeConfirmationText }}</p>
33-
<div class="flex justify-end gap-2">
44+
<div
45+
role="alertdialog"
46+
aria-modal="true"
47+
:aria-labelledby="confirmationTitleId"
48+
class="w-full sm:max-w-sm"
49+
:class="dialogPanelClasses"
50+
>
51+
<div class="px-5 py-[18px]">
52+
<h2 :id="confirmationTitleId" class="mb-1.5 text-base font-semibold text-lightDialogHeaderText dark:text-darkDialogHeaderText">{{ t('Confirm Close') }}</h2>
53+
<p class="text-sm text-lightDialogBodyText dark:text-darkDialogBodyText">{{ props.closeConfirmationText }}</p>
54+
</div>
55+
<div :class="dialogFooterClasses">
3456
<Button
3557
variant="secondary"
3658
@click="showConfirmationOnClose = false"
@@ -50,13 +72,15 @@
5072
</div>
5173
</div>
5274
</div>
75+
</Transition>
5376
</Teleport>
5477
</template>
5578

5679
<script setup lang="ts">
5780
import Button from "./Button.vue";
58-
import { ref, onMounted, nextTick, onUnmounted, computed, type Ref } from 'vue';
81+
import { ref, onMounted, nextTick, onUnmounted, computed, watch, useId, type Ref } from 'vue';
5982
import { useI18n } from 'vue-i18n';
83+
import { dialogPanelClasses, dialogFooterClasses } from './dialogStyles';
6084
6185
const isModalOpen = defineModel<boolean>('open', { default: false });
6286
const { t } = useI18n();
@@ -92,6 +116,23 @@ const props = withDefaults(defineProps<DialogProps>(), {
92116
})
93117
94118
const showConfirmationOnClose = ref(false);
119+
const confirmationTitleId = useId();
120+
121+
const panelRef = ref<HTMLElement>();
122+
let focusBeforeOpen: HTMLElement | null = null;
123+
124+
// focus goes into the dialog on open (unless the content already took it) and back to the trigger on close
125+
watch(isModalOpen, async (open) => {
126+
if (open) {
127+
focusBeforeOpen = document.activeElement as HTMLElement | null;
128+
await nextTick();
129+
if (!panelRef.value!.contains(document.activeElement)) {
130+
panelRef.value!.focus({ preventScroll: true });
131+
}
132+
} else {
133+
focusBeforeOpen?.focus({ preventScroll: true });
134+
}
135+
});
95136
96137
97138
async function open() {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// a dialog panel is centered on desktop and docks to the bottom edge as a sheet on phones (below `sm`),
2+
// `max-sm:` keeps the width classes an app passes to Dialog/Modal in charge on desktop
3+
export const dialogPanelClasses = `
4+
relative mt-auto sm:mb-auto rounded-xl
5+
bg-lightDialogBackgorund dark:bg-darkDialogBackgorund shadow-popover dark:shadow-darkPopover
6+
max-sm:w-full max-sm:max-w-none max-sm:rounded-b-none max-sm:rounded-t-2xl max-sm:pb-[env(safe-area-inset-bottom)]
7+
`;
8+
9+
// actions sit in a gray band on desktop, in the sheet they are stacked full width with the last (main) one on top
10+
export const dialogFooterClasses = `
11+
flex flex-col-reverse gap-2 px-5 pb-5
12+
sm:flex-row sm:flex-wrap sm:items-center sm:justify-end sm:py-3 sm:rounded-b-xl
13+
sm:border-t sm:border-lightDialogBreakLine sm:dark:border-darkDialogBreakLine
14+
sm:bg-lightFormHeading sm:dark:bg-darkFormHeading
15+
`;

‎adminforth/spa/src/components/AcceptModal.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
backgroundCustomClasses="z-[998]"
77
modalCustomClasses="z-[999] flex items-center justify-center"
88
>
9-
<div class="relative p-6 sm:w-[420px] rounded-xl shadow-popover dark:shadow-darkPopover bg-lightAcceptModalBackground dark:bg-darkAcceptModalBackground" >
9+
<div class="relative p-6 sm:w-[420px] rounded-[inherit] bg-lightAcceptModalBackground dark:bg-darkAcceptModalBackground" >
1010

1111
<button type="button" @click="modalStore.togleModal()" class="absolute top-3 right-3 p-1.5 rounded-default text-lightAcceptModalCloseIcon hover:text-lightAcceptModalCloseIconHover hover:bg-lightAcceptModalCloseIconHoverBackground dark:text-darkAcceptModalCloseIcon dark:hover:text-darkAcceptModalCloseIconHover dark:hover:bg-darkAcceptModalCloseIconHoverBackground transition-colors" >
1212
<IconX class="w-4 h-4" />

‎adminforth/spa/src/components/Filters.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@
159159
</div>
160160
</div>
161161

162-
<div v-if="show" class="bg-zinc-900/30 dark:bg-black/60 fixed inset-0 z-40"
162+
<div v-if="show" class="bg-lightScrim dark:bg-darkScrim fixed inset-0 z-40"
163163
@click="$emit('hide')">
164164
</div>
165165
</template>

0 commit comments

Comments
 (0)