Skip to content

Commit 76e1b4a

Browse files
authored
Merge pull request #4 from pheralb/astro
✨ Migrate docs to Astro Content
2 parents 069d485 + b3426d9 commit 76e1b4a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+1265
-1051
lines changed

.changeset/config.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"baseBranch": "main",
99
"updateInternalDependencies": "patch",
1010
"ignore": [
11-
"@pheralb/toast-website",
11+
"@pheralb/toast-docs",
1212
"@pheralb-toast/nextjs-example",
1313
"@pheralb-toast/astro-example"
1414
]

.vscode/extensions.json

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"recommendations": ["astro-build.astro-vscode"],
3+
"unwantedRecommendations": []
4+
}

docs/astro.config.ts

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { defineConfig } from 'astro/config';
2+
3+
// Integrations:
4+
import react from '@astrojs/react';
5+
import tailwind from '@astrojs/tailwind';
6+
import mdx from '@astrojs/mdx';
7+
8+
// MDX Plugins:
9+
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
10+
import rehypeSlug from 'rehype-slug';
11+
import { HEADING_LINK_ANCHOR } from './src/ui/headings';
12+
13+
// Astro config:
14+
export default defineConfig({
15+
site: 'https://toast.pheralb.dev',
16+
integrations: [
17+
react(),
18+
tailwind({
19+
applyBaseStyles: false,
20+
}),
21+
mdx({
22+
syntaxHighlight: 'shiki',
23+
shikiConfig: { theme: 'vesper', wrap: true },
24+
gfm: true,
25+
rehypePlugins: [
26+
rehypeSlug,
27+
[
28+
rehypeAutolinkHeadings,
29+
{ behavior: 'wrap', properties: { className: HEADING_LINK_ANCHOR } },
30+
],
31+
],
32+
}),
33+
],
34+
});

website/components.json docs/components.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"tsx": true,
66
"tailwind": {
77
"config": "tailwind.config.ts",
8-
"css": "styles/globals.css",
8+
"css": "src/styles/globals.css",
99
"baseColor": "neutral",
1010
"cssVariables": false,
1111
"prefix": ""

docs/package.json

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "@pheralb/toast-docs",
3+
"type": "module",
4+
"version": "1.0.0",
5+
"scripts": {
6+
"dev": "astro dev",
7+
"start": "astro dev",
8+
"build": "astro check && astro build",
9+
"preview": "astro preview",
10+
"astro": "astro"
11+
},
12+
"dependencies": {
13+
"@astrojs/check": "0.9.1",
14+
"@astrojs/mdx": "3.1.3",
15+
"@astrojs/react": "3.6.1",
16+
"@astrojs/tailwind": "5.1.0",
17+
"@radix-ui/react-dropdown-menu": "2.1.1",
18+
"@radix-ui/react-icons": "1.3.0",
19+
"@radix-ui/react-slot": "1.1.0",
20+
"astro": "4.13.0",
21+
"class-variance-authority": "0.7.0",
22+
"clsx": "2.1.1",
23+
"fast-npm-meta": "0.0.1",
24+
"js-confetti": "0.12.0",
25+
"lucide-react": "0.399.0",
26+
"react": "18.3.1",
27+
"react-dom": "18.3.1",
28+
"rehype-autolink-headings": "7.1.0",
29+
"rehype-slug": "6.0.0",
30+
"tailwind-merge": "2.3.0",
31+
"tailwindcss-animate": "1.0.7",
32+
"zustand": "4.5.4"
33+
},
34+
"devDependencies": {
35+
"@tailwindcss/typography": "0.5.13",
36+
"@types/react": "18.3.3",
37+
"@types/react-dom": "18.3.0",
38+
"tailwindcss": "3.4.7",
39+
"typescript": "5.5.4"
40+
}
41+
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

website/app/components/examples/toast.tsx docs/src/components/examples/toast.tsx

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
1-
import type { Variant } from '@pheralb-toast/extra-types';
21
import type { CodeBlockProps } from './examples.types';
2+
import type { ToastVariant as Variant } from '@pheralb/toast';
33

4-
import { useRef, useState } from 'react';
5-
import { Button } from '@/ui/button';
64
import { toast } from '@pheralb/toast';
5+
import { useRef, useState } from 'react';
76
import JSConfetti from 'js-confetti';
8-
import { CopyIcon, PartyPopperIcon } from 'lucide-react';
7+
import { CheckCheckIcon, CopyIcon, PartyPopperIcon } from 'lucide-react';
8+
9+
import { Button } from '@/ui/button';
10+
import { CopyCodeBtnStyles } from '@/ui/copyCodeBtn';
911
import { copyToClipboard } from '@/utils';
10-
import { CopyCodeBtnStyles } from '../mdx/codeBlock';
1112

1213
const ToastCodeBlock = (props: CodeBlockProps) => {
1314
const preRef = useRef<HTMLPreElement>(null);
15+
const [isCopied, setIsCopied] = useState<boolean>(false);
1416

1517
const copyPreContent = async () => {
1618
const content = preRef.current?.textContent ?? '';
1719
await copyToClipboard(content);
18-
toast.success({
19-
text: 'Copied to clipboard',
20-
});
20+
setIsCopied(true);
21+
setTimeout(() => setIsCopied(false), 700);
2122
};
2223

2324
return (
@@ -62,7 +63,7 @@ const ToastCodeBlock = (props: CodeBlockProps) => {
6263
</pre>
6364
<button className={CopyCodeBtnStyles} onClick={copyPreContent}>
6465
<span className="sr-only">Copy</span>
65-
<CopyIcon size={16} />
66+
{isCopied ? <CheckCheckIcon size={16} /> : <CopyIcon size={16} />}
6667
</button>
6768
</div>
6869
);

website/app/components/examples/toaster.tsx docs/src/components/examples/toaster.tsx

+17-11
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,37 @@
1-
import type { Position, Theme } from '@pheralb-toast/extra-types';
21
import type { CodeBlockProps } from './examples.types';
32

4-
import { toast } from '@pheralb/toast';
3+
import type {
4+
ToastPosition as Position,
5+
ToastTheme as Theme,
6+
} from '@pheralb/toast';
7+
8+
import { useRef, useState } from 'react';
59
import { useDocsStore } from '@/store';
10+
11+
import { toast } from '@pheralb/toast';
612
import { Button } from '@/ui/button';
713
import {
14+
CheckCheckIcon,
815
CheckIcon,
916
CopyIcon,
1017
MoonIcon,
1118
RefreshCcwIcon,
1219
SunIcon,
1320
} from 'lucide-react';
1421
import { cn, copyToClipboard } from '@/utils';
15-
import { useRef } from 'react';
16-
import { CopyCodeBtnStyles } from '../mdx/codeBlock';
22+
import { CopyCodeBtnStyles } from '@/ui/copyCodeBtn';
1723

18-
const activeBtn = cn('border-neutral-600 dark:border-neutral-800');
24+
const activeBtn = cn('border-neutral-600 dark:border-neutral-700');
1925

2026
const ProviderCodeBlock = (props: CodeBlockProps) => {
2127
const preRef = useRef<HTMLPreElement>(null);
28+
const [isCopied, setIsCopied] = useState<boolean>(false);
2229

2330
const copyPreContent = async () => {
2431
const content = preRef.current?.textContent ?? '';
2532
await copyToClipboard(content);
26-
toast.success({
27-
text: 'Copied to clipboard',
28-
});
33+
setIsCopied(true);
34+
setTimeout(() => setIsCopied(false), 700);
2935
};
3036

3137
return (
@@ -56,7 +62,7 @@ const ProviderCodeBlock = (props: CodeBlockProps) => {
5662
</pre>
5763
<button className={CopyCodeBtnStyles} onClick={copyPreContent}>
5864
<span className="sr-only">Copy</span>
59-
<CopyIcon size={16} />
65+
{isCopied ? <CheckCheckIcon size={16} /> : <CopyIcon size={16} />}
6066
</button>
6167
</div>
6268
);
@@ -130,7 +136,7 @@ const Positions = () => {
130136
);
131137
};
132138

133-
const Theme = () => {
139+
const ThemeExamples = () => {
134140
const { toastTheme, setToastTheme } = useDocsStore();
135141
const iconSize = 14;
136142

@@ -186,4 +192,4 @@ const Theme = () => {
186192
);
187193
};
188194

189-
export { Positions, Theme };
195+
export { Positions, ThemeExamples };

docs/src/components/header.astro

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
import { cn } from '@/utils';
3+
import { SocialLinks } from '@/docs.config';
4+
5+
import { buttonVariants } from '@/ui/button';
6+
import { Logo } from '@/components/icons';
7+
import MobileMenu from '@/components/mobileMenu';
8+
import { ModeToggle } from '@/components/theme/modeToggle';
9+
---
10+
11+
<nav
12+
class={cn(
13+
'sticky top-0 z-50 bg-neutral-50/90 backdrop-blur-sm dark:bg-neutral-900/90',
14+
'flex w-full py-4 dark:border-neutral-800',
15+
)}
16+
>
17+
<div class="container flex max-w-7xl items-center justify-between">
18+
<div class="flex items-center">
19+
<MobileMenu client:load />
20+
<a
21+
href="/"
22+
class="group flex items-center space-x-3 font-medium tracking-tight transition-opacity duration-75 hover:opacity-80"
23+
>
24+
<Logo width={22} className="group-hover:animate-pulse" />
25+
<span class="text-neutral-700 dark:text-neutral-300">
26+
pheralb/toast
27+
</span>
28+
</a>
29+
</div>
30+
<div class="flex items-center space-x-1">
31+
{
32+
SocialLinks.map((link) =>
33+
link.routes.map((route) => (
34+
<a
35+
href={route.path}
36+
class={buttonVariants({
37+
variant: 'ghost',
38+
size: 'icon',
39+
className: 'group',
40+
})}
41+
>
42+
{route.icon && <route.icon height={18} width={18} />}
43+
<span class="sr-only">{route.title}</span>
44+
</a>
45+
)),
46+
)
47+
}
48+
<ModeToggle client:load />
49+
</div>
50+
</div>
51+
</nav>
File renamed without changes.
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<script is:inline data-astro-rerun>
2+
document.addEventListener(
3+
'astro:page-load',
4+
() => {
5+
let copyButtonLabel = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>`;
6+
let codeBlocks = Array.from(document.querySelectorAll('pre'));
7+
8+
for (let codeBlock of codeBlocks) {
9+
let wrapper = document.createElement('div');
10+
wrapper.style.position = 'relative';
11+
12+
let copyButton = document.createElement('button');
13+
copyButton.title = 'Copy code';
14+
copyButton.className =
15+
'absolute right-0 top-0 m-3 text-white opacity-50 transition-opacity hover:opacity-100';
16+
copyButton.innerHTML = copyButtonLabel;
17+
18+
codeBlock.setAttribute('tabindex', '0');
19+
codeBlock.appendChild(copyButton);
20+
codeBlock.parentNode.insertBefore(wrapper, codeBlock);
21+
wrapper.appendChild(codeBlock);
22+
23+
copyButton.addEventListener('click', async () => {
24+
await copyCode(codeBlock, copyButton);
25+
});
26+
}
27+
28+
async function copyCode(block, button) {
29+
let code = block.querySelector('code');
30+
let text = code.innerText;
31+
32+
await navigator.clipboard.writeText(text);
33+
button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-check"><path d="M18 6 7 17l-5-5"/><path d="m22 10-7.5 7.5L13 16"/></svg>`;
34+
35+
setTimeout(() => {
36+
button.innerHTML = copyButtonLabel;
37+
}, 700);
38+
}
39+
},
40+
{ once: true },
41+
);
42+
</script>

website/app/components/mobile-menu.tsx docs/src/components/mobileMenu.tsx

+13-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { ReactNode } from 'react';
2-
import { Link } from '@remix-run/react';
3-
import { SidebarRoutes } from '@/docs.routes';
2+
import { SidebarRoutes } from '@/docs.config';
43

54
import {
65
DropdownMenu,
@@ -10,17 +9,25 @@ import {
109
DropdownMenuSeparator,
1110
DropdownMenuTrigger,
1211
} from '@/ui/dropdown-menu';
12+
import { Button } from '@/ui/button';
13+
import { MenuIcon } from 'lucide-react';
1314

1415
interface MobileMenuProps {
15-
children: ReactNode;
1616
className?: string;
1717
}
1818

1919
const MobileMenu = (props: MobileMenuProps) => {
2020
return (
2121
<DropdownMenu>
2222
<DropdownMenuTrigger className={props.className} asChild>
23-
{props.children}
23+
<Button
24+
variant="ghost"
25+
size="icon"
26+
className="mr-2 md:mr-0 md:hidden"
27+
aria-label="Open mobile menu"
28+
>
29+
<MenuIcon size={18} />
30+
</Button>
2431
</DropdownMenuTrigger>
2532
<DropdownMenuContent sideOffset={4} align="start">
2633
{SidebarRoutes.map((data) => (
@@ -29,9 +36,9 @@ const MobileMenu = (props: MobileMenuProps) => {
2936
{data.category}
3037
</DropdownMenuLabel>
3138
{data.routes.map((route) => (
32-
<Link to={route.path} key={route.title}>
39+
<a href={route.path} key={route.title}>
3340
<DropdownMenuItem>{route.title}</DropdownMenuItem>
34-
</Link>
41+
</a>
3542
))}
3643
{data !== SidebarRoutes[SidebarRoutes.length - 1] && (
3744
<DropdownMenuSeparator />

0 commit comments

Comments
 (0)