Initial commit

This commit is contained in:
2025-11-17 15:28:20 +08:00
commit 0c64279e34
100 changed files with 23827 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
import { SiteHeader } from './site-header';
import { SiteFooter } from './site-footer';
export function LayoutShell({ children }: { children: React.ReactNode }) {
return (
<div className="min-h-screen flex flex-col">
<SiteHeader />
<main className="flex-1 container mx-auto px-4 py-6">{children}</main>
<SiteFooter />
</div>
);
}

View File

@@ -0,0 +1,31 @@
import type { MDXComponents } from 'mdx/types';
export const mdxComponents: MDXComponents = {
h1: (props) => (
<h1 className="mt-8 scroll-m-20 text-3xl font-bold" {...props} />
),
h2: (props) => (
<h2 className="mt-6 scroll-m-20 text-2xl font-semibold" {...props} />
),
p: (props) => (
<p className="leading-7 [&:not(:first-child)]:mt-4" {...props} />
),
a: (props) => (
<a
className="font-medium text-blue-600 underline-offset-4 hover:underline"
{...props}
/>
),
ul: (props) => <ul className="my-4 ml-6 list-disc" {...props} />,
ol: (props) => <ol className="my-4 ml-6 list-decimal" {...props} />,
code: (props) => (
<code
className="rounded bg-gray-100 px-1 py-0.5 text-xs dark:bg-gray-800"
{...props}
/>
),
pre: (props) => (
<pre className="my-4 overflow-x-auto rounded bg-gray-900 p-4 text-sm text-gray-100" {...props} />
)
};

View File

@@ -0,0 +1,8 @@
export function SiteFooter() {
return (
<footer className="border-t py-4 text-center text-sm text-gray-500">
© {new Date().getFullYear()} Your Name
</footer>
);
}

View File

@@ -0,0 +1,20 @@
import Link from 'next/link';
import { ThemeToggle } from './theme-toggle';
export function SiteHeader() {
return (
<header className="border-b bg-white/80 dark:bg-gray-950/80 backdrop-blur">
<div className="container mx-auto flex items-center justify-between px-4 py-3">
<Link href="/" className="font-semibold">
</Link>
<nav className="flex items-center gap-4 text-sm">
<Link href="/blog">Blog</Link>
<Link href="/pages/關於作者"></Link>
<ThemeToggle />
</nav>
</div>
</header>
);
}

View File

@@ -0,0 +1,20 @@
'use client';
import { useTheme } from 'next-themes';
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
const next = theme === 'dark' ? 'light' : 'dark';
return (
<button
type="button"
className="rounded border px-2 py-1 text-xs"
onClick={() => setTheme(next)}
>
{theme === 'dark' ? '☀️' : '🌙'}
</button>
);
}