Skip to content

Commit 5ddae1d

Browse files
committed
feat: enhance UI components with error handling and loading states; add EmptyState component for better user feedback
1 parent 11b7dae commit 5ddae1d

File tree

12 files changed

+397
-132
lines changed

12 files changed

+397
-132
lines changed

.github/agents/code.agent.md

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,26 @@ You implement features by following specs. Quality and spec compliance are non-n
3535

3636
```
3737
BEFORE: board → view <spec> → deps <spec> → update --status in-progress
38-
DURING: Code (follow spec) → Test → Document → Link deps
39-
AFTER: Check off items → validate → update --status complete
38+
DURING: Code → Check off completed items in spec → Test → Document progress in spec → Link deps
39+
AFTER: Verify all items checked → validate → update --status complete
4040
```
4141

42+
**CRITICAL:** Update the spec file AS YOU WORK:
43+
- Check off `- [ ]` items as you complete them
44+
- Add implementation notes in real-time
45+
- Document decisions, trade-offs, challenges DURING implementation
46+
- The spec is your working document, not just a reference
47+
4248
## Rules
4349

4450
1. **NEVER edit frontmatter** - Use tools
4551
2. **ALWAYS update status first** - `in-progress` before coding
46-
3. **ALWAYS link references** - Connect related specs
47-
4. **ALWAYS document** - Decisions, learnings, trade-offs
48-
5. **ALWAYS complete checklist** - Every acceptance criteria
49-
6. **NEVER skip validation** - Run before marking complete
50-
7. **NO COMPROMISES** - Full spec implementation required
52+
3. **CHECK OFF ITEMS AS YOU GO** - Update `- [x]` in spec immediately after completing each task
53+
4. **UPDATE SPEC CONTINUOUSLY** - Document decisions, progress, learnings IN THE SPEC FILE as you work
54+
5. **ALWAYS link references** - Connect related specs
55+
6. **ALWAYS complete checklist** - Every acceptance criteria must be checked before marking complete
56+
7. **NEVER skip validation** - Run before marking complete
57+
8. **NO COMPROMISES** - Full spec implementation required
5158

5259
## Status Tracking
5360

@@ -76,7 +83,8 @@ Completion verification: All checklist items must be checked. Use `--force` only
7683

7784
## Document Implementation
7885

79-
Add to spec:
86+
**Update the spec file continuously during implementation:**
87+
8088
```markdown
8189
## Implementation Notes
8290
- Approach taken
@@ -85,6 +93,14 @@ Add to spec:
8593
- Testing approach
8694
```
8795

96+
**As you complete each task:**
97+
1. Change `- [ ] Task` to `- [x] Task` in the spec
98+
2. Add notes about how it was done
99+
3. Document any deviations or learnings
100+
4. Keep the spec synchronized with actual progress
101+
102+
**The spec is your implementation log, not a static document.**
103+
88104
---
89105

90106
**Mission:** Deliver COMPLETE implementations that EXACTLY match spec requirements. NO compromises. NO workarounds. ALWAYS follow spec instructions.

.github/agents/review.agent.md

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ You validate completed specs, ensuring full implementation without compromises.
1111

1212
## Core Responsibilities
1313

14-
1. **Verify completion** - All acceptance criteria met
15-
2. **Validate quality** - Implementation matches spec exactly
16-
3. **Check documentation** - Spec updated with details
17-
4. **Test functionality** - Features work as described
18-
5. **Verify claimed progress** - Status/todos/checkboxes match actual code/commits
19-
6. **Report issues** - Actionable feedback
14+
1. **Verify spec was updated DURING work** - Not just at the end, but continuously
15+
2. **Verify completion** - All acceptance criteria met
16+
3. **Validate quality** - Implementation matches spec exactly
17+
4. **Check documentation** - Spec updated with details as work progressed
18+
5. **Test functionality** - Features work as described
19+
6. **Verify claimed progress** - Status/todos/checkboxes match actual code/commits
20+
7. **Report issues** - Actionable feedback
2021

2122
## 🚨 CRITICAL: ZERO TOLERANCE FOR COMPROMISES
2223

@@ -32,6 +33,28 @@ You validate completed specs, ensuring full implementation without compromises.
3233
- Flag any deviation from spec instructions
3334
- Reject work that compromises on spec requirements
3435

36+
## ⚠️ VERIFY SPEC WAS UPDATED DURING WORK
37+
38+
**The spec must be a living document, not updated only at completion:**
39+
40+
**Check git history of the spec file:**
41+
- `git log --oneline specs/NNN-name/README.md` - Multiple commits during implementation?
42+
- Spec updated incrementally as work progressed?
43+
- Checkboxes checked off throughout, not all at once at the end?
44+
- Implementation notes added during work, not just at completion?
45+
46+
**Red flags (REJECT if found):**
47+
- All checkboxes changed from `[ ]` to `[x]` in a single commit at the end
48+
- No spec file updates between "in-progress" and "complete" status changes
49+
- Implementation notes all added in one final commit
50+
- Git history shows spec untouched during days/weeks of implementation work
51+
52+
**Proper pattern:**
53+
- Regular commits updating spec file throughout implementation
54+
- Checkboxes checked off as each task completes
55+
- Implementation notes added when decisions are made
56+
- Spec evolves alongside code development
57+
3558
## ⚠️ VERIFY CLAIMED PROGRESS
3659

3760
**Specs must reflect reality:**
@@ -43,7 +66,8 @@ You validate completed specs, ensuring full implementation without compromises.
4366
- No stale specs (code changed but spec not updated)
4467

4568
**Cross-check against:**
46-
- `git log` - Recent commits for this spec's files
69+
- `git log specs/NNN-name/README.md` - Spec updated throughout work, not just at end?
70+
- `git log --since="<date spec marked in-progress>"` - Work commits align with spec updates?
4771
- `git diff` - Changes since spec marked in-progress
4872
- `grep_search` - Verify mentioned files/functions exist
4973
- `read_file` - Check implementation details match spec claims
@@ -53,13 +77,14 @@ You validate completed specs, ensuring full implementation without compromises.
5377

5478
```
5579
1. Assess: view → validate → validate --check-deps
56-
2. Verify Progress: git log → git diff → grep claimed files/features
57-
3. Criteria: ALL items checked? Test each manually
58-
4. Code: Matches spec EXACTLY? Tests pass? Quality OK?
59-
5. Docs: Implementation notes? Decisions documented?
60-
6. Test: Run feature, test edge cases, verify errors
61-
7. Dependencies: deps → verify complete
62-
8. Report: APPROVED / NEEDS WORK + specific issues
80+
2. Verify Spec History: git log specs/NNN/README.md → Check incremental updates
81+
3. Verify Progress: git log → git diff → grep claimed files/features
82+
4. Criteria: ALL items checked? Test each manually
83+
5. Code: Matches spec EXACTLY? Tests pass? Quality OK?
84+
6. Docs: Implementation notes? Decisions documented?
85+
7. Test: Run feature, test edge cases, verify errors
86+
8. Dependencies: deps → verify complete
87+
9. Report: APPROVED / NEEDS WORK + specific issues
6388
```
6489

6590
## Tools
@@ -68,6 +93,7 @@ You validate completed specs, ensuring full implementation without compromises.
6893

6994
## Review Checklist
7095

96+
**Spec Update History:** Git log shows incremental spec updates? Checkboxes checked throughout? Implementation notes added during work? Not all updated at the end?
7197
**Claimed Progress:** Status matches code? Checked items have implementation? Commits align? Files exist? No phantom progress?
7298
**Spec:** All criteria checked, status complete, implementation notes, decisions, learnings
7399
**Code:** Matches spec intent EXACTLY, tests pass, proper errors, follows conventions
@@ -78,14 +104,15 @@ You validate completed specs, ensuring full implementation without compromises.
78104

79105
## Common Issues
80106

81-
Phantom progress (checked without code), stale specs (code changed but spec not updated), status mismatch (complete but features missing), unchecked items, manual frontmatter edits, missing impl notes, broken deps, token bloat, missing tests, missing translations
107+
Bulk spec updates at end (all checkboxes in one commit), phantom progress (checked without code), stale specs (code changed but spec not updated), status mismatch (complete but features missing), unchecked items, manual frontmatter edits, missing impl notes, broken deps, token bloat, missing tests, missing translations
82108

83109
## Report Format
84110

85111
```markdown
86112
# Review: [Spec]
87113
**Status**: APPROVED ✅ | NEEDS WORK ❌
88114

115+
## Spec Update History: Incremental updates? Or bulk at end?
89116
## Progress Verification: Status matches code? Commits align? Files exist?
90117
## Criteria: [x/y] checked
91118
## Code: Matches spec? Tests pass?
@@ -98,19 +125,20 @@ Phantom progress (checked without code), stale specs (code changed but spec not
98125

99126
## Approval Criteria
100127

101-
**APPROVE:** Claimed progress verified against code/commits, all criteria met, code matches spec exactly, tests pass, docs complete
102-
**NEEDS WORK:** Phantom progress, status mismatch, criteria unchecked, doesn't match spec, compromises/workarounds found, tests fail
128+
**APPROVE:** Spec updated incrementally during work (not bulk at end), claimed progress verified against code/commits, all criteria met, code matches spec exactly, tests pass, docs complete
129+
**NEEDS WORK:** Bulk spec updates at completion, phantom progress, status mismatch, criteria unchecked, doesn't match spec, compromises/workarounds found, tests fail
103130

104131
## Standards
105132

106-
1. Verify claimed progress against actual code/commits first
107-
2. Thorough but fair
108-
3. Specific with file/line refs
109-
4. Actionable fixes
110-
5. Reject compromises
111-
6. Verify complete implementation
112-
7. Keep specs synchronized with reality
133+
1. Check spec git history FIRST - incremental updates or bulk at end?
134+
2. Verify claimed progress against actual code/commits
135+
3. Thorough but fair
136+
4. Specific with file/line refs
137+
5. Actionable fixes
138+
6. Reject compromises
139+
7. Verify complete implementation
140+
8. Keep specs synchronized with reality
113141

114142
---
115143

116-
**Mission:** Ensure specs represent COMPLETE, WORKING features that match actual implementation. REJECT compromises and workarounds. VERIFY full spec implementation. PREVENT phantom progress and stale specs.
144+
**Mission:** Ensure specs were UPDATED DURING WORK (not bulk at end), represent COMPLETE, WORKING features that match actual implementation. REJECT compromises and workarounds. VERIFY full spec implementation. PREVENT phantom progress, bulk updates, and stale specs.

packages/ui-vite/src/components/Layout.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import { Outlet } from 'react-router-dom';
1+
import { Outlet, useLocation } from 'react-router-dom';
22
import { useState } from 'react';
33
import { Navigation } from './Navigation';
44
import { MainSidebar } from './MainSidebar';
55
import { useGlobalShortcuts } from '../hooks/useKeyboardShortcuts';
6+
import { ErrorBoundary } from './shared/ErrorBoundary';
7+
import { PageTransition } from './shared/PageTransition';
8+
import { BackToTop } from './shared/BackToTop';
69

710
function KeyboardShortcutsHelp({ onClose }: { onClose: () => void }) {
811
const shortcuts = [
@@ -40,6 +43,7 @@ function KeyboardShortcutsHelp({ onClose }: { onClose: () => void }) {
4043

4144
export function Layout() {
4245
const [showShortcuts, setShowShortcuts] = useState(false);
46+
const location = useLocation();
4347

4448
// Register global keyboard shortcuts
4549
useGlobalShortcuts();
@@ -50,10 +54,15 @@ export function Layout() {
5054
<div className="flex w-full min-w-0">
5155
<MainSidebar />
5256
<main className="flex-1 min-w-0 w-full lg:w-[calc(100vw-var(--main-sidebar-width,240px))] px-4 py-6 lg:px-6">
53-
<Outlet />
57+
<ErrorBoundary key={location.pathname} onReset={() => window.location.reload()}>
58+
<PageTransition>
59+
<Outlet />
60+
</PageTransition>
61+
</ErrorBoundary>
5462
</main>
5563
</div>
5664
{showShortcuts && <KeyboardShortcutsHelp onClose={() => setShowShortcuts(false)} />}
65+
<BackToTop />
5766
</div>
5867
);
5968
}

packages/ui-vite/src/components/context/ContextClient.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,19 @@ export function ContextClient({ projectRoot }: ContextClientProps) {
135135
</CardHeader>
136136
<CardContent>
137137
{files.length === 0 ? (
138-
<div className="text-center py-8 text-muted-foreground text-sm">
139-
No context files found in .lean-spec/context
138+
<div className="text-center py-8 text-muted-foreground text-sm space-y-3">
139+
<div>No context files found in .lean-spec/context.</div>
140+
<Button size="sm" variant="secondary" onClick={loadList}>
141+
<RefreshCcw className="h-4 w-4 mr-2" />
142+
Rescan project
143+
</Button>
144+
</div>
145+
) : groupedFiles.length === 0 ? (
146+
<div className="text-center py-8 text-muted-foreground text-sm space-y-3">
147+
<div>No files match this search.</div>
148+
<Button size="sm" variant="outline" onClick={() => setSearch('')}>
149+
Clear search
150+
</Button>
140151
</div>
141152
) : (
142153
<div className="space-y-4 max-h-[70vh] overflow-y-auto pr-1">

packages/ui-vite/src/components/context/ContextFileDetail.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import rehypeSlug from 'rehype-slug';
66
import { ArrowLeft, Clock, Copy, ExternalLink, FileText, Hash, Layers, Type } from 'lucide-react';
77
import { Badge, Button, Card, CardContent } from '@leanspec/ui-components';
88
import { TableOfContents, TableOfContentsSidebar } from '../spec-detail/TableOfContents';
9-
import { BackToTop } from '../shared/BackToTop';
109
import { MermaidDiagram } from '../MermaidDiagram';
1110
import type { ContextFileContent } from '../../lib/api';
1211

@@ -163,8 +162,6 @@ export function ContextFileDetail({ file, projectRoot, onBack }: ContextFileDeta
163162
<TableOfContents content={headingContent} />
164163
</div>
165164
)}
166-
167-
<BackToTop />
168165
</div>
169166
);
170167
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { LucideIcon } from 'lucide-react';
2+
import { Card, CardContent, Button } from '@leanspec/ui-components';
3+
import { cn } from '../../lib/utils';
4+
import type { ReactNode } from 'react';
5+
6+
interface EmptyStateProps {
7+
icon: LucideIcon;
8+
title: string;
9+
description?: string;
10+
actions?: ReactNode;
11+
className?: string;
12+
tone?: 'muted' | 'error';
13+
}
14+
15+
export function EmptyState({ icon: Icon, title, description, actions, className, tone = 'muted' }: EmptyStateProps) {
16+
return (
17+
<Card className={cn('border-dashed', className)}>
18+
<CardContent className="py-10 text-center space-y-3">
19+
<div className="flex justify-center">
20+
<Button
21+
size="icon"
22+
variant={tone === 'error' ? 'destructive' : 'secondary'}
23+
className="h-10 w-10 rounded-full"
24+
aria-label={title}
25+
>
26+
<Icon className="h-5 w-5" />
27+
</Button>
28+
</div>
29+
<div className="text-lg font-semibold">{title}</div>
30+
{description && <p className="text-sm text-muted-foreground max-w-xl mx-auto">{description}</p>}
31+
{actions && <div className="flex justify-center gap-2 flex-wrap pt-1">{actions}</div>}
32+
</CardContent>
33+
</Card>
34+
);
35+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { Component, type ErrorInfo, type ReactNode } from 'react';
2+
import { AlertTriangle } from 'lucide-react';
3+
import { Button } from '@leanspec/ui-components';
4+
import { EmptyState } from './EmptyState';
5+
6+
interface Props {
7+
children: ReactNode;
8+
title?: string;
9+
message?: string;
10+
onReset?: () => void;
11+
}
12+
13+
interface State {
14+
hasError: boolean;
15+
error?: Error;
16+
}
17+
18+
export class ErrorBoundary extends Component<Props, State> {
19+
state: State = { hasError: false };
20+
21+
static getDerivedStateFromError(error: Error): State {
22+
return { hasError: true, error };
23+
}
24+
25+
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
26+
console.error('UI error captured', error, errorInfo);
27+
}
28+
29+
resetBoundary = () => {
30+
this.setState({ hasError: false, error: undefined });
31+
this.props.onReset?.();
32+
};
33+
34+
render() {
35+
if (this.state.hasError) {
36+
return (
37+
<EmptyState
38+
icon={AlertTriangle}
39+
title={this.props.title || 'Something went wrong'}
40+
description={this.props.message || this.state.error?.message || 'The page failed to render.'}
41+
tone="error"
42+
actions={(
43+
<>
44+
<Button size="sm" onClick={this.resetBoundary}>
45+
Retry
46+
</Button>
47+
<Button size="sm" variant="outline" onClick={() => window.location.reload()}>
48+
Reload page
49+
</Button>
50+
</>
51+
)}
52+
/>
53+
);
54+
}
55+
56+
return this.props.children;
57+
}
58+
}

0 commit comments

Comments
 (0)