mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
style(ui): use semantic tokens for mood and feedback indicators
Closes the v1.4.6 deferred polish item — feedback / mood / medication
status indicators now ask for *meaning* (success / warning / info)
instead of hard-coding `text-dracula-green` / `bg-dracula-orange/15`.
Adds three CSS aliases to `globals.css`:
--success → dracula-green (positive outcome)
--warning → dracula-orange (caution / attention)
--info → dracula-cyan (neutral informational)
Dark mode (Dracula): each alias resolves to the same hex as before, so
the visual is pixel-identical to v1.4.6 — what changes is the *intent*
of the class.
Light mode (Alucard): the raw Dracula greens and oranges fail AA
contrast on a white card. The new tokens get higher-contrast
counterparts (#14720a, #a34d14, #036a96) that match the existing
`--destructive` / `--chart-*` light-mode swap.
Migrated callers:
- `src/components/admin/feedback-inbox-section.tsx`:
- BUG category badge → `destructive` (semantic — bug *is* broken)
- "published to GitHub" badge → `success`
- `src/components/medications/medication-card.tsx`:
- in-window status → `success`
- very-overdue status → `warning`
- "late" intermediate stays on `dracula-yellow` (yellow doesn't
map to either semantic bucket — it's mid-warning)
- `src/components/settings/ai-section.tsx`:
- "ChatGPT connected" badge + success toast → `success`
- "Connection expired" badge + raw-data warning → `warning`
Charts (`src/components/charts/**`) untouched per
`feedback_charts_visual_identity.md`. Other dracula-token callsites in
settings/* (telegram, ntfy, web-push, account, about, test-connection)
are deferred to v1.5.1 — broader sweep, not in tonight's scope.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
788c8ad335
commit
569300eaca
4 files changed
+46
-10
No files matched your search
@@ -55,6 +55,20 @@
|
||||
--color-dracula-red: var(--dracula-red);
|
||||
--color-dracula-yellow: var(--dracula-yellow);
|
||||
--color-dracula-lavender: var(--dracula-lavender);
|
||||
|
||||
/*
|
||||
* Semantic feedback tokens — aliases over the Dracula palette so badges,
|
||||
* banners, and status pills can stop hard-coding `text-dracula-green` /
|
||||
* `bg-dracula-orange/15` and ask for the *meaning* instead. Each is a
|
||||
* straight alias of the existing colour at the time of introduction so
|
||||
* the visual stays pixel-identical to v1.4.6 — what changes is intent.
|
||||
* - success → dracula-green (positive outcome, e.g. published)
|
||||
* - warning → dracula-orange (caution / non-blocking attention)
|
||||
* - info → dracula-cyan (neutral informational note)
|
||||
*/
|
||||
--color-success: var(--success);
|
||||
--color-warning: var(--warning);
|
||||
--color-info: var(--info);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -78,6 +92,16 @@
|
||||
--dracula-yellow: #f1fa8c;
|
||||
--dracula-lavender: #d6acff;
|
||||
|
||||
/*
|
||||
* Semantic feedback tokens (see @theme `--color-success` / `--color-warning`
|
||||
* / `--color-info` re-exports). Aliased over the Dracula palette so existing
|
||||
* dark-mode visuals stay identical; light mode (Alucard) below provides the
|
||||
* higher-contrast counterpart so AA contrast lands on the white card.
|
||||
*/
|
||||
--success: var(--dracula-green);
|
||||
--warning: var(--dracula-orange);
|
||||
--info: var(--dracula-cyan);
|
||||
|
||||
--radius: 0.625rem;
|
||||
}
|
||||
|
||||
@@ -135,6 +159,14 @@
|
||||
--accent: #dcdeef;
|
||||
--accent-foreground: #1f1f1f;
|
||||
--destructive: #cb3a2a;
|
||||
/*
|
||||
* Alucard light-mode overrides for the semantic tokens — straight Dracula
|
||||
* green/orange/cyan would fail AA contrast on a white card. These match the
|
||||
* darker palette already used for `--destructive`/`--chart-*` in light mode.
|
||||
*/
|
||||
--success: #14720a;
|
||||
--warning: #a34d14;
|
||||
--info: #036a96;
|
||||
--border: #cfcfde;
|
||||
--input: #cfcfde;
|
||||
--ring: #644ac9;
|
||||
|
||||
@@ -206,7 +206,11 @@ function FeedbackCategoryBadge({
|
||||
> = {
|
||||
BUG: {
|
||||
label: t("admin.feedback.categoryBug"),
|
||||
className: "bg-dracula-red/15 text-dracula-red border-dracula-red/30",
|
||||
// Bug = something that's broken → semantic `destructive` token instead
|
||||
// of raw `dracula-red`. Visually identical in dark mode (both resolve
|
||||
// to #ff5555); light mode now picks up the AA-contrast `#cb3a2a`.
|
||||
className:
|
||||
"bg-destructive/15 text-destructive border-destructive/30",
|
||||
},
|
||||
FEATURE_REQUEST: {
|
||||
label: t("admin.feedback.categoryFeature"),
|
||||
@@ -500,7 +504,7 @@ function FeedbackDetailDialog({
|
||||
</Button>
|
||||
)}
|
||||
{issueUrl && (
|
||||
<Badge className="border-dracula-green/30 bg-dracula-green/15 text-dracula-green ml-auto">
|
||||
<Badge className="border-success/30 bg-success/15 text-success ml-auto">
|
||||
{t("admin.feedback.publishedToGithub")}
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
@@ -416,10 +416,10 @@ export function MedicationCard({ medication, onEdit }: MedicationCardProps) {
|
||||
<span
|
||||
className={
|
||||
currentWindowStatus.status === "in_window"
|
||||
? "text-dracula-green font-medium"
|
||||
? "text-success font-medium"
|
||||
: currentWindowStatus.status === "late"
|
||||
? "text-dracula-yellow font-medium"
|
||||
: "text-dracula-orange font-medium"
|
||||
: "text-warning font-medium"
|
||||
}
|
||||
>
|
||||
{currentWindowStatus.status === "in_window"
|
||||
|
||||
@@ -334,7 +334,7 @@ function InsightsSettingsCard({
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{settings?.codexStatus === "connected" && (
|
||||
<Badge className="border-dracula-green/30 bg-dracula-green/15 text-dracula-green">
|
||||
<Badge className="border-success/30 bg-success/15 text-success">
|
||||
{t("settings.ai.chatgptConnectedBadge")}
|
||||
</Badge>
|
||||
)}
|
||||
@@ -344,7 +344,7 @@ function InsightsSettingsCard({
|
||||
</Badge>
|
||||
)}
|
||||
{settings?.codexStatus === "expired" && (
|
||||
<Badge className="border-dracula-orange/30 bg-dracula-orange/15 text-dracula-orange">
|
||||
<Badge className="border-warning/30 bg-warning/15 text-warning">
|
||||
{t("settings.ai.connectionExpiredBadge")}
|
||||
</Badge>
|
||||
)}
|
||||
@@ -493,7 +493,7 @@ function InsightsSettingsCard({
|
||||
{msg && (
|
||||
<p
|
||||
role="alert"
|
||||
className={`text-sm ${msgType === "success" ? "text-dracula-green" : "text-destructive"}`}
|
||||
className={`text-sm ${msgType === "success" ? "text-success" : "text-destructive"}`}
|
||||
>
|
||||
{msg}
|
||||
</p>
|
||||
@@ -518,7 +518,7 @@ function InsightsSettingsCard({
|
||||
</div>
|
||||
</div>
|
||||
{settings?.privacyMode === "raw" && (
|
||||
<div className="bg-dracula-orange/15 text-dracula-orange mt-2 rounded-lg p-2 text-xs">
|
||||
<div className="bg-warning/15 text-warning mt-2 rounded-lg p-2 text-xs">
|
||||
{t("settings.rawDataWarning")}
|
||||
</div>
|
||||
)}
|
||||
@@ -958,7 +958,7 @@ function UserAIProviderSubsection() {
|
||||
{saveMsg && (
|
||||
<p
|
||||
className={`mt-2 text-xs ${
|
||||
saveOk ? "text-dracula-green" : "text-destructive"
|
||||
saveOk ? "text-success" : "text-destructive"
|
||||
}`}
|
||||
>
|
||||
{saveMsg}
|
||||
@@ -967,7 +967,7 @@ function UserAIProviderSubsection() {
|
||||
{testMsg && (
|
||||
<p
|
||||
className={`mt-2 text-xs ${
|
||||
testOk ? "text-dracula-green" : "text-destructive"
|
||||
testOk ? "text-success" : "text-destructive"
|
||||
}`}
|
||||
>
|
||||
{testMsg}
|
||||
|
||||
Reference in new issue
Block a user