Skip to content

Commit 852938d

Browse files
authored
Merge pull request #5 from pheralb/next
v0.2.3 🚀
2 parents 76e1b4a + 6cabfa4 commit 852938d

File tree

22 files changed

+347
-163
lines changed

22 files changed

+347
-163
lines changed

.github/workflows/check.yml

+2-28
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ on:
44
push:
55
branches:
66
- main
7+
- next
78
pull_request:
89
branches:
910
- main
11+
- next
1012

1113
concurrency: ${{ github.workflow }}-${{ github.ref }}
1214

@@ -29,20 +31,6 @@ jobs:
2931
version: 8
3032
run_install: false
3133

32-
- name: Get pnpm store directory
33-
id: pnpm-cache
34-
shell: bash
35-
run: |
36-
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
37-
38-
- uses: actions/cache@v3
39-
name: Setup pnpm cache
40-
with:
41-
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
42-
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
43-
restore-keys: |
44-
${{ runner.os }}-pnpm-store-
45-
4634
- name: Install dependencies
4735
run: pnpm install
4836

@@ -67,20 +55,6 @@ jobs:
6755
version: 8
6856
run_install: false
6957

70-
- name: Get pnpm store directory
71-
id: pnpm-cache
72-
shell: bash
73-
run: |
74-
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
75-
76-
- uses: actions/cache@v3
77-
name: Setup pnpm cache
78-
with:
79-
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
80-
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
81-
restore-keys: |
82-
${{ runner.os }}-pnpm-store-
83-
8458
- name: Install dependencies
8559
run: pnpm install
8660

docs/src/components/examples/toast.tsx

+89-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ import type { ToastVariant as Variant } from '@pheralb/toast';
44
import { toast } from '@pheralb/toast';
55
import { useRef, useState } from 'react';
66
import JSConfetti from 'js-confetti';
7-
import { CheckCheckIcon, CopyIcon, PartyPopperIcon } from 'lucide-react';
7+
import {
8+
CheckCheckIcon,
9+
CircleAlertIcon,
10+
CircleCheckIcon,
11+
CopyIcon,
12+
PartyPopperIcon,
13+
} from 'lucide-react';
814

915
import { Button } from '@/ui/button';
1016
import { CopyCodeBtnStyles } from '@/ui/copyCodeBtn';
@@ -75,10 +81,12 @@ const ToastVariantExamples = () => {
7581

7682
const handleChangeVariant = (variant: Variant) => {
7783
setToastVariant(variant);
78-
toast[variant as keyof typeof toast]({
79-
text: `A ${variant} toast 🚀`,
80-
description: '✨ @pheralb/toast',
81-
});
84+
if (variant !== 'loading') {
85+
toast[variant]({
86+
text: `A ${variant} toast 🚀`,
87+
description: '✨ @pheralb/toast',
88+
});
89+
}
8290
};
8391

8492
const handleDefault = () => {
@@ -149,4 +157,79 @@ const ToastActionsExamples = () => {
149157
);
150158
};
151159

152-
export { ToastVariantExamples, ToastActionsExamples };
160+
const ToastLoadingExample = () => {
161+
const runFunction = async () => {
162+
await new Promise((resolve) => {
163+
setTimeout(() => {
164+
resolve(true);
165+
}, 2000);
166+
});
167+
};
168+
169+
const runErrorFunction = async () => {
170+
await new Promise((resolve, reject) => {
171+
setTimeout(() => {
172+
reject(new Error('Test error'));
173+
}, 2000);
174+
});
175+
};
176+
177+
const handleToastLoading = (success: boolean) => {
178+
if (success) {
179+
toast.loading({
180+
text: 'Loading',
181+
options: {
182+
promise: runFunction,
183+
success: 'Ready',
184+
error: 'Error',
185+
autoDismiss: true,
186+
onSuccess: () => {
187+
console.log('Success');
188+
},
189+
onError: () => {
190+
console.log('Error');
191+
},
192+
},
193+
});
194+
} else {
195+
toast.loading({
196+
text: 'Loading',
197+
options: {
198+
promise: runErrorFunction,
199+
success: 'Ready',
200+
error: 'Error',
201+
autoDismiss: true,
202+
onSuccess: () => {
203+
console.log('Success');
204+
},
205+
onError: () => {
206+
console.log('Error');
207+
},
208+
},
209+
});
210+
}
211+
};
212+
213+
return (
214+
<div className="flex items-center space-x-2">
215+
<Button
216+
className="mb-2"
217+
variant="outline"
218+
onClick={() => handleToastLoading(true)}
219+
>
220+
<CircleCheckIcon size={16} />
221+
<span>Show a Loading Toast (Success)</span>
222+
</Button>
223+
<Button
224+
className="mb-2"
225+
variant="outline"
226+
onClick={() => handleToastLoading(false)}
227+
>
228+
<CircleAlertIcon size={16} />
229+
<span>Show a Loading Toast (Error)</span>
230+
</Button>
231+
</div>
232+
);
233+
};
234+
235+
export { ToastVariantExamples, ToastActionsExamples, ToastLoadingExample };

docs/src/components/header.astro

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { ModeToggle } from '@/components/theme/modeToggle';
1919
<MobileMenu client:load />
2020
<a
2121
href="/"
22+
title="pheralb/toast"
2223
class="group flex items-center space-x-3 font-medium tracking-tight transition-opacity duration-75 hover:opacity-80"
2324
>
2425
<Logo width={22} className="group-hover:animate-pulse" />
@@ -32,7 +33,9 @@ import { ModeToggle } from '@/components/theme/modeToggle';
3233
SocialLinks.map((link) =>
3334
link.routes.map((route) => (
3435
<a
36+
title={route.title}
3537
href={route.path}
38+
target="_blank"
3639
class={buttonVariants({
3740
variant: 'ghost',
3841
size: 'icon',

docs/src/components/theme/modeToggle.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export function ModeToggle() {
5050
return (
5151
<DropdownMenu>
5252
<DropdownMenuTrigger asChild>
53-
<Button variant="ghost" size="icon">
53+
<Button variant="ghost" size="icon" title="Toggle theme">
5454
{theme === 'dark' ? (
5555
<Sun size={20} strokeWidth={1.5} />
5656
) : (

docs/src/content/docs/toast.mdx

+60
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ category: 'API'
77
import {
88
ToastVariantExamples,
99
ToastActionsExamples,
10+
ToastLoadingExample,
1011
} from '../../components/examples/toast';
1112

1213
> 💡 Make sure you add the [`<Toaster />`](/toaster) provider to your app first.
@@ -39,6 +40,65 @@ toast.default({
3940
});
4041
```
4142

43+
- `toast.loading`: Show a toast with loading state and will update automatically after the promise resolves or fails:
44+
45+
<ToastLoadingExample client:only="react" />
46+
47+
```tsx
48+
toast.loading({
49+
// Initial message:
50+
text: 'Loading',
51+
options: {
52+
promise: yourFunction(),
53+
success: 'Ready',
54+
error: 'Error',
55+
// Close toast automatically (the duration depends by delayDuration property):
56+
autoDismiss: true,
57+
// Optional:
58+
onSuccess: () => {
59+
console.log('Success');
60+
},
61+
// Optional:
62+
onError: () => {
63+
console.log('Error');
64+
},
65+
},
66+
});
67+
```
68+
69+
> ✨ For example, you can use [Next.js Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations) to show a loading toast while fetching data from an API:
70+
71+
```tsx
72+
// 📃 actions/testAction.ts
73+
'use server';
74+
75+
export const testAction = async (name: string) => {
76+
await new Promise((resolve) => setTimeout(resolve, 1000));
77+
return {
78+
name: `Hello, ${name}!`,
79+
};
80+
};
81+
82+
// 📃 components/Example.tsx
83+
84+
import { testAction } from '@/actions/testAction';
85+
import { toast } from '@pheralb/toast';
86+
87+
toast.loading({
88+
text: 'Getting data',
89+
options: {
90+
promise: testAction(),
91+
success: 'Ready',
92+
error: 'Error',
93+
autoDismiss: false,
94+
onSuccess: (data) => {
95+
console.log(`Success: ${data.name}`);
96+
// Success: Hello, pheralb!
97+
},
98+
},
99+
});
100+
```
101+
42102
## API Reference
43103

44104
The `toast.variant` function accepts the following options:

examples/astro/astro.config.mjs

-8
This file was deleted.

examples/astro/package.json

-24
This file was deleted.

examples/astro/src/components/showToast.tsx

-17
This file was deleted.

examples/astro/src/env.d.ts

-1
This file was deleted.

examples/astro/src/layouts/Layout.astro

-25
This file was deleted.

examples/astro/src/pages/index.astro

-11
This file was deleted.

examples/astro/tsconfig.json

-7
This file was deleted.
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use server';
2+
3+
export const testAction = async (name: string) => {
4+
await new Promise((resolve) => setTimeout(resolve, 1000));
5+
return {
6+
data: `Hello, ${name}!`,
7+
};
8+
};
9+
10+
export const testErrorAction = async () => {
11+
return new Promise((resolve, reject) => {
12+
setTimeout(() => {
13+
reject(new Error('Test error'));
14+
}, 1000);
15+
});
16+
};

examples/nextjs/src/app/layout.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ export default function RootLayout({
1818
children: React.ReactNode;
1919
}>) {
2020
return (
21-
<html lang="en" className={inter.className}>
22-
<body className="bg-white text-black dark:bg-neutral-900 dark:text-white">
21+
<html lang="en">
22+
<body
23+
className={`${inter.className} bg-white text-black dark:bg-neutral-900 dark:text-white`}
24+
>
2325
<ThemeProvider
2426
attribute="class"
2527
defaultTheme="system"

0 commit comments

Comments
 (0)