Global: Extract ScrapeStatusIcon into a brand-consistent shared status component #47

Closed
opened 2026-06-27 15:41:16 +02:00 by bullitt · 1 comment
Owner

Problem

The ScrapeStatusIcon component is defined twice with identical logic:

  • frontend/src/pages/ShipmentDetail.tsx line ~104: function ScrapeStatusIcon
  • frontend/src/pages/Settings.tsx line ~401: function SettingsScrapeStatusIcon

Both switch on the same status values (success, no_change, error, timeout, disabled) and return the same icons. If a new status is added, both must be updated in sync. One will inevitably drift.

Implementation

Create a new shared component file: frontend/src/components/ScrapeStatusIcon.tsx:

export function ScrapeStatusIcon({ status }: { status: string }) {
  switch (status) {
    case "success":
      return <span className="text-emerald-600" title="Success"></span>
    case "no_change":
      return <span className="text-muted-foreground" title="No change"></span>
    case "error":
      return <span className="text-red-600" title="Error"></span>
    case "timeout":
      return <span className="text-amber-600" title="Timeout"></span>
    case "disabled":
      return <span className="text-red-600" title="Disabled"></span>
    default:
      return <span className="text-muted-foreground">?</span>
  }
}

Then in both ShipmentDetail.tsx and Settings.tsx:

  • Remove the local ScrapeStatusIcon / SettingsScrapeStatusIcon function definitions
  • Import: import { ScrapeStatusIcon } from "@/components/ScrapeStatusIcon"
  • Update all usages to <ScrapeStatusIcon status={...} />

Acceptance criteria

  • ScrapeStatusIcon is defined once in frontend/src/components/ScrapeStatusIcon.tsx
  • Both ShipmentDetail.tsx and Settings.tsx import and use the shared component
  • No local duplicate definitions remain

Brand identity alignment

Sync/scrape status is a recurring data-transparency signal. A shared component ensures consistent semantic color, iconography, labels, and accessibility across Detail and Settings.

Brand-compliant implementation notes

  • Prefer lucide line icons (CheckCircle2, MinusCircle, AlertTriangle, Clock, CircleOff, HelpCircle) over mixed text emoji symbols.
  • Pair icons with title/aria-label so status is not color-only.
  • Use semantic colors from the brand brief: green for success, amber for timeout/no fresh data, red for errors, gray for disabled/no change.
  • Keep default icon size consistent with the rest of the UI (h-4 w-4).

Additional acceptance criteria

  • The shared component centralizes status labels and semantic colors.
  • Both Settings and Detail use the same status language and icon treatment.
  • The component remains compact enough for tables and log rows.

Migrated from GitHub issue #26: https://github.com/bullitt186/trackbox/issues/26
Original author: @bullitt186
Original created: 2026-06-27T13:26:10Z
Original labels: ux

## Problem The `ScrapeStatusIcon` component is defined twice with identical logic: - `frontend/src/pages/ShipmentDetail.tsx` line ~104: `function ScrapeStatusIcon` - `frontend/src/pages/Settings.tsx` line ~401: `function SettingsScrapeStatusIcon` Both switch on the same status values (`success`, `no_change`, `error`, `timeout`, `disabled`) and return the same icons. If a new status is added, both must be updated in sync. One will inevitably drift. ## Implementation Create a new shared component file: `frontend/src/components/ScrapeStatusIcon.tsx`: ```tsx export function ScrapeStatusIcon({ status }: { status: string }) { switch (status) { case "success": return <span className="text-emerald-600" title="Success">✓</span> case "no_change": return <span className="text-muted-foreground" title="No change">—</span> case "error": return <span className="text-red-600" title="Error">✗</span> case "timeout": return <span className="text-amber-600" title="Timeout">⏱</span> case "disabled": return <span className="text-red-600" title="Disabled">⛔</span> default: return <span className="text-muted-foreground">?</span> } } ``` Then in both `ShipmentDetail.tsx` and `Settings.tsx`: - Remove the local `ScrapeStatusIcon` / `SettingsScrapeStatusIcon` function definitions - Import: `import { ScrapeStatusIcon } from "@/components/ScrapeStatusIcon"` - Update all usages to `<ScrapeStatusIcon status={...} />` ## Acceptance criteria - `ScrapeStatusIcon` is defined once in `frontend/src/components/ScrapeStatusIcon.tsx` - Both `ShipmentDetail.tsx` and `Settings.tsx` import and use the shared component - No local duplicate definitions remain ## Brand identity alignment Sync/scrape status is a recurring data-transparency signal. A shared component ensures consistent semantic color, iconography, labels, and accessibility across Detail and Settings. ## Brand-compliant implementation notes - Prefer lucide line icons (`CheckCircle2`, `MinusCircle`, `AlertTriangle`, `Clock`, `CircleOff`, `HelpCircle`) over mixed text emoji symbols. - Pair icons with `title`/`aria-label` so status is not color-only. - Use semantic colors from the brand brief: green for success, amber for timeout/no fresh data, red for errors, gray for disabled/no change. - Keep default icon size consistent with the rest of the UI (`h-4 w-4`). ## Additional acceptance criteria - The shared component centralizes status labels and semantic colors. - Both Settings and Detail use the same status language and icon treatment. - The component remains compact enough for tables and log rows. --- Migrated from GitHub issue #26: https://github.com/bullitt186/trackbox/issues/26 Original author: @bullitt186 Original created: 2026-06-27T13:26:10Z Original labels: ux
bullitt changed title from Global: Extract duplicated ScrapeStatusIcon into a shared component to Global: Extract ScrapeStatusIcon into a brand-consistent shared status component 2026-06-27 15:46:22 +02:00
Author
Owner

Implemented in commit bd6b0e7. Extracted ScrapeStatusIcon into src/components/ScrapeStatusIcon.tsx using lucide icons (CheckCircle2, MinusCircle, AlertTriangle, Clock, Ban) with semantic colors and title attributes via wrapper spans. Both ShipmentDetail.tsx and Settings.tsx now import the shared component. Local duplicates (ScrapeStatusIcon in ShipmentDetail and SettingsScrapeStatusIcon in Settings) have been removed.

Implemented in commit bd6b0e7. Extracted `ScrapeStatusIcon` into `src/components/ScrapeStatusIcon.tsx` using lucide icons (CheckCircle2, MinusCircle, AlertTriangle, Clock, Ban) with semantic colors and `title` attributes via wrapper spans. Both `ShipmentDetail.tsx` and `Settings.tsx` now import the shared component. Local duplicates (`ScrapeStatusIcon` in ShipmentDetail and `SettingsScrapeStatusIcon` in Settings) have been removed.
Sign in to join this conversation.
No labels
arch
harness
security
ux
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bullitt/trackbox#47
No description provided.