feat: replace P/F/C text labels with Lucide macro icons across fitness routes

Use Beef (protein), Droplet (fat), Wheat (carbs) icons consistently in
ring graphs, macro bars, food cards, detail rows, ingredient lists, and
stats page. Add labelIcon snippet prop to RingGraph/StatsRingGraph. Show
macro split legend always (was hidden on mobile) and group it with the
title in horizontal layout.
This commit is contained in:
2026-04-09 21:00:38 +02:00
parent 1e23ed02c2
commit f3f55f1cae
6 changed files with 108 additions and 67 deletions
@@ -1,6 +1,7 @@
<script>
import { detectFitnessLang } from '$lib/js/fitnessI18n';
import { page } from '$app/stores';
import { Beef, Droplet, Wheat } from '@lucide/svelte';
import RingGraph from './RingGraph.svelte';
/**
@@ -51,9 +52,9 @@
}
const macros = $derived([
{ pct: macroPercent.protein, label: isEn ? 'Protein' : 'Eiweiß', color: 'var(--nord14)', grams: protein },
{ pct: macroPercent.fat, label: isEn ? 'Fat' : 'Fett', color: 'var(--nord12)', grams: fat },
{ pct: macroPercent.carbs, label: isEn ? 'Carbs' : 'Kohlenh.', color: 'var(--nord9)', grams: carbs },
{ pct: macroPercent.protein, label: isEn ? 'Protein' : 'Eiweiß', color: 'var(--nord14)', grams: protein, icon: Beef },
{ pct: macroPercent.fat, label: isEn ? 'Fat' : 'Fett', color: 'var(--nord12)', grams: fat, icon: Droplet },
{ pct: macroPercent.carbs, label: isEn ? 'Carbs' : 'Kohlenh.', color: 'var(--nord9)', grams: carbs, icon: Wheat },
]);
</script>
@@ -67,23 +68,26 @@
<div class="mb-rings">
{#each macros as macro (macro.color)}
{@const MacroIcon = macro.icon}
<RingGraph
percent={macro.pct}
color={macro.color}
label={macro.label}
sublabel="{fmt(macro.grams)}g"
/>
>
{#snippet labelIcon()}<MacroIcon size={12} />{/snippet}
</RingGraph>
{/each}
</div>
{#if showDetailRows}
<div class="mb-rows">
<div class="mb-row">
<span>{isEn ? 'Protein' : 'Eiweiß'}</span>
<span class="mb-row-label"><Beef size={12} /> {isEn ? 'Protein' : 'Eiweiß'}</span>
<span>{fmt(protein)} g</span>
</div>
<div class="mb-row">
<span>{isEn ? 'Fat' : 'Fett'}</span>
<span class="mb-row-label"><Droplet size={12} /> {isEn ? 'Fat' : 'Fett'}</span>
<span>{fmt(fat)} g</span>
</div>
<div class="mb-row sub">
@@ -91,7 +95,7 @@
<span>{fmt(saturatedFat)} g</span>
</div>
<div class="mb-row">
<span>{isEn ? 'Carbohydrates' : 'Kohlenhydrate'}</span>
<span class="mb-row-label"><Wheat size={12} /> {isEn ? 'Carbohydrates' : 'Kohlenhydrate'}</span>
<span>{fmt(carbs)} g</span>
</div>
<div class="mb-row sub">
@@ -149,6 +153,11 @@
.mb-row:last-child {
border-bottom: none;
}
.mb-row-label {
display: flex;
align-items: center;
gap: 0.3rem;
}
.mb-row.sub span:first-child {
padding-left: 0.75rem;
color: var(--color-text-tertiary);
+7 -1
View File
@@ -18,6 +18,7 @@
* label?: string,
* sublabel?: string,
* extra?: import('svelte').Snippet,
* labelIcon?: import('svelte').Snippet,
* }}
*/
let {
@@ -26,6 +27,7 @@
label = '',
sublabel = '',
extra = undefined,
labelIcon = undefined,
} = $props();
</script>
@@ -43,7 +45,7 @@
<text class="ring-text" x="35" y="35">{percent}%</text>
</svg>
{#if label}
<span class="ring-label">{label}</span>
<span class="ring-label">{@render labelIcon?.()}{label}</span>
{/if}
{#if sublabel}
<span class="ring-sublabel">{sublabel}</span>
@@ -83,6 +85,10 @@
dominant-baseline: central;
}
.ring-label {
display: flex;
align-items: center;
justify-content: center;
gap: 0.2rem;
font-size: 0.78rem;
font-weight: 600;
color: var(--color-text-primary);
@@ -10,6 +10,7 @@
* sublabel?: string,
* target?: number,
* markerColor?: string,
* labelIcon?: import('svelte').Snippet,
* }}
*/
let {
@@ -19,6 +20,7 @@
sublabel = '',
target = undefined,
markerColor = 'var(--color-text-secondary)',
labelIcon = undefined,
} = $props();
/**
@@ -45,7 +47,7 @@
}
</script>
<RingGraph {percent} {color} {label} {sublabel}>
<RingGraph {percent} {color} {label} {sublabel} {labelIcon}>
{#snippet extra()}
{#if target != null}
{@const pos = targetMarkerPos(target)}