feat: add PageMeta, animation classes, and layout fixes to remaining pages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-03-09 15:59:51 -04:00
parent d916531af0
commit 742c166738
15 changed files with 28 additions and 22 deletions

View File

@@ -42,6 +42,11 @@
When adding new pages/components: use "ResolutionFlow" branding, ice-cyan gradient accent theme, `.glass-card` / `.glass-card-static` containers, `text-foreground`/`text-muted-foreground` hierarchy. Primary actions use `bg-gradient-brand`. Pages render inside the app shell (CSS Grid: topbar + sidebar + main). Use "Flows" not "Trees" in all user-facing text; use "Projects" not "Procedures" for procedural flows. Reference [UI-DESIGN-SYSTEM.md](UI-DESIGN-SYSTEM.md) for layout patterns, navigation, and component specs. When adding new pages/components: use "ResolutionFlow" branding, ice-cyan gradient accent theme, `.glass-card` / `.glass-card-static` containers, `text-foreground`/`text-muted-foreground` hierarchy. Primary actions use `bg-gradient-brand`. Pages render inside the app shell (CSS Grid: topbar + sidebar + main). Use "Flows" not "Trees" in all user-facing text; use "Projects" not "Procedures" for procedural flows. Reference [UI-DESIGN-SYSTEM.md](UI-DESIGN-SYSTEM.md) for layout patterns, navigation, and component specs.
## Implementation Principles
- Prefer correct architecture over minimal diff
- If two approaches exist, implement the one that scales, not the one that's faster to write
- Flag any "simpler approach" tradeoffs for product owner review before proceeding
--- ---
## Current State ## Current State

View File

@@ -2,7 +2,7 @@ import { Outlet } from 'react-router-dom'
export function AccountLayout() { export function AccountLayout() {
return ( return (
<div className="container mx-auto max-w-(--breakpoint-lg) px-4 py-6"> <div className="overflow-y-auto h-full container mx-auto max-w-(--breakpoint-lg) px-4 py-6">
<Outlet /> <Outlet />
</div> </div>
) )

View File

@@ -19,7 +19,7 @@ export function ViewTransitionOutlet() {
const routeKey = segments.slice(0, 2).join('/') || '/' const routeKey = segments.slice(0, 2).join('/') || '/'
return ( return (
<div key={routeKey} className="flex-1 min-h-0 overflow-y-auto animate-fade-in-up"> <div key={routeKey} className="flex-1 min-h-0 animate-fade-in-up">
<Outlet /> <Outlet />
</div> </div>
) )

View File

@@ -306,7 +306,8 @@
.main-content { .main-content {
min-height: 0; min-height: 0;
min-width: 0; min-width: 0;
overflow-y: auto; /* Each page handles its own scrolling — full-height pages use
overflow-hidden, scrollable pages use overflow-y-auto */
} }
@media (max-width: 767px) { @media (max-width: 767px) {

View File

@@ -99,7 +99,7 @@ export default function BatchStatusPage() {
const progressPercent = total > 0 ? Math.round((completed / total) * 100) : 0 const progressPercent = total > 0 ? Math.round((completed / total) * 100) : 0
return ( return (
<div className="container mx-auto max-w-3xl space-y-6 px-4 py-6 sm:px-6 sm:py-8"> <div className="overflow-y-auto h-full container mx-auto max-w-3xl space-y-6 px-4 py-6 sm:px-6 sm:py-8">
{/* Breadcrumb */} {/* Breadcrumb */}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<button <button

View File

@@ -131,7 +131,7 @@ export function FeedbackPage() {
} }
return ( return (
<> <div className="overflow-y-auto h-full">
<PageMeta title="Feedback" /> <PageMeta title="Feedback" />
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
{/* Page header */} {/* Page header */}
@@ -276,7 +276,7 @@ export function FeedbackPage() {
)} )}
</div> </div>
</div> </div>
</> </div>
) )
} }

View File

@@ -9,7 +9,7 @@ export default function GuideDetailPage() {
if (!guide) { if (!guide) {
return ( return (
<div className="flex flex-col items-center justify-center h-full text-center p-6"> <div className="flex flex-col items-center justify-center h-full text-center p-6 overflow-y-auto">
<h2 className="text-lg font-heading font-semibold text-foreground mb-2">Guide Not Found</h2> <h2 className="text-lg font-heading font-semibold text-foreground mb-2">Guide Not Found</h2>
<p className="text-sm text-muted-foreground mb-4">The guide you're looking for doesn't exist.</p> <p className="text-sm text-muted-foreground mb-4">The guide you're looking for doesn't exist.</p>
<Link <Link
@@ -25,7 +25,7 @@ export default function GuideDetailPage() {
const Icon = guide.icon const Icon = guide.icon
return ( return (
<div className="p-6 max-w-3xl mx-auto"> <div className="overflow-y-auto h-full p-6 max-w-3xl mx-auto">
{/* Breadcrumb */} {/* Breadcrumb */}
<nav className="flex items-center gap-1.5 text-xs text-muted-foreground mb-6"> <nav className="flex items-center gap-1.5 text-xs text-muted-foreground mb-6">
<Link to="/guides" className="hover:text-primary transition-colors"> <Link to="/guides" className="hover:text-primary transition-colors">

View File

@@ -5,7 +5,7 @@ import { GuideCard } from '@/components/guides/GuideCard'
export default function GuidesHubPage() { export default function GuidesHubPage() {
return ( return (
<> <div className="overflow-y-auto h-full">
<PageMeta title="Guides" /> <PageMeta title="Guides" />
<div className="p-6 max-w-5xl mx-auto"> <div className="p-6 max-w-5xl mx-auto">
{/* Header */} {/* Header */}
@@ -28,6 +28,6 @@ export default function GuidesHubPage() {
))} ))}
</div> </div>
</div> </div>
</> </div>
) )
} }

View File

@@ -124,7 +124,7 @@ export default function MaintenanceFlowDetailPage() {
const hasActiveBatch = recentSessions.some(s => s.started_at && !s.completed_at && s.batch_id) const hasActiveBatch = recentSessions.some(s => s.started_at && !s.completed_at && s.batch_id)
return ( return (
<div className="container mx-auto max-w-4xl space-y-6 px-4 py-6 sm:px-6 sm:py-8"> <div className="overflow-y-auto h-full container mx-auto max-w-4xl space-y-6 px-4 py-6 sm:px-6 sm:py-8">
{/* Active batch banner */} {/* Active batch banner */}
{hasActiveBatch && !bannerDismissed && ( {hasActiveBatch && !bannerDismissed && (
<ActiveBatchBanner <ActiveBatchBanner

View File

@@ -122,7 +122,7 @@ export default function MySharesPage() {
} }
return ( return (
<> <div className="overflow-y-auto h-full">
<PageMeta title="My Shares" /> <PageMeta title="My Shares" />
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
{/* Back link */} {/* Back link */}
@@ -244,6 +244,6 @@ export default function MySharesPage() {
confirmLabel="Revoke" confirmLabel="Revoke"
/> />
</div> </div>
</> </div>
) )
} }

View File

@@ -118,7 +118,7 @@ export function MyTreesPage() {
} }
return ( return (
<> <div className="overflow-y-auto h-full">
<PageMeta title="My Flows" /> <PageMeta title="My Flows" />
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
<div className="mb-6 flex items-center justify-between sm:mb-8"> <div className="mb-6 flex items-center justify-between sm:mb-8">
@@ -393,7 +393,7 @@ export function MyTreesPage() {
)} )}
</div> </div>
</> </div>
) )
} }

View File

@@ -278,7 +278,7 @@ export function QuickStartPage() {
] ]
return ( return (
<> <div className="overflow-y-auto h-full">
<PageMeta title="Dashboard" /> <PageMeta title="Dashboard" />
<div className="p-6 space-y-6"> <div className="p-6 space-y-6">
{/* Greeting */} {/* Greeting */}
@@ -649,7 +649,7 @@ export function QuickStartPage() {
)} )}
</div> </div>
</> </div>
) )
} }

View File

@@ -340,7 +340,7 @@ export function SessionDetailPage() {
const outcomeConfig = session.outcome ? OUTCOME_CONFIG[session.outcome] : null const outcomeConfig = session.outcome ? OUTCOME_CONFIG[session.outcome] : null
return ( return (
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="overflow-y-auto h-full container mx-auto px-4 py-6 sm:px-6 sm:py-8">
{/* Back nav */} {/* Back nav */}
<button <button
onClick={() => navigate('/sessions')} onClick={() => navigate('/sessions')}

View File

@@ -156,7 +156,7 @@ export function SessionHistoryPage() {
} }
return ( return (
<> <div className="overflow-y-auto h-full">
<PageMeta title="Session History" /> <PageMeta title="Session History" />
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
<div className="mb-8"> <div className="mb-8">
@@ -316,7 +316,7 @@ export function SessionHistoryPage() {
</> </>
)} )}
</div> </div>
</> </div>
) )
} }

View File

@@ -266,7 +266,7 @@ export function TreeLibraryPage() {
selectedCategoryId || selectedTags.length > 0 || searchQuery || selectedFolderId selectedCategoryId || selectedTags.length > 0 || searchQuery || selectedFolderId
return ( return (
<> <div className="overflow-y-auto h-full">
<PageMeta title="Flow Library" /> <PageMeta title="Flow Library" />
<div className="min-h-full"> <div className="min-h-full">
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
@@ -599,7 +599,7 @@ export function TreeLibraryPage() {
/> />
)} )}
</div> </div>
</> </div>
) )
} }