Files
igny8/IGNY8_DESIGN_STANDARD.md
IGNY8 VPS (Salman) 4fe68cc271 ui frotneedn fixes
2025-11-26 06:47:23 +00:00

15 KiB

IGNY8 Design Standard Reference

Standardized UI patterns used across Planner, Writer, and Dashboard modules

This document defines the locked design patterns and component usage standards for the IGNY8 application. All modules (including Sites) should follow these patterns to maintain visual consistency.


Core Component Library

1. Button Component

Location: frontend/src/components/ui/button/Button.tsx
Status: 🔒 STYLE LOCKED - See DESIGN_SYSTEM.md

Variants (5 total)

  • solid - Filled background (primary action)
  • soft - Light background (secondary action)
  • outline - Border only (tertiary action)
  • ghost - No border or background (minimal action)
  • gradient - Gradient background with shadow (premium/highlight action)

Sizes (4 total)

  • xs - Extra small
  • sm - Small
  • md - Medium (default)
  • lg - Large

Tones (5 total)

  • brand - Primary brand color (blue)
  • success - Green
  • warning - Orange
  • danger - Red/Error
  • neutral - Gray

Usage Example

import Button from '../../components/ui/button/Button';

<Button variant="solid" tone="brand" size="md" startIcon={<Icon />}>
  Click Me
</Button>

⚠️ Anti-Pattern

// ❌ DON'T: Raw HTML buttons with inline Tailwind
<button className="px-4 py-2 bg-blue-500 text-white rounded-lg">
  Click Me
</button>

// ✅ DO: Use Button component
<Button variant="solid" tone="brand">
  Click Me
</Button>

2. ComponentCard

Location: frontend/src/components/common/ComponentCard.tsx
Purpose: Standard card wrapper for sections with title and description

Props

  • title (required) - Section title (string or ReactNode)
  • desc (optional) - Description text below title
  • children (required) - Card content
  • className (optional) - Additional styling

Usage Example

import ComponentCard from '../../components/common/ComponentCard';

<ComponentCard title="Quick Actions" desc="Common planning tasks and shortcuts">
  <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
    {/* Content */}
  </div>
</ComponentCard>

Structure

  • Header: Title + optional description (gray text)
  • Body: Border-top separated content area with padding
  • Dark mode: Automatic theme support

⚠️ Anti-Pattern

// ❌ DON'T: Raw Card component with manual header
<Card>
  <div className="px-6 py-5">
    <h3 className="text-base font-medium">Quick Actions</h3>
  </div>
  <div className="p-6">
    {/* Content */}
  </div>
</Card>

// ✅ DO: Use ComponentCard
<ComponentCard title="Quick Actions">
  {/* Content */}
</ComponentCard>

3. EnhancedMetricCard

Location: frontend/src/components/dashboard/EnhancedMetricCard.tsx
Purpose: Display metrics with optional trends, tooltips, and navigation

Key Props

  • title (required) - Metric label
  • value (required) - Main metric value (string | number)
  • subtitle (optional) - Additional context below value
  • icon (optional) - Icon component
  • accentColor (required) - Border accent color
  • trend (optional) - { direction: 'up' | 'down', value: string }
  • href (optional) - React Router navigation path
  • onClick (optional) - Click handler (alternative to href)
  • tooltip (optional) - Tooltip text on hover
  • details (optional) - Array of tooltip detail breakdowns

Accent Colors (6 total)

  • blue - Primary/default metrics
  • green - Success/positive metrics
  • orange - Warning/attention metrics
  • purple - Special/premium metrics
  • red - Error/critical metrics
  • success - Alternative green (var(--color-success))

Usage Example

import EnhancedMetricCard from '../../components/dashboard/EnhancedMetricCard';

<EnhancedMetricCard
  title="Active Keywords"
  value={1234}
  subtitle="Across all clusters"
  icon={<ListIcon className="h-5 w-5" />}
  accentColor="blue"
  trend={{ direction: 'up', value: '+12%' }}
  href="/planner/keywords"
  tooltip="View all active keywords"
  details={[
    { label: 'Tracked', value: '800' },
    { label: 'Untracked', value: '434' },
  ]}
/>

Features

  • Automatic Link wrapping when href provided
  • Hover effects and transitions
  • Dark mode support
  • Tooltip with optional details breakdown
  • Trend indicators with arrows

⚠️ Anti-Pattern

// ❌ DON'T: Custom metric cards with inline styles
<div className="bg-white rounded-xl border-2 border-slate-200 p-6">
  <div className="flex items-center justify-between">
    <div>
      <p className="text-sm text-gray-600">Active Keywords</p>
      <p className="text-3xl font-bold">1,234</p>
    </div>
    <ListIcon className="h-8 w-8 text-blue-500" />
  </div>
</div>

// ✅ DO: Use EnhancedMetricCard
<EnhancedMetricCard
  title="Active Keywords"
  value={1234}
  icon={<ListIcon className="h-5 w-5" />}
  accentColor="blue"
/>

4. PageHeader

Location: frontend/src/components/common/PageHeader.tsx
Purpose: Standardized page header with title, site/sector info, and selectors

Key Props

  • title (required) - Page title
  • lastUpdated (optional) - Last refresh timestamp
  • badge (optional) - { icon: ReactNode, color: 'blue' | 'green' | ... }
  • showRefresh (optional) - Show refresh button
  • onRefresh (optional) - Refresh button handler
  • hideSiteSector (optional) - Hide site/sector info for global pages
  • className (optional) - Additional styling

Badge Colors (6 total)

Same as Button/Metric: blue, green, purple, orange, red, indigo

Usage Example

import PageHeader from '../../components/common/PageHeader';
import { ListIcon } from '../../icons';

<PageHeader
  title="Keyword Dashboard"
  lastUpdated={new Date()}
  badge={{ icon: <ListIcon className="h-5 w-5" />, color: 'blue' }}
  showRefresh={true}
  onRefresh={handleRefresh}
/>

Features

  • Automatic site/sector display from stores
  • SiteAndSectorSelector integration
  • Responsive layout (stack on mobile)
  • Badge with icon support
  • Last updated timestamp

⚠️ Anti-Pattern

// ❌ DON'T: Custom page headers with manual layout
<div className="flex items-center justify-between mb-6">
  <div>
    <h2 className="text-2xl font-bold">Keyword Dashboard</h2>
    <p className="text-sm text-gray-500">
      Site: {site.name}  Sector: {sector.name}
    </p>
  </div>
  <button onClick={refresh}>Refresh</button>
</div>

// ✅ DO: Use PageHeader
<PageHeader
  title="Keyword Dashboard"
  showRefresh={true}
  onRefresh={refresh}
/>

Location: react-router-dom
Purpose: Standard navigation with automatic prefetching and accessibility

Usage Example

import { Link } from 'react-router-dom';

<Link
  to="/planner/keywords"
  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>Navigate to Keywords</div>
</Link>

Benefits Over Button + Navigate

  • Proper semantic HTML (<a> tag)
  • Keyboard navigation (Tab + Enter)
  • Right-click "Open in new tab" support
  • Screen reader accessibility
  • Browser history support
  • Automatic prefetching

⚠️ Anti-Pattern

// ❌ DON'T: Button with onClick navigate
<button onClick={() => navigate('/planner/keywords')}>
  Go to Keywords
</button>

// ✅ DO: Use Link component
<Link to="/planner/keywords">
  Go to Keywords
</Link>

Design Patterns

Quick Actions Grid

Standard pattern used in: Planner Dashboard, Writer Dashboard

Structure

<ComponentCard title="Quick Actions" desc="Common planning tasks and shortcuts">
  <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
    <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"
    >
      {/* Gradient Icon */}
      <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>
      
      {/* Content */}
      <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>
      
      {/* Arrow Icon */}
      <ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[var(--color-primary)] transition" />
    </Link>
  </div>
</ComponentCard>

Key Elements

  1. ComponentCard wrapper - Title + description
  2. Responsive grid - 1 col mobile, 2 col tablet, 4 col desktop
  3. Link component - Not button
  4. Gradient icon box - 48px (size-12), gradient from primary to primary-dark
  5. Content area - Title (font-semibold) + description (text-sm)
  6. Arrow icon - Right-pointing, changes color on hover
  7. Hover effects - Border color + shadow on hover

Gradient Color Variants

// Primary (Blue)
from-[var(--color-primary)] to-[var(--color-primary-dark)]

// Success (Green)
from-[var(--color-success)] to-[var(--color-success-dark)]

// Warning (Orange)
from-[var(--color-warning)] to-[var(--color-warning-dark)]

// Purple
from-[var(--color-purple)] to-[var(--color-purple-dark)]

⚠️ Anti-Pattern - Sites Dashboard Current Implementation

// ❌ DON'T: Button with navigate + manual styling
<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>

// ✅ DO: Link component
<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>

Metrics Dashboard Grid

Standard pattern used in: Planner Dashboard, Writer Dashboard

Structure

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  <EnhancedMetricCard
    title="Metric Name"
    value={1234}
    icon={<Icon className="h-5 w-5" />}
    accentColor="blue"
    href="/path"
  />
</div>

Grid Breakpoints

  • Mobile (< 768px): 1 column
  • Tablet (768px - 1024px): 2 columns
  • Desktop (> 1024px): 3 columns

Best Practices

  • Use href prop for navigation (not onClick)
  • Consistent icon sizing: h-5 w-5
  • Map accent colors to metric meaning (blue = neutral, green = success, orange = warning, red = error)
  • Include tooltips for complex metrics
  • Add trend indicators when comparing periods

Color System

CSS Variables

--color-primary: #0693e3; /* Brand Blue */
--color-primary-dark: #0570b8;
--color-success: #0bbf87; /* Green */
--color-success-dark: #089968;
--color-warning: #ff7a00; /* Orange */
--color-warning-dark: #cc6200;
--color-purple: #5d4ae3;
--color-purple-dark: #4a3bb5;
--color-error: #f44336; /* Red */

Tailwind Color Classes

  • brand-* - Primary blue (50-900)
  • success-* - Green (50-900)
  • warning-* - Orange (50-900)
  • error-* - Red (50-900)
  • purple-* - Purple (50-900)
  • gray-* - Neutral (50-900)

Sites Module Refactor Checklist

Current Inconsistencies (Sites Dashboard Example)

  • Uses <button onClick={() => navigate(...)} instead of <Link to={...}>
  • Missing ComponentCard wrapper for Quick Actions section
  • Manual heading instead of ComponentCard title prop
  • ⚠️ Uses Button component correctly (partial compliance)
  • Uses EnhancedMetricCard correctly

Required Changes

  1. Replace all <button onClick={() => navigate(...)} with <Link to={...}>

    • Better accessibility
    • Standard keyboard navigation
    • Consistent with Planner/Writer modules
  2. Wrap Quick Actions in ComponentCard

    • Current: Manual <h2> heading
    • Target: <ComponentCard title="Quick Actions" desc="...">
  3. Extract ActionCard component (if repeated)

    • DRY principle for Quick Action cards
    • Reusable across Sites module
  4. Standardize Button usage

    • Verify all buttons use variant prop (not custom classes)
    • Ensure consistent tone/size across module
  5. Add missing EnhancedMetricCard features

    • Tooltips for complex metrics
    • Trend indicators where applicable

Implementation Priority

Phase 1: Navigation (High Impact)

  1. Replace button + navigate with Link components
  2. Update click handlers to href props
  3. Test keyboard navigation and accessibility

Phase 2: Component Wrapping (Medium Impact)

  1. Wrap sections in ComponentCard
  2. Replace manual headings with ComponentCard title prop
  3. Verify consistent spacing and styling

Phase 3: Component Extraction (Low Impact)

  1. Create reusable ActionCard component
  2. Create SiteMetricCard if Sites-specific logic needed
  3. Update DESIGN_SYSTEM.md with new components

Phase 4: Polish (Continuous)

  1. Add missing tooltips
  2. Add trend indicators
  3. Verify dark mode consistency
  4. Test responsive layouts

Testing Checklist

Visual Consistency

  • Quick Actions match Planner/Writer pattern
  • Metrics grid matches dashboard standards
  • Button variants consistent across pages
  • Color usage matches design system

Accessibility

  • All navigation uses Link (not button)
  • Keyboard navigation works (Tab, Enter)
  • Screen reader labels present
  • Focus indicators visible

Functionality

  • All routes navigate correctly
  • Hover states work consistently
  • Dark mode renders properly
  • Responsive breakpoints work

Code Quality

  • No raw <button> for navigation
  • No inline Tailwind for common patterns
  • TypeScript errors resolved
  • Component props properly typed

References

Key Files

  • frontend/DESIGN_SYSTEM.md - Locked component variants
  • frontend/src/components/ui/button/Button.tsx - Button component
  • frontend/src/components/common/ComponentCard.tsx - Card wrapper
  • frontend/src/components/dashboard/EnhancedMetricCard.tsx - Metric display
  • frontend/src/components/common/PageHeader.tsx - Page header
  • frontend/src/pages/Planner/Dashboard.tsx - Reference implementation
  • frontend/src/pages/Writer/Dashboard.tsx - Reference implementation
  • master-docs/API-COMPLETE-REFERENCE.md - API contracts
  • REFACTOR_DOCS_INDEX.md - Refactor documentation
  • .github/copilot-instructions.md - AI agent guidelines

Last Updated: 2025-01-21
Maintained By: IGNY8 Development Team
Status: Living Document - Update when design patterns change