Skip to content

Commit 4e1a038

Browse files
committed
feat(toastify): make toastify components
- make toastify component for pop up message
1 parent a58dbe7 commit 4e1a038

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed

apps/client/src/app.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@
1313
animation: rotate 10s ease-in-out infinite alternate;
1414
}
1515

16+
@keyframes slide-in {
17+
from {
18+
opacity: 0;
19+
transform: translateX(100%);
20+
}
21+
to {
22+
opacity: 1;
23+
transform: translateX(0);
24+
}
25+
}
26+
27+
.animate-slide-in {
28+
animation: slide-in 0.3s ease-in-out;
29+
}
30+
1631
input[type='range'] {
1732
-webkit-appearance: none;
1833
appearance: none;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<script lang="ts">
2+
let { type, duration = 5000, children } = $props();
3+
4+
let bgColor = $state('');
5+
6+
if (type === 'success') bgColor = '#34D399';
7+
else if (type === 'error') bgColor = '#FB7185';
8+
else bgColor = '#38BDF8';
9+
</script>
10+
11+
<div
12+
class="relative rounded text-white bg-slate-900 min-w-sm min-h-20 p-2 custom-before animate-pop"
13+
style="
14+
--before-bg-color: {bgColor};
15+
--animation-duration: {duration}ms;
16+
--animation-duration-s: {duration / 1000}s;
17+
"
18+
>
19+
<strong>
20+
<p>{@render children()}</p>
21+
<span>{type}</span>
22+
</strong>
23+
</div>
24+
25+
<style>
26+
@keyframes animate-width {
27+
from {
28+
width: 0%;
29+
}
30+
to {
31+
width: 100%;
32+
}
33+
}
34+
35+
@keyframes animate-pop {
36+
from {
37+
transform: scale(0.8);
38+
}
39+
to {
40+
transform: scale(1);
41+
}
42+
}
43+
44+
.custom-before::before {
45+
content: '';
46+
position: absolute;
47+
top: 0;
48+
left: 0;
49+
height: 4px;
50+
width: 100%;
51+
background-color: var(--before-bg-color);
52+
animation: animate-width linear forwards;
53+
animation-duration: var(--animation-duration-s);
54+
}
55+
56+
.animate-pop {
57+
animation: animate-pop linear forwards;
58+
animation-duration: 0.2s;
59+
}
60+
</style>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
<script lang="ts">
2+
import Toast from '$components/toast.svelte';
3+
import { ToastState } from '$states/toast.svelte';
24
import '../app.css';
35
46
let { children } = $props();
57
</script>
68

9+
<div class="absolute z-10 flex flex-col bottom-2 right-2 gap-2">
10+
{#each ToastState.queue as toast (toast.id)}
11+
<Toast type={toast.type} duration={toast.duration}>
12+
{toast.message}
13+
</Toast>
14+
{/each}
15+
</div>
16+
717
{@render children()}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// toast.svelte.ts
2+
export type ToastType = 'success' | 'error' | 'info';
3+
4+
export interface IToastMessage {
5+
id: number;
6+
message: string;
7+
type: ToastType;
8+
duration: number;
9+
}
10+
11+
export interface IToastState {
12+
queue: IToastMessage[];
13+
}
14+
15+
export const ToastState = $state<IToastState>({
16+
queue: []
17+
});
18+
19+
let toastId = 0;
20+
21+
export function addToast(message: string, type: ToastType, duration: number = 5000) {
22+
const id = toastId++;
23+
24+
const toast: IToastMessage = {
25+
id,
26+
message,
27+
type,
28+
duration
29+
};
30+
31+
ToastState.queue.push(toast);
32+
33+
setTimeout(() => {
34+
ToastState.queue.shift();
35+
}, duration);
36+
}

0 commit comments

Comments
 (0)