๐ Svelte ๋น ๋ฅธ ํ: ํ ์คํธ ์๋ฆผ ์์คํ ๋ง๋ค๊ธฐ
16540 ๋จ์ด sveltejavascripttoastsui
๋น์ ์ด ๋งํ๋ ํ ์คํธ? ๐
์ผ๋ฐ์ ์ธ UI ๋์์ธ ํจํด์ "ํ ์คํธ"๋๋ ์ฌ์ฉ์์๊ฒ ์ค์๊ฐ์ผ๋ก ์ผ์ด๋๋ ์ผ(์: ์์ ์ ์ถ ์ค๋ฅ, ์ ๋ฉ์์ง ๋๋ ์น๊ตฌ ์์ฒญ ๋ฑ)์ ์๋ฆฌ๋ ์์ UI ์๋ฆผ์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
์ด ๊ธฐ์ฌ์์๋ Svelte์์ ๋ค์๊ณผ ๊ฐ์ ๊ฐ๋จํ ํ ์คํธ ์์คํ
์ ๊ตฌ์ถํ ๊ฒ์
๋๋ค.
์ง์ฆ๋? ์ฐธ์กฐ REPL here
ํ ์คํธ ์๋ฆผ์ ์ํ Svelte ์คํ ์ด ๋ง๋ค๊ธฐ
ํ ์คํธ ์์คํ
์ ์ํ ๊ฐ๋จํ Svelte ์คํ ์ด๋ฅผ ๋ง๋๋ ๊ฒ๋ถํฐ ์์ํ๊ฒ ์ต๋๋ค. ์ ์ฅ์์๋ ์ ํ ์คํธ๊ฐ ์์ฑ๋๊ฑฐ๋ "ํด์ "๋ ๋ ์
๋ฐ์ดํธํ ๋ฐฐ์ด์ด ํฌํจ๋ฉ๋๋ค.
import { writable } from 'svelte/store'
export const toasts = writable([])
export const dismissToast = (id) => {
toasts.update((all) => all.filter((t) => t.id !== id))
}
export const addToast = (toast) => {
// Create a unique ID so we can easily find/remove it
// if it is dismissible/has a timeout.
const id = Math.floor(Math.random() * 10000)
// Setup some sensible defaults for a toast.
const defaults = {
id,
type: 'info',
dismissible: true,
timeout: 3000,
}
// Push the toast to the top of the list of toasts
const t = { ...defaults, ...toast }
toasts.update((all) => [t, ...all])
// If toast is dismissible, dismiss it after "timeout" amount of time.
if (t.timeout) setTimeout(() => dismissToast(id), t.timeout)
}
์ ๋ฐ์ ์ผ๋ก ์ด๊ฒ์ ๋งค์ฐ ๊ฐ๋จํด์ผ ํฉ๋๋ค. ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ํ๋๋ ํ ์คํธ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด๊ณ ๋ค๋ฅธ ํ๋๋ ์ ๊ฑฐํ๋ ๊ฒ์
๋๋ค. ํ ์คํธ์ timeout
ํ๋๊ฐ ์๋ ๊ฒฝ์ฐ ํ ์คํธ๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ํด ์๊ฐ ์ด๊ณผ๋ฅผ ์ค์ ํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๋ชจ๋ ํ ์คํธ์ ๋ช ๊ฐ์ง ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ๊ณ ํ ์คํธ์ id
๋ฅผ ์ ๊ณตํ์ฌ ๋ ์ฝ๊ฒ ์ถ๊ฐ/์ ๊ฑฐํ๊ณ Svelte์ ํ๊ทธ{#each}
๊ฐ ๋ ๋์ ์์ธ์ ์์ฑํ๋๋ก ํฉ๋๋ค.
ํ ์คํธ ๋ถ๋ชจ ๊ตฌ์ฑ ์์ ๋ง๋ค๊ธฐ
<script lang="ts">
import Toast from './Toast.svelte'
import { dismissToast, toasts } from './store'
</script>
{#if $toasts}
<section>
{#each $toasts as toast (toast.id)}
<Toast
type={toast.type}
dismissible={toast.dismissible}
on:dismiss={() => dismissToast(toast.id)}>{toast.message}</Toast>
{/each}
</section>
{/if}
<style lang="postcss">
section {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
display: flex;
margin-top: 1rem;
justify-content: center;
flex-direction: column;
z-index: 1000;
}
</style>
ํ ์คํธ ๊ตฌ์ฑ ์์ ๋ง๋ค๊ธฐ
๋ค์์ผ๋ก ์ฑ๊ณต, ์ค๋ฅ ๋ฐ ์ ๋ณด์ ๊ฐ์ ๋ค์ํ ์ํ๋ฅผ ๊ฐ์ง Toast.svelte
๊ตฌ์ฑ ์์๋ฅผ ์์ฑํฉ๋๋ค.
<script>
import { createEventDispatcher } from 'svelte'
import { fade } from 'svelte/transition'
import SuccessIcon from './SuccessIcon.svelte'
import ErrorIcon from './ErrorIcon.svelte'
import InfoIcon from './InfoIcon.svelte'
import CloseIcon from './CloseIcon.svelte'
const dispatch = createEventDispatcher()
export let type = 'error'
export let dismissible = true
</script>
<article class={type} role="alert" transition:fade>
{#if type === 'success'}
<SuccessIcon width="1.1em" />
{:else if type === 'error'}
<ErrorIcon width="1.1em" />
{:else}
<InfoIcon width="1.1em" />
{/if}
<div class="text">
<slot />
</div>
{#if dismissible}
<button class="close" on:click={() => dispatch('dismiss')}>
<CloseIcon width="0.8em" />
</button>
{/if}
</article>
<style lang="postcss">
article {
color: white;
padding: 0.75rem 1.5rem;
border-radius: 0.2rem;
display: flex;
align-items: center;
margin: 0 auto 0.5rem auto;
width: 20rem;
}
.error {
background: IndianRed;
}
.success {
background: MediumSeaGreen;
}
.info {
background: SkyBlue;
}
.text {
margin-left: 1rem;
}
button {
color: white;
background: transparent;
border: 0 none;
padding: 0;
margin: 0 0 0 auto;
line-height: 1;
font-size: 1rem;
}
</style>
๋ฐ๋ผ๊ฑด๋ ์ด ๊ตฌ์ฑ ์์๋ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค. ์ถ๋ฐฐ๋ฅผ ์ํ ์ผ๋ถ ์คํ์ผ์ผ ๋ฟ์ด๋ฉฐ "ํด์ ๊ฐ๋ฅ"ํ๊ณ ์์ด์ฝ ๊ตฌ์ฑ ์์(SVG์ผ ๋ฟ์)๊ฐ ์ค๋ ๊ฒฝ์ฐ์ ๋ํ ๋ช ๊ฐ์ง ์กฐ๊ฑด์
๋๋ค.
ํ ์คํธ ์๋ฆผ ๋ง๋ค๊ธฐ
์ด์ Svelte ์ฑ(JS ํ์ผ ๋๋ .svelte
ํ์ผ)์ ์ด๋ ๊ณณ์์๋ ํ ์คํธ ์๋ฆผ์ ๋ง๋ค ์ ์์ต๋๋ค.
import { addToast } from "./store";
addToast({
message: "Hello, World!",
type: "success",
dismissible: true,
timeout: 3000,
});
๊ทธ๋ฐ ๋ค์ ๋ ์ด์์ ๊ตฌ์ฑ ์์์ ์ด๋๊ฐ์์ <Toasts />
๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค(์: App.svelte
๋๋ _layout.svelte
๋ฑ).
๋ง๋ฌด๋ฆฌ ๐ฏ
๊ทธ๊ฒ ๋ค์ผ ์ฌ๋ฌ๋ถ, ์ค๋ ๋ญ๊ฐ๋ฅผ ๋ฐฐ์ฐ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค!
Svelte REPL here์์ ์ ์ฒด ํ ์คํธ ์์คํ
์ ์ฐธ์กฐํ์ญ์์ค.
์ฝ์ด ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค!
์ฝ์ด ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค! ์ด ๊ฒ์๋ฌผ์ โค๏ธ, ๐ฆ ๋๋ ๐๋ฅผ ์ง์ ํ์ฌ ๋์ค์ ๋ถ๋งํฌํ ์ ์์ต๋๋ค. ๐
๋ค๋ฅธ ํ, ์์ด๋์ด, ํผ๋๋ฐฑ ๋๋ ์์ ์ฌํญ์ด ์์ต๋๊น? ๋๊ธ๋ก ์๋ ค์ฃผ์ธ์! ๐โโ๏ธ
Dev.to( ), Twitter( ) ๋ฐ/๋๋ Github(danawoodman )์์ ์ ๋ฅผ ํ๋ก์ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์!
์ฌ์ง ์ ๊ณต: Joshua Aragon on Unsplash
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ Svelte ๋น ๋ฅธ ํ: ํ ์คํธ ์๋ฆผ ์์คํ
๋ง๋ค๊ธฐ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/danawoodman/svelte-quick-tip-creating-a-toast-notification-system-ge3
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
ํ ์คํธ ์์คํ ์ ์ํ ๊ฐ๋จํ Svelte ์คํ ์ด๋ฅผ ๋ง๋๋ ๊ฒ๋ถํฐ ์์ํ๊ฒ ์ต๋๋ค. ์ ์ฅ์์๋ ์ ํ ์คํธ๊ฐ ์์ฑ๋๊ฑฐ๋ "ํด์ "๋ ๋ ์ ๋ฐ์ดํธํ ๋ฐฐ์ด์ด ํฌํจ๋ฉ๋๋ค.
import { writable } from 'svelte/store'
export const toasts = writable([])
export const dismissToast = (id) => {
toasts.update((all) => all.filter((t) => t.id !== id))
}
export const addToast = (toast) => {
// Create a unique ID so we can easily find/remove it
// if it is dismissible/has a timeout.
const id = Math.floor(Math.random() * 10000)
// Setup some sensible defaults for a toast.
const defaults = {
id,
type: 'info',
dismissible: true,
timeout: 3000,
}
// Push the toast to the top of the list of toasts
const t = { ...defaults, ...toast }
toasts.update((all) => [t, ...all])
// If toast is dismissible, dismiss it after "timeout" amount of time.
if (t.timeout) setTimeout(() => dismissToast(id), t.timeout)
}
์ ๋ฐ์ ์ผ๋ก ์ด๊ฒ์ ๋งค์ฐ ๊ฐ๋จํด์ผ ํฉ๋๋ค. ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ํ๋๋ ํ ์คํธ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด๊ณ ๋ค๋ฅธ ํ๋๋ ์ ๊ฑฐํ๋ ๊ฒ์ ๋๋ค. ํ ์คํธ์
timeout
ํ๋๊ฐ ์๋ ๊ฒฝ์ฐ ํ ์คํธ๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ํด ์๊ฐ ์ด๊ณผ๋ฅผ ์ค์ ํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๋ชจ๋ ํ ์คํธ์ ๋ช ๊ฐ์ง ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ๊ณ ํ ์คํธ์ id
๋ฅผ ์ ๊ณตํ์ฌ ๋ ์ฝ๊ฒ ์ถ๊ฐ/์ ๊ฑฐํ๊ณ Svelte์ ํ๊ทธ{#each}
๊ฐ ๋ ๋์ ์์ธ์ ์์ฑํ๋๋ก ํฉ๋๋ค.ํ ์คํธ ๋ถ๋ชจ ๊ตฌ์ฑ ์์ ๋ง๋ค๊ธฐ
<script lang="ts">
import Toast from './Toast.svelte'
import { dismissToast, toasts } from './store'
</script>
{#if $toasts}
<section>
{#each $toasts as toast (toast.id)}
<Toast
type={toast.type}
dismissible={toast.dismissible}
on:dismiss={() => dismissToast(toast.id)}>{toast.message}</Toast>
{/each}
</section>
{/if}
<style lang="postcss">
section {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
display: flex;
margin-top: 1rem;
justify-content: center;
flex-direction: column;
z-index: 1000;
}
</style>
ํ ์คํธ ๊ตฌ์ฑ ์์ ๋ง๋ค๊ธฐ
๋ค์์ผ๋ก ์ฑ๊ณต, ์ค๋ฅ ๋ฐ ์ ๋ณด์ ๊ฐ์ ๋ค์ํ ์ํ๋ฅผ ๊ฐ์ง Toast.svelte
๊ตฌ์ฑ ์์๋ฅผ ์์ฑํฉ๋๋ค.
<script>
import { createEventDispatcher } from 'svelte'
import { fade } from 'svelte/transition'
import SuccessIcon from './SuccessIcon.svelte'
import ErrorIcon from './ErrorIcon.svelte'
import InfoIcon from './InfoIcon.svelte'
import CloseIcon from './CloseIcon.svelte'
const dispatch = createEventDispatcher()
export let type = 'error'
export let dismissible = true
</script>
<article class={type} role="alert" transition:fade>
{#if type === 'success'}
<SuccessIcon width="1.1em" />
{:else if type === 'error'}
<ErrorIcon width="1.1em" />
{:else}
<InfoIcon width="1.1em" />
{/if}
<div class="text">
<slot />
</div>
{#if dismissible}
<button class="close" on:click={() => dispatch('dismiss')}>
<CloseIcon width="0.8em" />
</button>
{/if}
</article>
<style lang="postcss">
article {
color: white;
padding: 0.75rem 1.5rem;
border-radius: 0.2rem;
display: flex;
align-items: center;
margin: 0 auto 0.5rem auto;
width: 20rem;
}
.error {
background: IndianRed;
}
.success {
background: MediumSeaGreen;
}
.info {
background: SkyBlue;
}
.text {
margin-left: 1rem;
}
button {
color: white;
background: transparent;
border: 0 none;
padding: 0;
margin: 0 0 0 auto;
line-height: 1;
font-size: 1rem;
}
</style>
๋ฐ๋ผ๊ฑด๋ ์ด ๊ตฌ์ฑ ์์๋ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค. ์ถ๋ฐฐ๋ฅผ ์ํ ์ผ๋ถ ์คํ์ผ์ผ ๋ฟ์ด๋ฉฐ "ํด์ ๊ฐ๋ฅ"ํ๊ณ ์์ด์ฝ ๊ตฌ์ฑ ์์(SVG์ผ ๋ฟ์)๊ฐ ์ค๋ ๊ฒฝ์ฐ์ ๋ํ ๋ช ๊ฐ์ง ์กฐ๊ฑด์
๋๋ค.
ํ ์คํธ ์๋ฆผ ๋ง๋ค๊ธฐ
์ด์ Svelte ์ฑ(JS ํ์ผ ๋๋ .svelte
ํ์ผ)์ ์ด๋ ๊ณณ์์๋ ํ ์คํธ ์๋ฆผ์ ๋ง๋ค ์ ์์ต๋๋ค.
import { addToast } from "./store";
addToast({
message: "Hello, World!",
type: "success",
dismissible: true,
timeout: 3000,
});
๊ทธ๋ฐ ๋ค์ ๋ ์ด์์ ๊ตฌ์ฑ ์์์ ์ด๋๊ฐ์์ <Toasts />
๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค(์: App.svelte
๋๋ _layout.svelte
๋ฑ).
๋ง๋ฌด๋ฆฌ ๐ฏ
๊ทธ๊ฒ ๋ค์ผ ์ฌ๋ฌ๋ถ, ์ค๋ ๋ญ๊ฐ๋ฅผ ๋ฐฐ์ฐ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค!
Svelte REPL here์์ ์ ์ฒด ํ ์คํธ ์์คํ
์ ์ฐธ์กฐํ์ญ์์ค.
์ฝ์ด ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค!
์ฝ์ด ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค! ์ด ๊ฒ์๋ฌผ์ โค๏ธ, ๐ฆ ๋๋ ๐๋ฅผ ์ง์ ํ์ฌ ๋์ค์ ๋ถ๋งํฌํ ์ ์์ต๋๋ค. ๐
๋ค๋ฅธ ํ, ์์ด๋์ด, ํผ๋๋ฐฑ ๋๋ ์์ ์ฌํญ์ด ์์ต๋๊น? ๋๊ธ๋ก ์๋ ค์ฃผ์ธ์! ๐โโ๏ธ
Dev.to( ), Twitter( ) ๋ฐ/๋๋ Github(danawoodman )์์ ์ ๋ฅผ ํ๋ก์ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์!
์ฌ์ง ์ ๊ณต: Joshua Aragon on Unsplash
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ Svelte ๋น ๋ฅธ ํ: ํ ์คํธ ์๋ฆผ ์์คํ
๋ง๋ค๊ธฐ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/danawoodman/svelte-quick-tip-creating-a-toast-notification-system-ge3
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
<script lang="ts">
import Toast from './Toast.svelte'
import { dismissToast, toasts } from './store'
</script>
{#if $toasts}
<section>
{#each $toasts as toast (toast.id)}
<Toast
type={toast.type}
dismissible={toast.dismissible}
on:dismiss={() => dismissToast(toast.id)}>{toast.message}</Toast>
{/each}
</section>
{/if}
<style lang="postcss">
section {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
display: flex;
margin-top: 1rem;
justify-content: center;
flex-direction: column;
z-index: 1000;
}
</style>
๋ค์์ผ๋ก ์ฑ๊ณต, ์ค๋ฅ ๋ฐ ์ ๋ณด์ ๊ฐ์ ๋ค์ํ ์ํ๋ฅผ ๊ฐ์ง
Toast.svelte
๊ตฌ์ฑ ์์๋ฅผ ์์ฑํฉ๋๋ค.<script>
import { createEventDispatcher } from 'svelte'
import { fade } from 'svelte/transition'
import SuccessIcon from './SuccessIcon.svelte'
import ErrorIcon from './ErrorIcon.svelte'
import InfoIcon from './InfoIcon.svelte'
import CloseIcon from './CloseIcon.svelte'
const dispatch = createEventDispatcher()
export let type = 'error'
export let dismissible = true
</script>
<article class={type} role="alert" transition:fade>
{#if type === 'success'}
<SuccessIcon width="1.1em" />
{:else if type === 'error'}
<ErrorIcon width="1.1em" />
{:else}
<InfoIcon width="1.1em" />
{/if}
<div class="text">
<slot />
</div>
{#if dismissible}
<button class="close" on:click={() => dispatch('dismiss')}>
<CloseIcon width="0.8em" />
</button>
{/if}
</article>
<style lang="postcss">
article {
color: white;
padding: 0.75rem 1.5rem;
border-radius: 0.2rem;
display: flex;
align-items: center;
margin: 0 auto 0.5rem auto;
width: 20rem;
}
.error {
background: IndianRed;
}
.success {
background: MediumSeaGreen;
}
.info {
background: SkyBlue;
}
.text {
margin-left: 1rem;
}
button {
color: white;
background: transparent;
border: 0 none;
padding: 0;
margin: 0 0 0 auto;
line-height: 1;
font-size: 1rem;
}
</style>
๋ฐ๋ผ๊ฑด๋ ์ด ๊ตฌ์ฑ ์์๋ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค. ์ถ๋ฐฐ๋ฅผ ์ํ ์ผ๋ถ ์คํ์ผ์ผ ๋ฟ์ด๋ฉฐ "ํด์ ๊ฐ๋ฅ"ํ๊ณ ์์ด์ฝ ๊ตฌ์ฑ ์์(SVG์ผ ๋ฟ์)๊ฐ ์ค๋ ๊ฒฝ์ฐ์ ๋ํ ๋ช ๊ฐ์ง ์กฐ๊ฑด์ ๋๋ค.
ํ ์คํธ ์๋ฆผ ๋ง๋ค๊ธฐ
์ด์ Svelte ์ฑ(JS ํ์ผ ๋๋ .svelte
ํ์ผ)์ ์ด๋ ๊ณณ์์๋ ํ ์คํธ ์๋ฆผ์ ๋ง๋ค ์ ์์ต๋๋ค.
import { addToast } from "./store";
addToast({
message: "Hello, World!",
type: "success",
dismissible: true,
timeout: 3000,
});
๊ทธ๋ฐ ๋ค์ ๋ ์ด์์ ๊ตฌ์ฑ ์์์ ์ด๋๊ฐ์์ <Toasts />
๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค(์: App.svelte
๋๋ _layout.svelte
๋ฑ).
๋ง๋ฌด๋ฆฌ ๐ฏ
๊ทธ๊ฒ ๋ค์ผ ์ฌ๋ฌ๋ถ, ์ค๋ ๋ญ๊ฐ๋ฅผ ๋ฐฐ์ฐ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค!
Svelte REPL here์์ ์ ์ฒด ํ ์คํธ ์์คํ
์ ์ฐธ์กฐํ์ญ์์ค.
์ฝ์ด ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค!
์ฝ์ด ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค! ์ด ๊ฒ์๋ฌผ์ โค๏ธ, ๐ฆ ๋๋ ๐๋ฅผ ์ง์ ํ์ฌ ๋์ค์ ๋ถ๋งํฌํ ์ ์์ต๋๋ค. ๐
๋ค๋ฅธ ํ, ์์ด๋์ด, ํผ๋๋ฐฑ ๋๋ ์์ ์ฌํญ์ด ์์ต๋๊น? ๋๊ธ๋ก ์๋ ค์ฃผ์ธ์! ๐โโ๏ธ
Dev.to( ), Twitter( ) ๋ฐ/๋๋ Github(danawoodman )์์ ์ ๋ฅผ ํ๋ก์ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์!
์ฌ์ง ์ ๊ณต: Joshua Aragon on Unsplash
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ Svelte ๋น ๋ฅธ ํ: ํ ์คํธ ์๋ฆผ ์์คํ
๋ง๋ค๊ธฐ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/danawoodman/svelte-quick-tip-creating-a-toast-notification-system-ge3
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
import { addToast } from "./store";
addToast({
message: "Hello, World!",
type: "success",
dismissible: true,
timeout: 3000,
});
๊ทธ๊ฒ ๋ค์ผ ์ฌ๋ฌ๋ถ, ์ค๋ ๋ญ๊ฐ๋ฅผ ๋ฐฐ์ฐ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค!
Svelte REPL here์์ ์ ์ฒด ํ ์คํธ ์์คํ ์ ์ฐธ์กฐํ์ญ์์ค.
์ฝ์ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!
์ฝ์ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค! ์ด ๊ฒ์๋ฌผ์ โค๏ธ, ๐ฆ ๋๋ ๐๋ฅผ ์ง์ ํ์ฌ ๋์ค์ ๋ถ๋งํฌํ ์ ์์ต๋๋ค. ๐
๋ค๋ฅธ ํ, ์์ด๋์ด, ํผ๋๋ฐฑ ๋๋ ์์ ์ฌํญ์ด ์์ต๋๊น? ๋๊ธ๋ก ์๋ ค์ฃผ์ธ์! ๐โโ๏ธ
Dev.to( ), Twitter( ) ๋ฐ/๋๋ Github(danawoodman )์์ ์ ๋ฅผ ํ๋ก์ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์!
์ฌ์ง ์ ๊ณต: Joshua Aragon on Unsplash
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ Svelte ๋น ๋ฅธ ํ: ํ ์คํธ ์๋ฆผ ์์คํ ๋ง๋ค๊ธฐ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://dev.to/danawoodman/svelte-quick-tip-creating-a-toast-notification-system-ge3ํ ์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค