18 KiB
Sites Module UI Standardization Plan
Goal: Make Sites module UI consistent with IGNY8 global design standard (Planner/Writer/Dashboard)
Reference: See IGNY8_DESIGN_STANDARD.md for complete design patterns
Status: Ready for implementation
Priority: Medium-High (improves UX, accessibility, maintainability)
Estimated Effort: 4-6 hours
Executive Summary
Current State
The Sites module uses inconsistent UI patterns:
- ✅ Uses Button component correctly in many places
- ✅ Uses EnhancedMetricCard for metrics
- ❌ Uses
<button onClick={() => navigate(...)}instead of<Link to={...}>in Quick Actions - ❌ Missing ComponentCard wrapper for section organization
- ⚠️ Heavy inline Tailwind styling instead of reusable components
- ⚠️ Manual section headings instead of ComponentCard title prop
Target State
Standardize Sites module to match Planner/Writer patterns:
- ✅ All navigation uses
<Link>component (accessibility + keyboard nav) - ✅ All sections wrapped in ComponentCard
- ✅ Quick Actions follow standard gradient icon pattern
- ✅ Consistent Button component usage (no raw buttons)
- ✅ Reduced inline Tailwind duplication
Impact
- Accessibility: Better keyboard navigation and screen reader support
- Maintainability: Easier to update shared styles globally
- Consistency: Users see familiar patterns across all modules
- Code Quality: Less duplication, clearer component boundaries
Audit Results
Files Analyzed
- ✅
Dashboard.tsx(357 lines) - Main site dashboard - ✅
List.tsx(sites list and creation) - ✅
Settings.tsx(site settings tabs) - ✅
Content.tsx(content management) - ✅
PageManager.tsx(page management) - ✅
PostEditor.tsx(post editing) - ✅
SyncDashboard.tsx(sync status) - ✅
DeploymentPanel.tsx(deployment) - ✅
Preview.tsx(site preview) - ✅
Manage.tsx(site management) - ✅
Editor.tsx(site editor)
Issues Found
1. Navigation Pattern Inconsistency
Files affected: Dashboard.tsx (5 instances)
Current (❌):
<button
onClick={() => navigate(`/sites/${siteId}/pages`)}
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[var(--color-primary)] hover:shadow-lg transition-all group"
>
{/* ... */}
</button>
Target (✅):
<Link
to={`/sites/${siteId}/pages`}
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[var(--color-primary)] hover:shadow-lg transition-all group"
>
{/* ... */}
</Link>
Reason: Link provides better accessibility, keyboard navigation, and browser features (right-click open in new tab)
2. Missing ComponentCard Wrapper
Files affected: Dashboard.tsx, List.tsx, Settings.tsx
Current (❌):
<div className="mb-6">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">
Quick Actions
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{/* actions */}
</div>
</div>
Target (✅):
<ComponentCard title="Quick Actions" desc="Common site management tasks">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{/* actions */}
</div>
</ComponentCard>
Reason: Consistent section styling, automatic dark mode support, less boilerplate
3. Button + Navigate Anti-Pattern
Files affected: Content.tsx (2 instances), Editor.tsx (2 instances), List.tsx (1 instance)
Current (❌):
<Button onClick={() => navigate('/sites/builder')} variant="primary">
Create New Site
</Button>
Target (✅):
<Button as={Link} to="/sites/builder" variant="primary">
Create New Site
</Button>
Reason: Button component supports as prop for Link rendering while maintaining Button styles
4. Inline Tailwind Duplication
Files affected: Settings.tsx (30+ instances), Content.tsx, List.tsx
Example:
className="mt-1 w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-md dark:bg-gray-800 dark:text-white"
Solution: Extract to reusable Input component or use existing form components
5. Raw Button Elements
Files affected: Multiple (50+ instances found)
Pattern: Some <button> tags for non-navigation actions (modals, toggles) - these are acceptable if not for navigation
Refactoring Plan by File
Phase 1: Dashboard.tsx (High Priority)
Lines affected: 254-324 (Quick Actions section)
Changes:
- Import Link from react-router-dom
- Replace 5
<button onClick={navigate}>with<Link to> - Wrap Quick Actions section in ComponentCard
- Remove manual heading, use ComponentCard title prop
Before:
<div className="mb-6">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">
Quick Actions
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<button onClick={() => navigate(`/sites/${siteId}/pages`)} className="...">
{/* ... */}
</button>
</div>
</div>
After:
<ComponentCard title="Quick Actions" desc="Common site management tasks">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<Link to={`/sites/${siteId}/pages`} className="...">
{/* ... */}
</Link>
</div>
</ComponentCard>
Estimated Time: 30 minutes
Phase 2: Content.tsx (Medium Priority)
Lines affected: 133, 214 (Button with navigate)
Changes:
- Replace
<Button onClick={() => navigate(...)}>with<Button as={Link} to={...}> - Verify variant prop consistency
- Test navigation after change
Before:
<Button onClick={() => navigate(`/sites/${siteId}/posts/new`)} variant="primary">
Create New Post
</Button>
After:
<Button as={Link} to={`/sites/${siteId}/posts/new`} variant="primary">
Create New Post
</Button>
Estimated Time: 15 minutes
Phase 3: List.tsx (Medium Priority)
Lines affected: 670 (Button with navigate), filter/tab sections
Changes:
- Replace
<Button onClick={() => navigate('/sites/builder')}with<Button as={Link} to="/sites/builder"> - Consider extracting filter section to reusable component
- Review tab navigation pattern for consistency
Estimated Time: 30 minutes
Phase 4: Settings.tsx (Low Priority - Large File)
Lines affected: 30+ inline Tailwind instances
Changes:
- Extract repeated input styling to shared component
- Consider creating SettingsSection component (like ComponentCard but for tabs)
- Review tab navigation pattern
- Consolidate status badge styling
Deferred: This file needs deeper refactor - consider separate task
Estimated Time: 2 hours (deferred)
Phase 5: Editor.tsx (Low Priority)
Lines affected: 117, 147 (Button with navigate)
Changes:
- Replace Button + navigate with Button as Link
- Verify navigation flow
Estimated Time: 10 minutes
Phase 6: Other Files
Files: SyncDashboard.tsx, PageManager.tsx, DeploymentPanel.tsx, Preview.tsx, Manage.tsx
Review: Most raw buttons here are for actions (not navigation) - acceptable usage Action: Verify each instance is truly an action (modal, toggle) and not navigation
Estimated Time: 30 minutes audit
Implementation Steps (Detailed)
Step 1: Create Quick Action Component (Optional - DRY)
File: frontend/src/components/sites/SiteActionCard.tsx
Purpose: Extract repeated Quick Action card pattern
Props:
interface SiteActionCardProps {
to: string;
icon: ReactNode;
title: string;
description: string;
gradientColor: 'primary' | 'success' | 'warning' | 'purple';
hoverColor: string;
}
Benefits:
- Reduce duplication (5 cards in Dashboard become 5 component calls)
- Consistent styling automatically
- Easier to update globally
Decision: Create if time permits - not critical path
Step 2: Dashboard.tsx Refactor
File: frontend/src/pages/Sites/Dashboard.tsx
Line-by-line changes:
- Add import:
import { Link } from 'react-router-dom';
import ComponentCard from '../../components/common/ComponentCard';
- Replace Quick Actions section (lines 245-324):
OLD:
{/* Quick Actions - Matching Planner Dashboard pattern */}
<div className="mb-6">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">
Quick Actions
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<button
onClick={() => navigate(`/sites/${siteId}/pages`)}
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[var(--color-primary)] hover:shadow-lg transition-all group"
>
NEW:
{/* Quick Actions */}
<ComponentCard title="Quick Actions" desc="Common site management tasks">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<Link
to={`/sites/${siteId}/pages`}
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[var(--color-primary)] hover:shadow-lg transition-all group"
>
-
Repeat for all 5 action cards:
- Manage Pages →
/sites/${siteId}/pages - Manage Content →
/sites/${siteId}/content - Integrations →
/sites/${siteId}/settings?tab=integrations - Sync Dashboard →
/sites/${siteId}/sync - Deploy Site →
/sites/${siteId}/deploy
- Manage Pages →
-
Update Recent Activity section (optional):
<ComponentCard title="Recent Activity">
{/* content */}
</ComponentCard>
Step 3: Content.tsx Refactor
File: frontend/src/pages/Sites/Content.tsx
Changes:
- Import Link:
import { Link } from 'react-router-dom';
- Replace line 133:
// OLD
<Button onClick={() => navigate(`/sites/${siteId}/posts/new`)} variant="primary">
// NEW
<Button as={Link} to={`/sites/${siteId}/posts/new`} variant="primary">
- Replace line 214 (duplicate):
// OLD
<Button onClick={() => navigate(`/sites/${siteId}/posts/new`)} variant="primary">
// NEW
<Button as={Link} to={`/sites/${siteId}/posts/new`} variant="primary">
Step 4: List.tsx Refactor
File: frontend/src/pages/Sites/List.tsx
Changes:
- Import Link:
import { Link } from 'react-router-dom';
- Replace line 670:
// OLD
<Button onClick={() => navigate('/sites/builder')} variant="outline">
// NEW
<Button as={Link} to="/sites/builder" variant="outline">
- Review filter buttons (lines 681-693): These appear to be actual buttons (state toggles), not navigation - keep as-is
Step 5: Editor.tsx Refactor
File: frontend/src/pages/Sites/Editor.tsx
Changes:
- Import Link:
import { Link } from 'react-router-dom';
- Replace line 117:
// OLD
<Button onClick={() => navigate('/sites/builder')} variant="primary">
// NEW
<Button as={Link} to="/sites/builder" variant="primary">
- Replace line 147:
// OLD
<Button onClick={() => navigate('/sites/builder')} variant="primary">
// NEW
<Button as={Link} to="/sites/builder" variant="primary">
Step 6: Final Audit
Files: All Sites pages
Checklist:
- No
<button onClick={() => navigate(...)}for navigation - All navigation uses Link or Button with
as={Link} - Section headers use ComponentCard where appropriate
- EnhancedMetricCard used for all metrics
- Button component variants consistent
- No raw
<button>for navigation (actions are OK)
Testing Plan
Visual Regression Testing
- Compare Sites Dashboard to Planner Dashboard side-by-side
- Verify Quick Actions grid layout matches (1/2/3 columns)
- Verify gradient icon boxes match size and colors
- Verify hover states match (border color, shadow)
- Verify ComponentCard styling matches other modules
Functional Testing
- Test keyboard navigation (Tab through actions, Enter to navigate)
- Test right-click "Open in new tab" on all action cards
- Test screen reader labels (use browser inspector)
- Test all navigation paths work correctly
- Test dark mode consistency
Accessibility Testing
- Run Lighthouse accessibility audit before/after
- Verify all Links have proper href attributes (not onClick)
- Verify focus indicators visible on keyboard nav
- Verify semantic HTML (Links vs buttons)
Code Quality Testing
- Run TypeScript compiler - 0 errors
- Run ESLint - 0 warnings on changed files
- Verify no console errors in browser
- Verify no duplicate imports
Rollback Plan
Pre-Implementation
- Create feature branch:
feature/sites-ui-standardization - Commit each file change separately for easy rollback
- Test each file after change before moving to next
If Issues Found
- Revert specific file commit
- Investigate issue in isolation
- Re-apply fix and test
Full Rollback
git checkout main -- frontend/src/pages/Sites/Dashboard.tsx
git checkout main -- frontend/src/pages/Sites/Content.tsx
# etc.
Success Criteria
Must Have (P0)
- ✅ All Quick Actions use Link component (not button + navigate)
- ✅ Dashboard Quick Actions wrapped in ComponentCard
- ✅ Zero TypeScript errors
- ✅ All navigation paths work correctly
Should Have (P1)
- ✅ Button + navigate replaced with Button as Link
- ✅ Keyboard navigation works on all action cards
- ✅ Visual consistency with Planner/Writer modules
Nice to Have (P2)
- ⏸ SiteActionCard component extracted (DRY improvement)
- ⏸ Settings.tsx input styling standardized (larger refactor)
- ⏸ Status badge component extracted
Risk Assessment
Low Risk
- Dashboard.tsx Quick Actions refactor (structural change, low impact)
- Content/List/Editor Button changes (simple prop change)
Medium Risk
- ComponentCard integration (may affect spacing/layout)
- Link component behavior differences (unlikely but possible)
High Risk
- None identified
Mitigation
- Test in dev environment before production
- Create feature flag if needed (not expected)
- Monitor error logs after deployment
Timeline
Immediate (Today)
- ✅ Design standard documentation (DONE)
- ✅ Audit sites pages (DONE)
- ✅ Create refactoring plan (DONE)
Phase 1 (1-2 hours)
- Dashboard.tsx Quick Actions refactor
- Test visual consistency
- Test navigation functionality
Phase 2 (30 minutes)
- Content.tsx, List.tsx, Editor.tsx refactors
- Test all navigation paths
Phase 3 (30 minutes)
- Final audit and QA
- Accessibility testing
- Documentation update
Total Estimated Time: 2-3 hours active work
Documentation Updates
After Implementation
- Update DESIGN_SYSTEM.md with Sites module compliance
- Add Sites Dashboard to reference implementations list
- Document SiteActionCard component (if created)
- Update CHANGELOG.md with UI standardization entry
Future Enhancements
Beyond This Refactor
- Extract Settings.tsx tab pattern to reusable component
- Create FormInput component for repeated input styling
- Standardize status badge patterns across all modules
- Add loading states to all navigation actions
- Add transition animations to match Planner/Writer
Technical Debt Reduction
- Audit all inline Tailwind usage across Sites module
- Create Sites-specific component library (like dashboard components)
- Consolidate color usage (ensure CSS variables used consistently)
Questions & Decisions
Open Questions
-
Should we create SiteActionCard component now or later?
- Decision: Later - keep first pass simple, extract after pattern proven
-
Should Settings.tsx be included in this refactor?
- Decision: No - defer to separate task due to complexity
-
Should we add analytics tracking to navigation events?
- Decision: Out of scope - separate feature request
Decisions Made
- ✅ Use Link component (not button + navigate) for all navigation
- ✅ Use ComponentCard for section organization
- ✅ Use Button
as={Link}pattern for button-styled navigation - ✅ Defer Settings.tsx refactor to separate task
- ✅ Keep PageManager.tsx raw buttons (mostly actions, not navigation)
Appendix: Code Snippets
Standard Quick Action Card Pattern
<Link
to={path}
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[var(--color-primary)] hover:shadow-lg transition-all group"
>
<div className="size-12 rounded-xl bg-gradient-to-br from-[var(--color-primary)] to-[var(--color-primary-dark)] flex items-center justify-center text-white shadow-lg">
<Icon className="h-6 w-6" />
</div>
<div className="flex-1 text-left">
<h4 className="font-semibold text-slate-900 mb-1">Action Title</h4>
<p className="text-sm text-slate-600">Action description</p>
</div>
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[var(--color-primary)] transition" />
</Link>
Gradient Color Reference
// Primary (Blue)
from-[var(--color-primary)] to-[var(--color-primary-dark)]
hover:border-[var(--color-primary)]
group-hover:text-[var(--color-primary)]
// Success (Green)
from-[var(--color-success)] to-[var(--color-success-dark)]
hover:border-[var(--color-success)]
group-hover:text-[var(--color-success)]
// Warning (Orange)
from-[var(--color-warning)] to-[var(--color-warning-dark)]
hover:border-[var(--color-warning)]
group-hover:text-[var(--color-warning)]
// Purple
from-[var(--color-purple)] to-[var(--color-purple-dark)]
hover:border-[var(--color-purple)]
group-hover:text-[var(--color-purple)]
End of Plan
Next Steps:
- Review this plan with team (if applicable)
- Create feature branch
- Start Phase 1 implementation (Dashboard.tsx)
- Test and iterate
- Deploy and monitor
Prepared By: GitHub Copilot
Date: 2025-01-21
Version: 1.0