Move UI to BoardUI with slate + salmon theme; add PDF plan export

- Adopt BoardUI (Pro init): theme tokens, Inter, .dark mode, Button,
  SegmentedControl, Meter, Skeleton and ThemeToggle; remap the app's
  color aliases onto BoardUI tokens and swap lucide for Remix icons
- Retint BoardUI's neutral ramp to cool slate with a salmon accent;
  drop the dotted background; raise muted text contrast
- Simplify the landing page and remove the overlap explorer
- Planner: explicit "I have this" toggle on grocery lines, pantry panel
  above the menu with the staples list spelled out, sticky aisle
  header fix, and a "Download PDF" plan export (jsPDF, lazy-loaded)
- Recipes: replace the family cabbage soup with Cade's Cabbage Soup
  (adds Bone-In Ham Steak to the catalog); remove Ham, Bean & Cabbage Soup
- Remove unused BoardUI components, dependencies and exports

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Cayden Schwechten 2026-11-06 16:36:33 -06:00
parent b02c7a024b
commit df5dd3a70e
56 changed files with 4749 additions and 788 deletions

View file

@ -0,0 +1,70 @@
"use client";
import type { ReactNode, Ref } from "react";
import { RiInformationFill } from "@remixicon/react";
import type { LabelProps as AriaLabelProps } from "react-aria-components";
import { Label as AriaLabel } from "react-aria-components";
import { cx } from "@/utils/cx";
/**
* Field label. Wraps `react-aria-components`' Label so the parent `TextField`
* automatically wires `htmlFor` / `aria-labelledby`.
*
* Visuals come from Figma:
* - Inter Medium 14/20, color text/primary
* - 2px gap between label + required asterisk + info icon
* - asterisk is text/error-primary (red/500)
* - info icon is 16×16 in foreground/icon/quaternary
*
* Pass `isRequired` to show the asterisk. Pass `tooltip` to show the info
* icon (currently a static glyph — when the Tooltip component lands it'll
* wire up here).
*/
export interface LabelProps extends AriaLabelProps {
children: ReactNode;
isRequired?: boolean;
/** Reserved for invalid-aware styling (asterisk color, etc.) once we need it. */
isInvalid?: boolean;
/** Show the info icon next to the label. */
tooltip?: boolean | string;
ref?: Ref<HTMLLabelElement>;
}
export function Label({
isRequired = false,
isInvalid: _isInvalid,
tooltip,
className,
children,
...props
}: LabelProps) {
void _isInvalid;
return (
<AriaLabel
data-label="true"
{...props}
className={cx(
"flex cursor-default items-center gap-0.5",
"text-body-medium text-text-primary",
className,
)}
>
{children}
{isRequired && (
<span
aria-hidden="true"
className="text-body-medium text-text-error-primary"
>
*
</span>
)}
{tooltip && (
<RiInformationFill
className="size-4 shrink-0 text-foreground-icon-quaternary"
aria-hidden
/>
)}
</AriaLabel>
);
}