Skip to content

Commit

Permalink
fix 1177
Browse files Browse the repository at this point in the history
  • Loading branch information
TGlide committed May 4, 2024
1 parent 3a121b6 commit 7ebc820
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 104 deletions.
5 changes: 5 additions & 0 deletions .changeset/mean-cherries-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 1,5 @@
---
'@melt-ui/svelte': patch
---

fix: Modal elements allow others to close again (closes #1177)
97 changes: 97 additions & 0 deletions src/docs/previews/popover/main/tailwind/Popover.svelte
Original file line number Diff line number Diff line change
@@ -0,0 1,97 @@
<script lang="ts">
import { createPopover, createSync, melt } from '$lib/index.js';
import { fade } from 'svelte/transition';
import { Settings2, X } from '$icons/index.js';
export let open = false;
const {
elements: { trigger, content, arrow, close },
states,
} = createPopover({
forceVisible: true,
});
const sync = createSync(states);
$: sync.open(open, (v) => (open = v));
</script>

<button
type="button"
class="trigger"
use:melt={$trigger}
aria-label="Update dimensions"
>
<Settings2 class="size-4" />
<span class="sr-only">Open Popover</span>
</button>

{#if open}
<div
use:melt={$content}
transition:fade={{ duration: 100 }}
class="force-dark content"
>
<div use:melt={$arrow} />
<div class="flex flex-col gap-2.5">
<p class="mb-2 font-medium text-neutral-900">Dimensions</p>
<fieldset class="flex items-center gap-5">
<label class="w-[75px] text-sm text-neutral-700" for="width"
>Width</label
>
<input type="number" id="width" class="input" placeholder="Width" />
</fieldset>
<fieldset class="flex items-center gap-5">
>
<label class="w-[75px] text-sm text-neutral-700" for="height"
>Height</label
>
<input type="number" id="height" class="input" placeholder="Height" />
</fieldset>
<fieldset class="flex items-center gap-5">
>
<label class="w-[75px] text-sm text-neutral-700" for="depth"
>Depth</label
>
<input type="number" id="depth" class="input" placeholder="Depth" />
</fieldset>
<fieldset class="flex items-center gap-5">
>
<label class="w-[75px] text-sm text-neutral-700" for="weight"
>Weight</label
>
<input type="number" id="weight" class="input" placeholder="Weight" />
</fieldset>
</div>
<button class="close" use:melt={$close}>
<X class="size-4" />
</button>
</div>
{/if}

<style lang="postcss">
.input {
@apply flex h-8 w-full rounded-md border border-magnum-800 bg-transparent px-2.5 text-sm;
@apply ring-offset-magnum-300 focus-visible:ring;
@apply focus-visible:ring-magnum-400 focus-visible:ring-offset-1;
@apply flex-1 items-center justify-center;
@apply px-2.5 text-sm leading-none text-magnum-700;
}
.trigger {
@apply inline-flex h-9 w-9 items-center justify-center rounded-full bg-white p-0;
@apply text-sm font-medium text-magnum-900 transition-colors hover:bg-white/90;
@apply focus-visible:ring focus-visible:ring-magnum-400 focus-visible:ring-offset-2;
}
.close {
@apply absolute right-1.5 top-1.5 flex h-7 w-7 items-center justify-center rounded-full;
@apply text-magnum-900 transition-colors hover:bg-magnum-500/10;
@apply focus-visible:ring focus-visible:ring-magnum-400 focus-visible:ring-offset-2;
@apply bg-white p-0 text-sm font-medium;
}
.content {
@apply z-10 w-60 rounded-[4px] bg-white p-5 shadow-sm;
}
</style>
94 changes: 4 additions & 90 deletions src/docs/previews/popover/main/tailwind/index.svelte
Original file line number Diff line number Diff line change
@@ -1,93 1,7 @@
<script lang="ts">
import { createPopover, melt } from '$lib/index.js';
import { fade } from 'svelte/transition';
import { Settings2, X } from '$icons/index.js';
const {
elements: { trigger, content, arrow, close },
states: { open },
} = createPopover({
forceVisible: true,
});
import Popover from './Popover.svelte';
</script>

<button
type="button"
class="trigger"
use:melt={$trigger}
aria-label="Update dimensions"
>
<Settings2 class="size-4" />
<span class="sr-only">Open Popover</span>
</button>

{#if $open}
<div
use:melt={$content}
transition:fade={{ duration: 100 }}
class="force-dark content"
>
<div use:melt={$arrow} />
<div class="flex flex-col gap-2.5">
<p>Dimensions</p>
<fieldset>
<label for="width">Width</label>
<input type="number" id="width" class="input" placeholder="Width" />
</fieldset>
<fieldset>
<label for="height">Height</label>
<input type="number" id="height" class="input" placeholder="Height" />
</fieldset>
<fieldset>
<label for="depth">Depth</label>
<input type="number" id="depth" class="input" placeholder="Depth" />
</fieldset>
<fieldset>
<label for="weight">Weight</label>
<input type="number" id="weight" class="input" placeholder="Weight" />
</fieldset>
</div>
<button class="close" use:melt={$close}>
<X class="size-4" />
</button>
</div>
{/if}

<style lang="postcss">
fieldset {
@apply flex items-center gap-5;
}
label {
@apply w-[75px] text-sm text-neutral-700;
}
p {
@apply mb-2 font-medium text-neutral-900;
}
.input {
@apply flex h-8 w-full rounded-md border border-magnum-800 bg-transparent px-2.5 text-sm;
@apply ring-offset-magnum-300 focus-visible:ring;
@apply focus-visible:ring-magnum-400 focus-visible:ring-offset-1;
@apply flex-1 items-center justify-center;
@apply px-2.5 text-sm leading-none text-magnum-700;
}
.trigger {
@apply inline-flex h-9 w-9 items-center justify-center rounded-full bg-white p-0;
@apply text-sm font-medium text-magnum-900 transition-colors hover:bg-white/90;
@apply focus-visible:ring focus-visible:ring-magnum-400 focus-visible:ring-offset-2;
}
.close {
@apply absolute right-1.5 top-1.5 flex h-7 w-7 items-center justify-center rounded-full;
@apply text-magnum-900 transition-colors hover:bg-magnum-500/10;
@apply focus-visible:ring focus-visible:ring-magnum-400 focus-visible:ring-offset-2;
@apply bg-white p-0 text-sm font-medium;
}
.content {
@apply z-10 w-60 rounded-[4px] bg-white p-5 shadow-sm;
}
</style>
<Popover />
<Popover />
<Popover />
25 changes: 13 additions & 12 deletions src/lib/builders/popover/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 19,7 @@ import {
portalAttr,
generateIds,
withGet,
sleep,
} from '$lib/internal/helpers/index.js';

import { usePopper, usePortal, type InteractOutsideEvent } from '$lib/internal/actions/index.js';
Expand Down Expand Up @@ -144,7 145,7 @@ export function createPopover(args?: CreatePopoverProps) {
},
});

function toggleOpen() {
async function toggleOpen() {
open.update((prev) => !prev);
}
function shouldCloseOnInteractOutside(e: InteractOutsideEvent) {
Expand Down Expand Up @@ -228,21 229,21 @@ export function createPopover(args?: CreatePopoverProps) {
const arrow = makeElement(name('arrow'), {
stores: arrowSize,
returned: ($arrowSize) =>
({
'data-arrow': true,
style: styleToString({
position: 'absolute',
width: `var(--arrow-size, ${$arrowSize}px)`,
height: `var(--arrow-size, ${$arrowSize}px)`,
}),
} as const),
({
'data-arrow': true,
style: styleToString({
position: 'absolute',
width: `var(--arrow-size, ${$arrowSize}px)`,
height: `var(--arrow-size, ${$arrowSize}px)`,
}),
} as const),
});

const close = makeElement(name('close'), {
returned: () =>
({
type: 'button',
} as const),
({
type: 'button',
} as const),
action: (node: HTMLElement): MeltActionReturn<PopoverEvents['close']> => {
const unsub = executeCallbacks(
addMeltEventListener(node, 'click', (e) => {
Expand Down
8 changes: 6 additions & 2 deletions src/lib/internal/actions/modal/action.ts
Original file line number Diff line number Diff line change
@@ -1,4 1,4 @@
import { isElement, last, noop } from '$lib/internal/helpers/index.js';
import { isElement, last, noop, sleep } from '$lib/internal/helpers/index.js';
import type { InteractOutsideEvent } from '../interact-outside/types.js';
import { useInteractOutside } from '../index.js';
import type { ModalConfig } from './types.js';
Expand All @@ -7,7 7,11 @@ import type { Action } from 'svelte/action';
const visibleModals: Element[] = [];
export const useModal = ((node, config) => {
let unsubInteractOutside = noop;
visibleModals.push(node);

// Filthy hack to allow closing elements before the new one appears
sleep(100).then(() => {
visibleModals.push(node);
})

function removeNodeFromVisibleModals() {
const index = visibleModals.indexOf(node);
Expand Down

0 comments on commit 7ebc820

Please sign in to comment.