Skip to content

🎨 Add Color-Coded Status Badges #72

Description

@desoga10

Description

Replace plain text invoice status with visual, color-coded badges to improve readability and make status recognition instant at a glance.

Why This Matters

  • Visual clarity: Colors convey meaning faster than text
  • Better UX: Users can quickly scan and identify invoice statuses
  • Professional appearance: Modern apps use visual indicators
  • Accessibility: Combine color + icon + text for all users

Current State

Invoice status displayed as plain text:

  • "paid"
  • "unpaid"
  • "draft"
  • "overdue"

Proposed Solution

Styled badges with colors and icons:

  • 🟢 PAID - Green badge with checkmark icon
  • 🔴 OVERDUE - Red badge with alert icon
  • 🟡 UNPAID - Yellow/Orange badge with clock icon
  • DRAFT - Gray badge with pencil icon

Visual Design

Badge Appearance:

[✓ PAID]     Green background, white text
[⏰ UNPAID]   Amber background, dark text
[⚠ OVERDUE]  Red background, white text
[📝 DRAFT]    Gray background, white text

Size Variants:

  • Small: For table rows (compact)
  • Medium: For cards and lists (default)
  • Large: For invoice detail page headers

Color Palette

Status Background Text Icon
Paid #10b981 (Green) #ffffff (White) check-circle
Unpaid #f59e0b (Amber) #78350f (Dark) clock
Overdue #ef4444 (Red) #ffffff (White) alert-circle
Draft #6b7280 (Gray) #ffffff (White) file-text

Where to Apply

Invoice List Page

  • Replace status column text with small badges
  • Compact display for table rows

Invoice Detail Page

  • Large badge prominently displayed near invoice number
  • Clear status indication

Dashboard (if exists)

  • Use badges in recent invoice lists
  • Status charts can use same colors

PDF Exports

  • Include colored status badge in generated PDFs
  • Print-friendly colors (work in grayscale too)

Technical Implementation

Create Reusable Component:

@Component({
  selector: 'app-status-badge',
  template: `
    <span class="badge badge-{{status}}" [class.badge-sm]="size === 'small'">
      <lucide-icon [name]="getIcon()" [size]="iconSize"></lucide-icon>
      <span>{{ status | titlecase }}</span>
    </span>
  `
})
export class StatusBadgeComponent {
  @Input() status: 'paid' | 'unpaid' | 'overdue' | 'draft' = 'draft';
  @Input() size: 'small' | 'medium' | 'large' = 'medium';
  
  getIcon(): string {
    const icons = {
      paid: 'check-circle',
      unpaid: 'clock',
      overdue: 'alert-circle',
      draft: 'file-text'
    };
    return icons[this.status];
  }
}

Usage in Templates:

<!-- Before -->
<td>{{ invoice.status }}</td>

<!-- After -->
<td>
  <app-status-badge [status]="invoice.status" size="small"></app-status-badge>
</td>

<!-- Invoice detail page -->
<app-status-badge [status]="invoice.status" size="large"></app-status-badge>

Styling Approach

Use Tailwind utility classes or custom CSS:

  • Rounded corners (border-radius: 12px)
  • Inline-flex layout (icon + text aligned)
  • Padding: 4px 12px (medium), adjust for sizes
  • Font weight: 600 (semi-bold)
  • Text transform: uppercase
  • Letter spacing: 0.5px

Design Considerations

Accessibility:

  • Ensure sufficient color contrast (WCAG AA standard)
  • Include icon + text (not color alone)
  • Add aria-label for screen readers
  • Support high contrast mode

Responsive:

  • Work on mobile, tablet, desktop
  • Scale appropriately at different screen sizes
  • Don't break table layouts on mobile

Print-Friendly:

  • Colors should be distinguishable in grayscale
  • Status readable when printed in black & white

Acceptance Criteria

  • StatusBadge component created
  • All 4 status types styled correctly
  • Icons display for each status
  • Three size variants work (small, medium, large)
  • Applied to invoice list page
  • Applied to invoice detail page
  • Applied to dashboard (if exists)
  • Sufficient color contrast (WCAG AA)
  • Accessible to screen readers
  • Responsive on all devices
  • Works in PDF exports

Example Layouts

Invoice List Table:

┌──────────┬────────────┬─────────┬────────────┐
│ Invoice  │ Client     │ Amount  │ Status     │
├──────────┼────────────┼─────────┼────────────┤
│ INV-001  │ Acme Corp  │ $1,200  │ [✓ PAID]   │
│ INV-002  │ Tech Inc   │ $850    │ [⏰ UNPAID] │
│ INV-003  │ Startup Co │ $2,500  │ [⚠ OVERDUE]│
│ INV-004  │ Local Biz  │ $500    │ [📝 DRAFT]  │
└──────────┴────────────┴─────────┴────────────┘

Invoice Detail Header:

┌─────────────────────────────────────────┐
│ Invoice #INV-001                         │
│ [✓ PAID]                                │
│                                          │
│ Client: Acme Corporation                 │
│ Amount: $1,200.00                        │
└─────────────────────────────────────────┘

Edge Cases

  • Very long status text (shouldn't happen, but handle)
  • Missing status (default to 'draft')
  • Custom statuses in future (make extensible)
  • Dark mode support (future enhancement)

Testing Checklist

  • All 4 statuses render correctly
  • Size variants display properly
  • Icons show correctly
  • Colors have good contrast
  • Readable on mobile devices
  • Screen reader announces status
  • Works in different browsers
  • Prints correctly (grayscale test)

Bonus Features

  • Pulse animation for "unpaid" badges (subtle)
  • Tooltip on hover showing more details
  • Status filter chips using same badge style
  • Transition animation when status changes

Priority

Medium - Nice UX improvement

Estimated Complexity

Low - Straightforward component creation

Estimated Time

2-4 hours

Related Features

  • Dashboard analytics (use same colors)
  • Status filters (matching badge styles)
  • PDF exports (include badges)

Notes

Keep it simple and consistent. The component should be reusable across the entire app. Consider making it generic enough to use for other status types in the future.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions