feat: Implement page routing using wouter and add simple mock-up pages

This commit is contained in:
2025-09-24 00:45:31 +09:00
parent 9fc00089b1
commit 97ee67cf64
10 changed files with 153 additions and 20 deletions

View File

@@ -12,14 +12,16 @@
"dependencies": { "dependencies": {
"@base-ui-components/react": "^1.0.0-beta.3", "@base-ui-components/react": "^1.0.0-beta.3",
"@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-slot": "^1.2.3",
"@tabler/icons-react": "^3.35.0",
"@tailwindcss/vite": "^4.1.13", "@tailwindcss/vite": "^4.1.13",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"lucide-react": "^0.543.0", "lucide-react": "^0.544.0",
"react": "^19.1.1", "react": "^19.1.1",
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"tailwind-merge": "^3.3.1", "tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.13", "tailwindcss": "^4.1.13",
"wouter": "^3.7.1",
"zustand": "^5.0.8" "zustand": "^5.0.8"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -1,12 +1,22 @@
import { Route, Switch } from 'wouter';
import Topbar from './Topbar'; import Topbar from './Topbar';
import Home from './pages/Home';
import Dashboard from './pages/Dashboard';
import Todos from './pages/Todos';
import NotFound from './pages/default/NotFound';
function PageContainer() { function PageContainer() {
return ( return (
<div className="flex flex-col flex-1"> <div className="flex flex-col flex-1">
<Topbar /> <Topbar />
<div className="p-4"> <Switch>
<h1 className="text-2xl font-bold">Main Content</h1> <Route path="/" component={Home} />
</div> <Route path="/dashboard" component={Dashboard} />
<Route path="/todos" component={Todos} />
<Route component={NotFound} />
</Switch>
</div> </div>
); );
} }

View File

@@ -1,7 +1,40 @@
import { Button } from '@/components/ui/button';
import { useLocation, Link } from 'wouter';
import {
IconHome,
IconCalendarWeekFilled,
IconLayoutCollage,
IconCheckupList,
} from '@tabler/icons-react';
// TODO: Add Sidebar Items(Pages, etc...) to Zustand Store
export const items = [
{ name: 'Home', href: '/', icon: IconHome },
{ name: 'Dashboard', href: '/dashboard', icon: IconLayoutCollage },
{ name: 'Todos', href: '/todos', icon: IconCheckupList },
{ name: 'Calendar', href: '/calendar', icon: IconCalendarWeekFilled },
];
function Sidebar() { function Sidebar() {
const [location] = useLocation();
return ( return (
<nav className="flex justify-center min-w-[240px] max-w-[480px] bg-sidebar border"> <nav className="flex flex-col min-w-[240px] max-w-[480px] bg-sidebar border">
<p>Sidebar</p> <div className="flex flex-col m-2 gap-2">
<p className="text-muted-foreground text-sm font-bold pl-2">Menus</p>
{items.map((item) => (
<Button
asChild
size="sm"
key={item.name}
variant={location === item.href ? 'secondary' : 'ghost'}
className="justify-start"
>
<Link href={item.href}>
<item.icon /> {item.name}
</Link>
</Button>
))}
</div>
</nav> </nav>
); );
} }

View File

@@ -1,9 +1,15 @@
import { Button } from '@/components/ui/button';
import { items } from './Sidebar';
import { useLocation } from 'wouter';
function Topbar() { function Topbar() {
const [location] = useLocation();
return ( return (
<div className="flex bg-sidebar p-2 gap-2 border-t border-r border-b border-l-0"> <div className="flex bg-sidebar p-2 gap-2 border-t border-r border-b border-l-0">
<span>item 1</span> <Button variant="ghost" size="sm" className="font-semibold">
<span>item 2</span> {items.find((item) => item.href === location)?.name}
<span>item 3</span> {/* TODO: Add Sidebar Items(Pages, etc...) to Zustand Store */}
</Button>
</div> </div>
); );
} }

View File

@@ -0,0 +1,9 @@
function Dashboard() {
return (
<div className="p-4">
<h1 className="text-2xl font-bold">Dashboard</h1>
</div>
);
}
export default Dashboard;

View File

@@ -0,0 +1,9 @@
function Home() {
return (
<div className="p-4">
<h1 className="text-2xl font-bold">Home</h1>
</div>
);
}
export default Home;

View File

@@ -0,0 +1,9 @@
function Todos() {
return (
<div className="p-4">
<h1 className="text-2xl font-bold">Todos</h1>
</div>
);
}
export default Todos;

View File

@@ -0,0 +1,9 @@
function NotFound() {
return (
<div className="p-4">
<h1 className="text-2xl font-bold">404 - Not Found!</h1>
</div>
);
}
export default NotFound;

View File

@@ -9,16 +9,15 @@ const buttonVariants = cva(
{ {
variants: { variants: {
variant: { variant: {
default: default: 'bg-primary text-primary-foreground hover:bg-primary/90',
'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
destructive: destructive:
'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
outline: outline:
'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50', 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
secondary: secondary:
'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80', 'bg-black/10 text-secondary-foreground hover:bg-black/5 dark:bg-secondary dark:hover:bg-secondary/80',
ghost: ghost:
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', 'hover:bg-black/5 hover:text-accent-foreground dark:hover:bg-accent/50',
link: 'text-primary underline-offset-4 hover:underline', link: 'text-primary underline-offset-4 hover:underline',
}, },
size: { size: {

View File

@@ -866,6 +866,24 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@tabler/icons-react@npm:^3.35.0":
version: 3.35.0
resolution: "@tabler/icons-react@npm:3.35.0"
dependencies:
"@tabler/icons": "npm:3.35.0"
peerDependencies:
react: ">= 16"
checksum: 10c0/8d280fcdae00916b001142ba0800ea05d8fa2acdcbd82f88a299b4141fb941237be2e826b86b1af710e038b4f8bb6f76f452c3309c29fd62398b4d5789c2b3e0
languageName: node
linkType: hard
"@tabler/icons@npm:3.35.0":
version: 3.35.0
resolution: "@tabler/icons@npm:3.35.0"
checksum: 10c0/93098828128ffed2cf412b39bd78992f93f25b22349a4e04523d2a018b7fe376ddeff105babcc3efedd707aa00b705425c7d9f598d6987552a563c62125795a2
languageName: node
linkType: hard
"@tailwindcss/node@npm:4.1.13": "@tailwindcss/node@npm:4.1.13":
version: 4.1.13 version: 4.1.13
resolution: "@tailwindcss/node@npm:4.1.13" resolution: "@tailwindcss/node@npm:4.1.13"
@@ -1883,6 +1901,7 @@ __metadata:
"@base-ui-components/react": "npm:^1.0.0-beta.3" "@base-ui-components/react": "npm:^1.0.0-beta.3"
"@eslint/js": "npm:^9.33.0" "@eslint/js": "npm:^9.33.0"
"@radix-ui/react-slot": "npm:^1.2.3" "@radix-ui/react-slot": "npm:^1.2.3"
"@tabler/icons-react": "npm:^3.35.0"
"@tailwindcss/vite": "npm:^4.1.13" "@tailwindcss/vite": "npm:^4.1.13"
"@types/node": "npm:^24.3.1" "@types/node": "npm:^24.3.1"
"@types/react": "npm:^19.1.10" "@types/react": "npm:^19.1.10"
@@ -1894,7 +1913,7 @@ __metadata:
eslint-plugin-react-hooks: "npm:^5.2.0" eslint-plugin-react-hooks: "npm:^5.2.0"
eslint-plugin-react-refresh: "npm:^0.4.20" eslint-plugin-react-refresh: "npm:^0.4.20"
globals: "npm:^16.3.0" globals: "npm:^16.3.0"
lucide-react: "npm:^0.543.0" lucide-react: "npm:^0.544.0"
react: "npm:^19.1.1" react: "npm:^19.1.1"
react-dom: "npm:^19.1.1" react-dom: "npm:^19.1.1"
tailwind-merge: "npm:^3.3.1" tailwind-merge: "npm:^3.3.1"
@@ -1903,6 +1922,7 @@ __metadata:
typescript: "npm:~5.8.3" typescript: "npm:~5.8.3"
typescript-eslint: "npm:^8.39.1" typescript-eslint: "npm:^8.39.1"
vite: "npm:^7.1.2" vite: "npm:^7.1.2"
wouter: "npm:^3.7.1"
zustand: "npm:^5.0.8" zustand: "npm:^5.0.8"
languageName: unknown languageName: unknown
linkType: soft linkType: soft
@@ -2328,12 +2348,12 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"lucide-react@npm:^0.543.0": "lucide-react@npm:^0.544.0":
version: 0.543.0 version: 0.544.0
resolution: "lucide-react@npm:0.543.0" resolution: "lucide-react@npm:0.544.0"
peerDependencies: peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
checksum: 10c0/76bb54f9c602ff5d44ec66f2786c035d92aaabca1e1abb380b0c8101dfb3290e52c82fa4d630e286ef07c05b63696e187f0ca3ae186535d9c5b4de7aa8825bd3 checksum: 10c0/2503f8cf65e62915997073b6053423bf8091b9470cb397560b417ef2f1628ea162c49e821b787cf153afb86828482d941f051c3f2aa642a1fa58c3de227e0113
languageName: node languageName: node
linkType: hard linkType: hard
@@ -2476,6 +2496,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"mitt@npm:^3.0.1":
version: 3.0.1
resolution: "mitt@npm:3.0.1"
checksum: 10c0/3ab4fdecf3be8c5255536faa07064d05caa3dd332bd318ff02e04621f7b3069ca1de9106cfe8e7ced675abfc2bec2ce4c4ef321c4a1bb1fb29df8ae090741913
languageName: node
linkType: hard
"mkdirp@npm:^3.0.1": "mkdirp@npm:^3.0.1":
version: 3.0.1 version: 3.0.1
resolution: "mkdirp@npm:3.0.1" resolution: "mkdirp@npm:3.0.1"
@@ -2713,6 +2740,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"regexparam@npm:^3.0.0":
version: 3.0.0
resolution: "regexparam@npm:3.0.0"
checksum: 10c0/a6430d7b97d5a7d5518f37a850b6b73aab479029d02f46af4fa0e8e4a1d7aad05b7a0d2d10c86ded21a14d5f0fa4c68525f873a5fca2efeefcccd93c36627459
languageName: node
linkType: hard
"reselect@npm:^5.1.1": "reselect@npm:^5.1.1":
version: 5.1.1 version: 5.1.1
resolution: "reselect@npm:5.1.1" resolution: "reselect@npm:5.1.1"
@@ -3136,7 +3170,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"use-sync-external-store@npm:^1.5.0": "use-sync-external-store@npm:^1.0.0, use-sync-external-store@npm:^1.5.0":
version: 1.5.0 version: 1.5.0
resolution: "use-sync-external-store@npm:1.5.0" resolution: "use-sync-external-store@npm:1.5.0"
peerDependencies: peerDependencies:
@@ -3229,6 +3263,19 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"wouter@npm:^3.7.1":
version: 3.7.1
resolution: "wouter@npm:3.7.1"
dependencies:
mitt: "npm:^3.0.1"
regexparam: "npm:^3.0.0"
use-sync-external-store: "npm:^1.0.0"
peerDependencies:
react: ">=16.8.0"
checksum: 10c0/1974f32f425c1cf6412e6946936e37db3a283e6e6965acd336ce04d67bb36fbf2c40fc90a1bc4537930b326e370b5e053437e0f80554cb94d34ec8c354b86693
languageName: node
linkType: hard
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version: 7.0.0 version: 7.0.0
resolution: "wrap-ansi@npm:7.0.0" resolution: "wrap-ansi@npm:7.0.0"