Skip to content

Commit 23c238a

Browse files
committed
feat: initial docs + mdx config
1 parent d061d74 commit 23c238a

37 files changed

+538
-310
lines changed

website/.eslintrc.cjs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* This is intended to be a basic starting point for linting in your app.
3+
* It relies on recommended configs out of the box for simplicity, but you can
4+
* and should modify this configuration to best suit your team's needs.
5+
*/
6+
7+
/** @type {import('eslint').Linter.Config} */
8+
module.exports = {
9+
root: true,
10+
parserOptions: {
11+
ecmaVersion: "latest",
12+
sourceType: "module",
13+
ecmaFeatures: {
14+
jsx: true,
15+
},
16+
},
17+
env: {
18+
browser: true,
19+
commonjs: true,
20+
es6: true,
21+
},
22+
ignorePatterns: ["!**/.server", "!**/.client"],
23+
24+
// Base config
25+
extends: ["eslint:recommended"],
26+
27+
overrides: [
28+
// React
29+
{
30+
files: ["**/*.{js,jsx,ts,tsx}"],
31+
plugins: ["react", "jsx-a11y"],
32+
extends: [
33+
"plugin:react/recommended",
34+
"plugin:react/jsx-runtime",
35+
"plugin:react-hooks/recommended",
36+
"plugin:jsx-a11y/recommended",
37+
],
38+
settings: {
39+
react: {
40+
version: "detect",
41+
},
42+
formComponents: ["Form"],
43+
linkComponents: [
44+
{ name: "Link", linkAttribute: "to" },
45+
{ name: "NavLink", linkAttribute: "to" },
46+
],
47+
"import/resolver": {
48+
typescript: {},
49+
},
50+
},
51+
},
52+
53+
// Typescript
54+
{
55+
files: ["**/*.{ts,tsx}"],
56+
plugins: ["@typescript-eslint", "import"],
57+
parser: "@typescript-eslint/parser",
58+
settings: {
59+
"import/internal-regex": "^~/",
60+
"import/resolver": {
61+
node: {
62+
extensions: [".ts", ".tsx"],
63+
},
64+
typescript: {
65+
alwaysTryTypes: true,
66+
},
67+
},
68+
},
69+
extends: [
70+
"plugin:@typescript-eslint/recommended",
71+
"plugin:import/recommended",
72+
"plugin:import/typescript",
73+
],
74+
},
75+
76+
// Node
77+
{
78+
files: [".eslintrc.cjs"],
79+
env: {
80+
node: true,
81+
},
82+
},
83+
],
84+
};

website/.eslintrc.json

-3
This file was deleted.

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

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use client';
2-
31
import { useToast } from '@pheralb/toast';
42

53
const Examples = () => {

website/src/components/header.tsx website/app/components/header.tsx

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { Logo } from '@/icons';
2-
import { cn } from '@/utils';
3-
import Link from 'next/link';
4-
import { ModeToggle } from './theme-toggle';
1+
import { Link } from '@remix-run/react';
52
import { Github, X } from 'iconoir-react';
3+
4+
import { Logo } from '@/components/icons';
65
import { buttonVariants } from '@/ui/button';
6+
import { cn } from '@/utils/index';
7+
import { ModeToggle } from './theme-toggle';
78

89
const socialLinks = [
910
{
@@ -28,7 +29,7 @@ const Header = () => {
2829
>
2930
<div className="container flex max-w-7xl items-center justify-between">
3031
<Link
31-
href="/"
32+
to="/"
3233
className="flex items-center space-x-2 font-medium tracking-tight transition-opacity duration-75 hover:opacity-80"
3334
>
3435
<Logo width={22} />

website/app/components/icons.tsx

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { cn } from '@/utils';
2+
import type { ComponentProps, FC } from 'react';
3+
4+
export type Position =
5+
| 'top-left'
6+
| 'top-right'
7+
| 'bottom-left'
8+
| 'bottom-right';
9+
10+
const Logo: FC<ComponentProps<'svg'>> = (props) => (
11+
<svg
12+
xmlns="http://www.w3.org/2000/svg"
13+
fill="currentColor"
14+
viewBox="0 0 256 256"
15+
{...props}
16+
>
17+
<path d="M224 71.1a8 8 0 01-10.78-3.42 94.13 94.13 0 00-33.46-36.91 8 8 0 118.54-13.54 111.46 111.46 0 0139.12 43.09A8 8 0 01224 71.1zM35.71 72a8 8 0 007.1-4.32 94.13 94.13 0 0133.46-36.91 8 8 0 10-8.54-13.54 111.46 111.46 0 00-39.12 43.09A8 8 0 0035.71 72zm186.1 103.94A16 16 0 01208 200h-40.8a40 40 0 01-78.4 0H48a16 16 0 01-13.79-24.06C43.22 160.39 48 138.28 48 112a80 80 0 01160 0c0 26.27 4.78 48.38 13.81 63.94zM150.62 200h-45.24a24 24 0 0045.24 0zM208 184c-10.64-18.27-16-42.49-16-72a64 64 0 00-128 0c0 29.52-5.38 53.74-16 72z" />
18+
</svg>
19+
);
20+
21+
export const SparkleSvg = ({ position }: { position: Position }) => {
22+
return (
23+
<svg
24+
xmlns="http://www.w3.org/2000/svg"
25+
width="24"
26+
height="24"
27+
viewBox="0 0 24 24"
28+
fill="none"
29+
stroke="currentColor"
30+
strokeWidth="2"
31+
strokeLinecap="round"
32+
strokeLinejoin="round"
33+
className={cn(
34+
'absolute z-10 size-4 fill-black',
35+
position === 'top-right' && '-right-2 -top-2',
36+
position === 'bottom-left' && '-bottom-2 -left-2',
37+
position === 'bottom-right' && '-bottom-2 -right-2',
38+
position === 'top-left' && '-left-2 -top-2',
39+
)}
40+
>
41+
<path d="m12 3-1.9 5.8a2 2 0 0 1-1.287 1.288L3 12l5.8 1.9a2 2 0 0 1 1.288 1.287L12 21l1.9-5.8a2 2 0 0 1 1.287-1.288L21 12l-5.8-1.9a2 2 0 0 1-1.288-1.287Z"></path>
42+
</svg>
43+
);
44+
};
45+
46+
export { Logo };

website/src/components/sidebar.tsx website/app/components/sidebar.tsx

+11-21
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,16 @@
1-
'use client';
1+
import { Link, useLocation } from '@remix-run/react';
22

3-
import { DocsRoutes } from '@/routes';
4-
import { buttonVariants } from '@/ui/button';
5-
import { CardAnimatedBorder } from '@/ui/cards-spotlight';
6-
import {
7-
Collapsible,
8-
CollapsibleContent,
9-
CollapsibleTrigger,
10-
} from '@/ui/collapsible';
11-
import { cn } from '@/utils';
12-
import { ArrowUpRight, NavArrowDown } from 'iconoir-react';
13-
14-
import Link from 'next/link';
15-
import { usePathname } from 'next/navigation';
3+
import { DocsRoutes } from '@/docs.routes';
4+
import { cn } from '@/utils/index';
5+
import { ArrowUpRight } from 'iconoir-react';
166

177
const SidebarContent = () => {
18-
const pathname = usePathname();
8+
const location = useLocation();
199
return (
2010
<nav
2111
className={cn(
22-
'] fixed z-50 h-[calc(100vh-4rem)] overflow-y-auto overflow-x-hidden pb-10',
23-
'bg-white dark:bg-neutral-900',
12+
'fixed z-50 h-[calc(100vh-4rem)] overflow-y-auto overflow-x-hidden pb-10',
13+
'bg-neutral-50 dark:bg-neutral-900',
2414
'flex flex-col',
2515
)}
2616
>
@@ -34,13 +24,13 @@ const SidebarContent = () => {
3424
{route.routes.map((r) => (
3525
<Link
3626
key={r.path}
37-
href={r.path}
27+
to={r.path}
3828
className={cn(
3929
'px-4 py-2 text-sm',
4030
'border-l border-neutral-200 dark:border-neutral-800',
4131
'text-neutral-600 hover:text-black dark:text-neutral-400 dark:hover:text-white',
4232
'transition-colors',
43-
pathname === r.path
33+
location.pathname === r.path
4434
? 'border-black font-medium text-black dark:border-white dark:text-white'
4535
: 'bg-transparent',
4636
)}
@@ -52,8 +42,8 @@ const SidebarContent = () => {
5242
</div>
5343
))}
5444
</div>
55-
<div className="w-full border-b border-neutral-200 py-2 text-sm dark:border-neutral-800">
56-
<p className="font-medium">Found an issue?</p>
45+
<div className="w-full border-b-2 border-dashed border-neutral-200 py-2 text-sm dark:border-neutral-800">
46+
<p className="font-medium">Found a bug?</p>
5747
<a
5848
href="https://github.com/pheralb/toast/issues/new"
5949
target="_blank"
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { HalfMoon, SunLight } from 'iconoir-react';
2+
import { Theme, useTheme } from 'remix-themes';
3+
4+
import {
5+
DropdownMenu,
6+
DropdownMenuContent,
7+
DropdownMenuItem,
8+
DropdownMenuTrigger,
9+
} from '@/ui/dropdown-menu';
10+
import { Button } from '@/ui/button';
11+
12+
export function ModeToggle() {
13+
const [, setTheme] = useTheme();
14+
15+
return (
16+
<DropdownMenu>
17+
<DropdownMenuTrigger asChild>
18+
<Button variant="ghost" size="icon">
19+
<SunLight className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
20+
<HalfMoon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
21+
<span className="sr-only">Toggle theme</span>
22+
</Button>
23+
</DropdownMenuTrigger>
24+
<DropdownMenuContent align="end">
25+
<DropdownMenuItem onClick={() => setTheme(Theme.LIGHT)}>
26+
Light
27+
</DropdownMenuItem>
28+
<DropdownMenuItem onClick={() => setTheme(Theme.DARK)}>
29+
Dark
30+
</DropdownMenuItem>
31+
</DropdownMenuContent>
32+
</DropdownMenu>
33+
);
34+
}

website/src/routes.ts website/app/docs.routes.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const DocsRoutes: iDocsRoutes[] = [
1616
},
1717
{
1818
title: 'Usage with Next.js',
19-
path: '/nextjs',
19+
path: '/docs/nextjs',
2020
},
2121
],
2222
},
@@ -25,11 +25,11 @@ export const DocsRoutes: iDocsRoutes[] = [
2525
routes: [
2626
{
2727
title: 'Positions',
28-
path: '/positions',
28+
path: '/docs/positions',
2929
},
3030
{
3131
title: 'Variants',
32-
path: '/variants',
32+
path: '/docs/variants',
3333
},
3434
],
3535
},
@@ -38,15 +38,15 @@ export const DocsRoutes: iDocsRoutes[] = [
3838
routes: [
3939
{
4040
title: 'Rich Colors',
41-
path: '/colors',
41+
path: '/docs/colors',
4242
},
4343
{
4444
title: 'Dark Mode',
45-
path: '/dark-mode',
45+
path: '/docs/dark-mode',
4646
},
4747
{
4848
title: 'Tailwind CSS',
49-
path: '/tailwind-css',
49+
path: '/docs/tailwind-css',
5050
},
5151
],
5252
},

website/app/root.tsx

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import type { LinksFunction, LoaderFunctionArgs } from '@vercel/remix';
2+
3+
import {
4+
Links,
5+
Meta,
6+
Outlet,
7+
Scripts,
8+
ScrollRestoration,
9+
useLoaderData,
10+
} from '@remix-run/react';
11+
12+
// Styles:
13+
import stylesheet from '@/styles/globals.css?url';
14+
import { cn } from './utils';
15+
16+
// Layout:
17+
import Header from './components/header';
18+
import SidebarContent from './components/sidebar';
19+
20+
// Providers:
21+
import { ToastProvider } from '@pheralb/toast';
22+
import {
23+
PreventFlashOnWrongTheme,
24+
ThemeProvider,
25+
useTheme,
26+
} from 'remix-themes';
27+
import { themeSessionResolver } from './sessions.server';
28+
29+
export const links: LinksFunction = () => [
30+
{ rel: 'stylesheet', href: stylesheet },
31+
];
32+
33+
export async function loader({ request }: LoaderFunctionArgs) {
34+
const { getTheme } = await themeSessionResolver(request);
35+
return {
36+
theme: getTheme(),
37+
};
38+
}
39+
40+
export default function AppWithProviders() {
41+
const data = useLoaderData<typeof loader>();
42+
return (
43+
<ThemeProvider specifiedTheme={data.theme} themeAction="/action/set-theme">
44+
<App />
45+
</ThemeProvider>
46+
);
47+
}
48+
49+
function App() {
50+
const data = useLoaderData<typeof loader>();
51+
const [theme] = useTheme();
52+
return (
53+
<html lang="en" className={cn(theme)}>
54+
<head>
55+
<meta charSet="utf-8" />
56+
<meta name="viewport" content="width=device-width, initial-scale=1" />
57+
<Meta />
58+
<PreventFlashOnWrongTheme ssrTheme={Boolean(data.theme)} />
59+
<Links />
60+
</head>
61+
<body
62+
className={cn(
63+
'font-sans antialiased',
64+
'bg-neutral-50 dark:bg-neutral-900',
65+
'text-neutral-900 dark:text-neutral-50',
66+
)}
67+
>
68+
<Header />
69+
<ToastProvider
70+
position="bottom-right"
71+
theme={data.theme == 'dark' ? 'dark' : 'light'}
72+
>
73+
<div className="container mx-auto max-w-7xl">
74+
<SidebarContent />
75+
<main className="ml-60">
76+
<Outlet />
77+
</main>
78+
</div>
79+
</ToastProvider>
80+
<ScrollRestoration />
81+
<Scripts />
82+
</body>
83+
</html>
84+
);
85+
}

0 commit comments

Comments
 (0)