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:
parent
b02c7a024b
commit
df5dd3a70e
56 changed files with 4749 additions and 788 deletions
61
utils/cx.ts
Normal file
61
utils/cx.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import { extendTailwindMerge } from "tailwind-merge";
|
||||
|
||||
/**
|
||||
* Text-style classes from styles/typography.css.
|
||||
*
|
||||
* IMPORTANT: every text-* utility we define via @theme (e.g. `text-body-medium`,
|
||||
* `text-title-1-semibold`) must be listed here. Otherwise tailwind-merge — which
|
||||
* has no view of our Tailwind theme — treats them as text-color utilities and
|
||||
* silently drops them when they appear in the same className as a real color
|
||||
* (`text-foreground-full`, `text-text-primary`, etc).
|
||||
*
|
||||
* If you add or rename a text style in typography.css, mirror the change here.
|
||||
*/
|
||||
const TEXT_FAMILIES = [
|
||||
"large-title",
|
||||
"display-1",
|
||||
"display-2",
|
||||
"display-3",
|
||||
"display-4",
|
||||
"title-1",
|
||||
"title-2",
|
||||
"title-3",
|
||||
"headline",
|
||||
"body",
|
||||
"body-2",
|
||||
"caption-1",
|
||||
"caption-2",
|
||||
] as const;
|
||||
|
||||
const TEXT_WEIGHTS = ["regular", "medium", "semibold", "bold"] as const;
|
||||
|
||||
const TEXT_STYLE_SUFFIXES = TEXT_FAMILIES.flatMap((family) =>
|
||||
TEXT_WEIGHTS.map((weight) => `${family}-${weight}`),
|
||||
);
|
||||
|
||||
const twMerge = extendTailwindMerge({
|
||||
extend: {
|
||||
classGroups: {
|
||||
"font-size": [{ text: TEXT_STYLE_SUFFIXES }],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Merge Tailwind classes safely. Last-write-wins on conflicting utilities.
|
||||
*/
|
||||
export const cx = twMerge;
|
||||
|
||||
/**
|
||||
* Identity helper that gives the Tailwind IntelliSense extension a hook for
|
||||
* sorting classes inside style objects (the extension doesn't sort inside
|
||||
* plain object literals otherwise).
|
||||
*/
|
||||
export function sortCx<
|
||||
T extends Record<
|
||||
string,
|
||||
string | number | Record<string, string | number | Record<string, string | number>>
|
||||
>,
|
||||
>(classes: T): T {
|
||||
return classes;
|
||||
}
|
||||
18
utils/directional-icon.ts
Normal file
18
utils/directional-icon.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import {
|
||||
RiArrowLeftLine,
|
||||
RiArrowLeftSLine,
|
||||
RiArrowRightLine,
|
||||
RiArrowRightSLine,
|
||||
RiSidebarFoldLine,
|
||||
RiSidebarUnfoldLine,
|
||||
} from "@remixicon/react";
|
||||
|
||||
/** Navigation glyphs mirror; logos, media controls and trend arrows do not. */
|
||||
const directionalIcons: ReadonlySet<unknown> = new Set([
|
||||
RiArrowLeftLine, RiArrowLeftSLine, RiArrowRightLine, RiArrowRightSLine,
|
||||
RiSidebarFoldLine, RiSidebarUnfoldLine,
|
||||
]);
|
||||
|
||||
export function directionalIconClass(icon: unknown): string | undefined {
|
||||
return directionalIcons.has(icon) ? "rtl:rotate-180" : undefined;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue