Skip to content

Commit 40b6a21

Browse files
authored
Merge pull request #12 from masseater/feat/sdd-webapp-webui-refactor
sdd-webapp: adopt shadcn/ui + tailwind, show archived, fix navigation
2 parents be2d42b + 9f495c3 commit 40b6a21

35 files changed

Lines changed: 1450 additions & 1275 deletions

bun.lock

Lines changed: 189 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/sdd-webapp/biome.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,10 @@
1717
"formatter": {
1818
"quoteStyle": "double"
1919
}
20+
},
21+
"css": {
22+
"parser": {
23+
"tailwindDirectives": true
24+
}
2025
}
2126
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "new-york",
4+
"rsc": false,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "src/client/tailwind.config.js",
8+
"css": "src/client/styles.css",
9+
"baseColor": "neutral",
10+
"cssVariables": true,
11+
"prefix": ""
12+
},
13+
"iconLibrary": "lucide",
14+
"aliases": {
15+
"components": "@/components",
16+
"utils": "@/lib/utils",
17+
"ui": "@/components/ui",
18+
"lib": "@/lib",
19+
"hooks": "@/hooks"
20+
},
21+
"registries": {}
22+
}

packages/sdd-webapp/package.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,32 @@
2727
},
2828
"dependencies": {
2929
"@modelcontextprotocol/sdk": "^1.25.1",
30+
"@radix-ui/react-popover": "^1.1.15",
31+
"@radix-ui/react-slot": "^1.2.4",
32+
"class-variance-authority": "^0.7.1",
33+
"clsx": "^2.1.1",
3034
"highlight.js": "^11.11.0",
3135
"hono": "^4.10.2",
36+
"lucide-react": "^0.562.0",
3237
"marked": "^15.0.0",
33-
"marked-highlight": "^2.2.0"
38+
"marked-highlight": "^2.2.0",
39+
"tailwind-merge": "^3.4.0",
40+
"tw-animate-css": "^1.4.0"
3441
},
3542
"devDependencies": {
3643
"@biomejs/biome": "^2.0.0",
44+
"@tailwindcss/typography": "^0.5.19",
45+
"@tailwindcss/vite": "^4.1.18",
3746
"@types/bun": "^1.3.4",
3847
"@types/react": "^19.0.0",
3948
"@types/react-dom": "^19.0.0",
4049
"@typescript/native-preview": "^7.0.0-dev.20251217.1",
4150
"@vitejs/plugin-react": "^4.4.0",
51+
"autoprefixer": "^10.4.23",
52+
"postcss": "^8.5.6",
4253
"react": "^19.0.0",
4354
"react-dom": "^19.0.0",
55+
"tailwindcss": "^4.1.18",
4456
"typescript": "^5.9.3",
4557
"vite": "^6.0.0"
4658
},

packages/sdd-webapp/src/client/App.tsx

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { useState } from "react";
2+
import { Button } from "@/components/ui/button";
3+
import type { TaskStatus } from "../types";
24
import { Dashboard } from "./components/Dashboard";
35
import { ProjectSelector } from "./components/ProjectSelector";
46
import { TaskDetailView } from "./components/TaskDetailView";
57
import { useProjects } from "./hooks/useProjects";
6-
import { type TaskStatus, useSpecs } from "./hooks/useSpecs";
8+
import { useSpecs } from "./hooks/useSpecs";
79

810
export function App() {
911
const {
@@ -13,9 +15,17 @@ export function App() {
1315
addProject,
1416
removeProject,
1517
loading: projectsLoading,
18+
error: projectsError,
1619
} = useProjects();
17-
const { fileTree, selectedFile, specContent, status, fetchSpecContent } =
18-
useSpecs(selectedProject?.id ?? null);
20+
const [includeArchived, setIncludeArchived] = useState(false);
21+
const {
22+
fileTree,
23+
selectedFile,
24+
specContent,
25+
status,
26+
fetchSpecContent,
27+
error: specsError,
28+
} = useSpecs(selectedProject?.id ?? null, { includeArchived });
1929
const [selectedTask, setSelectedTask] = useState<TaskStatus | null>(null);
2030

2131
const handleTaskClick = (task: TaskStatus) => {
@@ -28,42 +38,63 @@ export function App() {
2838

2939
if (projectsLoading) {
3040
return (
31-
<div className="app">
32-
<div className="loading">Loading...</div>
41+
<div className="min-h-screen bg-muted/30">
42+
<div className="mx-auto max-w-5xl p-6 text-muted-foreground">
43+
Loading...
44+
</div>
3345
</div>
3446
);
3547
}
3648

3749
return (
38-
<div className="app">
39-
<header className="app-header">
40-
<div className="app-header-left">
41-
<h1 className="app-title">SDD Webapp</h1>
42-
{selectedTask && (
43-
<>
44-
<span className="breadcrumb-separator">/</span>
45-
<span className="breadcrumb-current">{selectedTask.name}</span>
46-
</>
47-
)}
50+
<div className="min-h-screen bg-muted/30">
51+
{(projectsError || specsError) && (
52+
<div
53+
className="border-b border-destructive/20 bg-destructive/10 px-6 py-3 text-sm text-destructive"
54+
role="alert"
55+
>
56+
{projectsError || specsError}
4857
</div>
49-
<div className="app-header-right">
50-
<ProjectSelector
51-
projects={projects}
52-
selectedProject={selectedProject}
53-
onSelect={(project) => {
54-
setSelectedProject(project);
55-
setSelectedTask(null);
56-
}}
57-
onAdd={addProject}
58-
onRemove={removeProject}
59-
/>
58+
)}
59+
<header className="sticky top-0 z-10 border-b bg-background/80 backdrop-blur">
60+
<div className="mx-auto flex h-16 max-w-6xl items-center justify-between gap-4 px-6">
61+
<div className="flex items-center gap-3">
62+
<h1 className="text-lg font-semibold">SDD Webapp</h1>
63+
{selectedTask && (
64+
<>
65+
<span className="text-muted-foreground">/</span>
66+
<Button
67+
type="button"
68+
variant="link"
69+
className="h-auto p-0 text-sm text-muted-foreground"
70+
onClick={handleBackToDashboard}
71+
>
72+
{selectedTask.name}
73+
</Button>
74+
</>
75+
)}
76+
</div>
77+
<div className="flex items-center gap-3">
78+
<ProjectSelector
79+
projects={projects}
80+
selectedProject={selectedProject}
81+
onSelect={(project) => {
82+
setSelectedProject(project);
83+
setSelectedTask(null);
84+
}}
85+
onAdd={addProject}
86+
onRemove={removeProject}
87+
/>
88+
</div>
6089
</div>
6190
</header>
62-
<main className="main-content">
91+
<main className="mx-auto w-full max-w-6xl flex-1 px-6 py-6">
6392
{!selectedProject ? (
64-
<div className="empty-state">
65-
<h2>No Project Selected</h2>
66-
<p>Add a project to get started.</p>
93+
<div className="rounded-lg border bg-background p-8 text-center">
94+
<h2 className="text-lg font-semibold">No Project Selected</h2>
95+
<p className="mt-2 text-sm text-muted-foreground">
96+
Add a project to get started.
97+
</p>
6798
</div>
6899
) : selectedTask ? (
69100
<TaskDetailView
@@ -78,6 +109,8 @@ export function App() {
78109
<Dashboard
79110
status={status}
80111
projectName={selectedProject.name}
112+
includeArchived={includeArchived}
113+
onToggleArchived={setIncludeArchived}
81114
onTaskClick={handleTaskClick}
82115
/>
83116
)}

0 commit comments

Comments
 (0)