-
-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathComponent.svelte
66 lines (59 loc) · 1.78 KB
/
Component.svelte
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<script lang="ts" context="module">
import type { ComponentProps, ComponentType, SvelteComponent } from 'svelte'
import { writable } from 'svelte/store'
// we will store the modal's content in a writable store to be able to react to it when the value changes
const modal = writable<ComponentType | undefined>(undefined)
const modalProps = writable<Record<string, any> | undefined>(undefined)
// we can call this function from anywhere in our code to open a modal
export const openModal = <Component extends SvelteComponent>(
component: ComponentType<Component>,
// little hack to be able to either disallow or require props
...props: { [x: string]: never } extends ComponentProps<Component> ? [] : [ComponentProps<Component>]
) => {
modal.set(component)
// `props` is an array with a single item (the object containing all the props of the component)
modalProps.set(props[0])
}
export const closeModal = () => {
modal.set(undefined)
modalProps.set(undefined)
}
</script>
<!-- basic implementation how a modal could work -->
{#if $modal}
<div class="modal">
<button class="modal__closer" on:click={closeModal}>❌</button>
<div class="modal__content">
<!-- with svelte:component we can render any component and pass arbitrary props via the spread syntax -->
<svelte:component this={$modal} {...$modalProps} />
</div>
</div>
{/if}
<style>
/* basic styling for the modal */
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
.modal__closer {
position: absolute;
top: 0;
right: 0;
padding: 1rem;
cursor: pointer;
}
.modal__content {
background: white;
padding: 2rem;
border-radius: 0.5rem;
margin: 3rem;
}
</style>