Rebuild app IA and polish pantry, chips, and food data.
Introduce the four-tab hubs (Jetzt/Küche/Planen/Wissen), frosted ingredient flyouts with caution reasons, structured nutrition fields with protein sorting, and disabled coming-soon nav tiles. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -70,9 +70,7 @@ export function Accordion({
|
||||
"active:brightness-[0.98]",
|
||||
)}
|
||||
>
|
||||
{icon ? (
|
||||
<span className="shrink-0 text-xl leading-none">{icon}</span>
|
||||
) : null}
|
||||
{icon ? <span className="shrink-0 leading-none">{icon}</span> : null}
|
||||
<span className="type-title-sm min-w-0 flex-1 text-[var(--ink)]">
|
||||
{title}
|
||||
</span>
|
||||
|
||||
@@ -17,6 +17,7 @@ export interface BottomNavProps {
|
||||
|
||||
/**
|
||||
* Floating pill bottom navigation — float elevation above content cards.
|
||||
* Active state uses --ui-accent (non-semantic chrome), not category colors.
|
||||
*/
|
||||
export function BottomNav({ items, className }: BottomNavProps) {
|
||||
return (
|
||||
@@ -49,7 +50,7 @@ export function BottomNav({ items, className }: BottomNavProps) {
|
||||
className={cx(
|
||||
"text-xl leading-none [&_svg]:h-5 [&_svg]:w-5",
|
||||
item.active
|
||||
? "text-[var(--color-obstgem-dk)]"
|
||||
? "text-[var(--ui-accent)]"
|
||||
: "text-[var(--ink-soft)]",
|
||||
)}
|
||||
>
|
||||
@@ -59,14 +60,9 @@ export function BottomNav({ items, className }: BottomNavProps) {
|
||||
className={cx(
|
||||
"type-label normal-case tracking-wide",
|
||||
item.active
|
||||
? "bg-clip-text text-transparent"
|
||||
? "text-[var(--ui-accent)]"
|
||||
: "text-[var(--ink-soft)]",
|
||||
)}
|
||||
style={
|
||||
item.active
|
||||
? { backgroundImage: "var(--gradient-accent)" }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
|
||||
84
client/src/components/ui-pp/TimeIconBadge.tsx
Normal file
84
client/src/components/ui-pp/TimeIconBadge.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import type { LucideIcon } from "lucide-react"
|
||||
|
||||
import { cx } from "@/lib/cx"
|
||||
import {
|
||||
DAYLIGHT_GRADIENT,
|
||||
daylightIconPlate,
|
||||
daylightPeriodFromHour,
|
||||
daylightPeriodFromMealTime,
|
||||
mealTimeIcon,
|
||||
periodFallbackIcon,
|
||||
type DaylightPeriod,
|
||||
} from "@/lib/daylight"
|
||||
import type { MealTime } from "@/types/domain"
|
||||
|
||||
export type { DaylightPeriod }
|
||||
|
||||
export interface TimeIconBadgeProps {
|
||||
icon?: LucideIcon
|
||||
/** Explicit period wins over hour / mealTime. */
|
||||
period?: DaylightPeriod
|
||||
/**
|
||||
* Wall-clock hour for live “now” gradient.
|
||||
* When set (without `period`), drives the sky gradient — even if `mealTime` is set for the icon.
|
||||
*/
|
||||
hour?: number
|
||||
/** Section meal slot — drives icon; drives gradient only when `hour` is omitted. */
|
||||
mealTime?: MealTime
|
||||
className?: string
|
||||
"aria-hidden"?: boolean
|
||||
"aria-label"?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounded gradient badge for time-of-day / meal-section headers.
|
||||
* - Suggestion (now): pass `hour` + `mealTime` (sky from hour, icon from meal).
|
||||
* - Wochenplan sections: pass `mealTime` only (stable per section).
|
||||
*/
|
||||
export function TimeIconBadge({
|
||||
icon,
|
||||
period: periodProp,
|
||||
hour,
|
||||
mealTime,
|
||||
className,
|
||||
"aria-hidden": ariaHidden,
|
||||
"aria-label": ariaLabel,
|
||||
}: TimeIconBadgeProps) {
|
||||
const period: DaylightPeriod =
|
||||
periodProp ??
|
||||
(hour !== undefined
|
||||
? daylightPeriodFromHour(hour)
|
||||
: mealTime
|
||||
? daylightPeriodFromMealTime(mealTime)
|
||||
: daylightPeriodFromHour(new Date().getHours()))
|
||||
|
||||
const Icon =
|
||||
icon ?? (mealTime ? mealTimeIcon(mealTime) : periodFallbackIcon(period))
|
||||
|
||||
const { plate, icon: iconColor } = daylightIconPlate(period)
|
||||
|
||||
return (
|
||||
<span
|
||||
aria-hidden={ariaHidden}
|
||||
aria-label={ariaLabel}
|
||||
className={cx(
|
||||
"inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-[var(--radius-control)]",
|
||||
"shadow-[var(--shadow-resting)]",
|
||||
className,
|
||||
)}
|
||||
style={{ backgroundImage: DAYLIGHT_GRADIENT[period] }}
|
||||
>
|
||||
<span
|
||||
className="inline-flex h-7 w-7 items-center justify-center rounded-[10px]"
|
||||
style={{ background: plate }}
|
||||
>
|
||||
<Icon
|
||||
className="h-4 w-4"
|
||||
strokeWidth={2.4}
|
||||
color={iconColor}
|
||||
aria-hidden
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user