diff --git a/app/components/Sidebar.module.css b/app/components/Sidebar.module.css
new file mode 100644
index 0000000..b395428
--- /dev/null
+++ b/app/components/Sidebar.module.css
@@ -0,0 +1,142 @@
+/* Hamburger button */
+.hamburger {
+ position: fixed;
+ top: 24px;
+ right: 24px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 5px;
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ background: rgba(0, 0, 0, 0.9);
+ backdrop-filter: blur(10px);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ border-radius: 50%;
+ cursor: pointer;
+ z-index: 1100;
+ transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+}
+
+.hamburger:hover {
+ background: rgba(0, 0, 0, 1);
+ border-color: rgba(255, 255, 255, 0.4);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
+}
+
+.hamburgerLine {
+ width: 16px;
+ height: 1.5px;
+ background: #ffffff;
+ border-radius: 1px;
+ transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
+ transform-origin: center;
+}
+
+.hamburgerLineTop {
+ transform: translateY(6.5px) rotate(45deg);
+}
+
+.hamburgerLineMid {
+ opacity: 0;
+}
+
+.hamburgerLineBot {
+ transform: translateY(-6.5px) rotate(-45deg);
+}
+
+/* Overlay backdrop */
+.overlay {
+ position: fixed;
+ inset: 0;
+ background: rgba(0, 0, 0, 0.5);
+ backdrop-filter: blur(4px);
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1);
+ z-index: 1050;
+}
+
+.overlayVisible {
+ opacity: 1;
+ pointer-events: auto;
+}
+
+/* Sidebar panel */
+.sidebar {
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: 320px;
+ max-width: 85vw;
+ height: 100dvh;
+ background: rgba(10, 10, 10, 0.95);
+ backdrop-filter: blur(20px);
+ border-left: 1px solid rgba(255, 255, 255, 0.1);
+ transform: translateX(100%);
+ transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
+ z-index: 1075;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ padding: 80px 40px;
+}
+
+.sidebarOpen {
+ transform: translateX(0);
+}
+
+/* Nav list */
+.navList {
+ list-style: none;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.navLink {
+ display: block;
+ padding: 14px 20px;
+ color: rgba(255, 255, 255, 0.6);
+ text-decoration: none;
+ font-size: 18px;
+ font-weight: 600;
+ letter-spacing: -0.01em;
+ border-radius: 12px;
+ transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
+}
+
+.navLink:hover {
+ color: #ffffff;
+ background: rgba(255, 255, 255, 0.08);
+}
+
+.navLinkActive {
+ color: #ffffff;
+ background: rgba(255, 255, 255, 0.1);
+}
+
+@media (max-width: 768px) {
+ .hamburger {
+ top: 16px;
+ right: 16px;
+ width: 36px;
+ height: 36px;
+ }
+
+ .hamburgerLine {
+ width: 14px;
+ }
+
+ .sidebar {
+ padding: 60px 24px;
+ }
+
+ .navLink {
+ font-size: 16px;
+ padding: 12px 16px;
+ }
+}
diff --git a/app/components/Sidebar.tsx b/app/components/Sidebar.tsx
new file mode 100644
index 0000000..951ac78
--- /dev/null
+++ b/app/components/Sidebar.tsx
@@ -0,0 +1,68 @@
+'use client'
+
+import { useState, useEffect } from 'react'
+import { usePathname } from 'next/navigation'
+import Link from 'next/link'
+import styles from './Sidebar.module.css'
+
+const navLinks = [
+ { href: '/', label: 'Home' },
+ { href: '/design-experiments', label: 'Design Experiments' },
+ { href: '/docs', label: 'Docs' },
+ { href: '/blog', label: 'Blog' },
+]
+
+export default function Sidebar() {
+ const [open, setOpen] = useState(false)
+ const pathname = usePathname()
+
+ useEffect(() => {
+ setOpen(false)
+ }, [pathname])
+
+ useEffect(() => {
+ if (open) {
+ document.body.style.overflow = 'hidden'
+ } else {
+ document.body.style.overflow = ''
+ }
+ return () => {
+ document.body.style.overflow = ''
+ }
+ }, [open])
+
+ return (
+ <>
+
+
+
setOpen(false)}
+ />
+
+
+ >
+ )
+}
diff --git a/app/layout.tsx b/app/layout.tsx
index 44e7b85..b3e0ecf 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,6 +1,7 @@
import { Inter } from 'next/font/google'
import './globals.css'
import BackButton from './components/BackButton'
+import Sidebar from './components/Sidebar'
const inter = Inter({
subsets: ['latin'],
@@ -22,6 +23,7 @@ export default function RootLayout({
+
{children}
diff --git a/package-lock.json b/package-lock.json
index 826b87f..22b6950 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,7 @@
"gray-matter": "^4.0.3",
"lucide-react": "^0.563.0",
"next": "^16.1.6",
- "next-mdx-remote": "^5.0.0",
+ "next-mdx-remote": "^6.0.0",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-syntax-highlighter": "^16.1.0",
@@ -3924,15 +3924,16 @@
}
},
"node_modules/next-mdx-remote": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-5.0.0.tgz",
- "integrity": "sha512-RNNbqRpK9/dcIFZs/esQhuLA8jANqlH694yqoDBK8hkVdJUndzzGmnPHa2nyi90N4Z9VmzuSWNRpr5ItT3M7xQ==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-6.0.0.tgz",
+ "integrity": "sha512-cJEpEZlgD6xGjB4jL8BnI8FaYdN9BzZM4NwadPe1YQr7pqoWjg9EBCMv3nXBkuHqMRfv2y33SzUsuyNh9LFAQQ==",
"license": "MPL-2.0",
"dependencies": {
"@babel/code-frame": "^7.23.5",
"@mdx-js/mdx": "^3.0.1",
"@mdx-js/react": "^3.0.1",
- "unist-util-remove": "^3.1.0",
+ "unist-util-remove": "^4.0.0",
+ "unist-util-visit": "^5.1.0",
"vfile": "^6.0.1",
"vfile-matter": "^5.0.0"
},
@@ -5258,47 +5259,14 @@
}
},
"node_modules/unist-util-remove": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-3.1.1.tgz",
- "integrity": "sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==",
- "license": "MIT",
- "dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-is": "^5.0.0",
- "unist-util-visit-parents": "^5.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/unist-util-remove/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "license": "MIT"
- },
- "node_modules/unist-util-remove/node_modules/unist-util-is": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz",
- "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==",
- "license": "MIT",
- "dependencies": {
- "@types/unist": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/unist-util-remove/node_modules/unist-util-visit-parents": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz",
- "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-4.0.0.tgz",
+ "integrity": "sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==",
"license": "MIT",
"dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-is": "^5.0.0"
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
},
"funding": {
"type": "opencollective",