Consolidate theme radius/shadow props and make rounded utilities responsive
- Remove duplicate roundedness/shadowLevel props (keep radius/shadow) - Switch globals.css radius scale to proportional (square→pill works) - Replace rounded-full with rounded-md on theme-driven elements - Remove banner props from Navigation, drop publishing overlay Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,14 +13,12 @@ export type ThemeProps = {
|
||||
mutedColor?: string;
|
||||
mutedForegroundColor?: string;
|
||||
borderColor?: string;
|
||||
roundedness?: "none" | "sm" | "md" | "lg" | "xl" | "full";
|
||||
radius?: "none" | "xs" | "sm" | "md" | "lg";
|
||||
shadowLevel?: "none" | "sm" | "md" | "lg" | "xl";
|
||||
shadow?: "none" | "sm" | "md" | "lg";
|
||||
radius?: "none" | "sm" | "md" | "lg" | "xl" | "full";
|
||||
shadow?: "none" | "sm" | "md" | "lg" | "xl";
|
||||
maxWidth?: "sm" | "md" | "lg" | "xl" | "2xl" | "full";
|
||||
};
|
||||
|
||||
const radiusMap: Record<NonNullable<ThemeProps["roundedness"]>, string> = {
|
||||
const radiusMap: Record<NonNullable<ThemeProps["radius"]>, string> = {
|
||||
none: "0px",
|
||||
sm: "0.25rem",
|
||||
md: "0.5rem",
|
||||
@@ -29,15 +27,7 @@ const radiusMap: Record<NonNullable<ThemeProps["roundedness"]>, string> = {
|
||||
full: "9999px",
|
||||
};
|
||||
|
||||
const radiusEnumMap: Record<NonNullable<ThemeProps["radius"]>, string> = {
|
||||
none: "0px",
|
||||
xs: "0.125rem",
|
||||
sm: "0.25rem",
|
||||
md: "0.5rem",
|
||||
lg: "0.75rem",
|
||||
};
|
||||
|
||||
const shadowMap: Record<NonNullable<ThemeProps["shadowLevel"]>, string> = {
|
||||
const shadowMap: Record<NonNullable<ThemeProps["shadow"]>, string> = {
|
||||
none: "0 0 #0000",
|
||||
sm: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
|
||||
md: "0 4px 6px -1px rgb(0 0 0 / 0.10), 0 2px 4px -2px rgb(0 0 0 / 0.10)",
|
||||
@@ -45,13 +35,6 @@ const shadowMap: Record<NonNullable<ThemeProps["shadowLevel"]>, string> = {
|
||||
xl: "0 20px 25px -5px rgb(0 0 0 / 0.10), 0 8px 10px -6px rgb(0 0 0 / 0.10)",
|
||||
};
|
||||
|
||||
const shadowEnumMap: Record<NonNullable<ThemeProps["shadow"]>, string> = {
|
||||
none: "0 0 #0000",
|
||||
sm: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
|
||||
md: "0 4px 6px -1px rgb(0 0 0 / 0.10), 0 2px 4px -2px rgb(0 0 0 / 0.10)",
|
||||
lg: "0 10px 15px -3px rgb(0 0 0 / 0.10), 0 4px 6px -4px rgb(0 0 0 / 0.10)",
|
||||
};
|
||||
|
||||
function googleFontsHref(headerFont?: string, bodyFont?: string): string | null {
|
||||
const fonts = [headerFont, bodyFont].filter(
|
||||
(f): f is string => !!f && f !== "system-ui"
|
||||
@@ -75,9 +58,7 @@ export function ThemeProvider({
|
||||
mutedColor,
|
||||
mutedForegroundColor,
|
||||
borderColor,
|
||||
roundedness,
|
||||
radius,
|
||||
shadowLevel,
|
||||
shadow,
|
||||
children,
|
||||
}: ThemeProps & { children?: React.ReactNode }) {
|
||||
@@ -93,10 +74,8 @@ export function ThemeProvider({
|
||||
if (mutedColor) vars["--muted"] = mutedColor;
|
||||
if (mutedForegroundColor) vars["--muted-foreground"] = mutedForegroundColor;
|
||||
if (borderColor) vars["--border"] = borderColor;
|
||||
if (radius) vars["--radius"] = radiusEnumMap[radius];
|
||||
else if (roundedness) vars["--radius"] = radiusMap[roundedness];
|
||||
if (shadow) vars["--shadow"] = shadowEnumMap[shadow];
|
||||
else if (shadowLevel) vars["--shadow"] = shadowMap[shadowLevel];
|
||||
if (radius) vars["--radius"] = radiusMap[radius];
|
||||
if (shadow) vars["--shadow"] = shadowMap[shadow];
|
||||
if (headerFont) vars["--font-header"] = `"${headerFont}", system-ui, sans-serif`;
|
||||
if (bodyFont) vars["--font-body"] = `"${bodyFont}", system-ui, sans-serif`;
|
||||
return vars;
|
||||
@@ -112,9 +91,7 @@ export function ThemeProvider({
|
||||
mutedColor,
|
||||
mutedForegroundColor,
|
||||
borderColor,
|
||||
roundedness,
|
||||
radius,
|
||||
shadowLevel,
|
||||
shadow,
|
||||
]);
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ export function FeaturedProductView({
|
||||
<Skeleton className="h-4 w-4/6" />
|
||||
</div>
|
||||
<div className="mt-2 flex flex-wrap gap-3">
|
||||
<Skeleton className="h-11 w-32 rounded-full" />
|
||||
<Skeleton className="h-11 w-32 rounded-full" />
|
||||
<Skeleton className="h-11 w-32 rounded-md" />
|
||||
<Skeleton className="h-11 w-32 rounded-md" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,13 +111,13 @@ export function FeaturedProductView({
|
||||
await cart.addItem(variant.id, 1);
|
||||
cart.openCart();
|
||||
}}
|
||||
className="inline-flex items-center justify-center rounded-full bg-foreground px-6 py-3 text-sm font-medium tracking-wide text-background hover:opacity-90"
|
||||
className="inline-flex items-center justify-center rounded-md bg-foreground px-6 py-3 text-sm font-medium tracking-wide text-background hover:opacity-90"
|
||||
>
|
||||
{ctaLabel}
|
||||
</button>
|
||||
<Link
|
||||
to={`/products/${product.handle}`}
|
||||
className="inline-flex items-center justify-center rounded-full border border-foreground px-6 py-3 text-sm font-medium tracking-wide hover:opacity-80"
|
||||
className="inline-flex items-center justify-center rounded-md border border-foreground px-6 py-3 text-sm font-medium tracking-wide hover:opacity-80"
|
||||
>
|
||||
View details
|
||||
</Link>
|
||||
|
||||
@@ -46,14 +46,14 @@ export function ProductDetailsView({ product: selected }: ProductDetailsProps) {
|
||||
<div className="flex flex-col gap-3">
|
||||
<Skeleton className="h-3 w-16" />
|
||||
<div className="flex gap-2">
|
||||
<Skeleton className="h-10 w-16 rounded-full" />
|
||||
<Skeleton className="h-10 w-16 rounded-full" />
|
||||
<Skeleton className="h-10 w-16 rounded-full" />
|
||||
<Skeleton className="h-10 w-16 rounded-md" />
|
||||
<Skeleton className="h-10 w-16 rounded-md" />
|
||||
<Skeleton className="h-10 w-16 rounded-md" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 pt-2">
|
||||
<Skeleton className="h-11 w-32 rounded-full" />
|
||||
<Skeleton className="h-11 flex-1 rounded-full" />
|
||||
<Skeleton className="h-11 w-32 rounded-md" />
|
||||
<Skeleton className="h-11 flex-1 rounded-md" />
|
||||
</div>
|
||||
<div className="space-y-2 border-t border-border pt-6">
|
||||
<Skeleton className="h-3 w-20" />
|
||||
@@ -157,7 +157,7 @@ export function ProductDetailsView({ product: selected }: ProductDetailsProps) {
|
||||
key={val}
|
||||
onClick={() => matching && setVariant(matching.node)}
|
||||
className={cn(
|
||||
"min-w-12 rounded-full border px-4 py-2 text-sm transition-colors",
|
||||
"min-w-12 rounded-md border px-4 py-2 text-sm transition-colors",
|
||||
selected
|
||||
? "border-foreground bg-foreground text-background"
|
||||
: "border-border hover:border-foreground",
|
||||
@@ -172,7 +172,7 @@ export function ProductDetailsView({ product: selected }: ProductDetailsProps) {
|
||||
))}
|
||||
|
||||
<div className="flex items-center gap-4 pt-2">
|
||||
<div className="flex items-center gap-3 rounded-full border border-border px-4 py-2">
|
||||
<div className="flex items-center gap-3 rounded-md border border-border px-4 py-2">
|
||||
<button
|
||||
onClick={() => setQuantity((q) => Math.max(1, q - 1))}
|
||||
className="text-base hover:opacity-60"
|
||||
@@ -190,7 +190,7 @@ export function ProductDetailsView({ product: selected }: ProductDetailsProps) {
|
||||
<button
|
||||
onClick={onAdd}
|
||||
disabled={!variant || adding}
|
||||
className="flex-1 rounded-full bg-foreground px-6 py-3 text-sm font-medium tracking-wide text-background transition-opacity hover:opacity-90 disabled:opacity-50"
|
||||
className="flex-1 rounded-md bg-foreground px-6 py-3 text-sm font-medium tracking-wide text-background transition-opacity hover:opacity-90 disabled:opacity-50"
|
||||
>
|
||||
{adding ? (
|
||||
<span className="flex items-center justify-center gap-2">
|
||||
|
||||
@@ -63,7 +63,7 @@ export function CTA({
|
||||
{primaryCta?.label ? (
|
||||
<Link
|
||||
to={primaryCta.href || "#"}
|
||||
className="inline-flex items-center justify-center rounded-full bg-white px-6 py-3 text-sm font-medium tracking-wide text-black hover:opacity-90"
|
||||
className="inline-flex items-center justify-center rounded-md bg-white px-6 py-3 text-sm font-medium tracking-wide text-black hover:opacity-90"
|
||||
>
|
||||
{primaryCta.label}
|
||||
</Link>
|
||||
@@ -71,7 +71,7 @@ export function CTA({
|
||||
{secondaryCta?.label ? (
|
||||
<Link
|
||||
to={secondaryCta.href || "#"}
|
||||
className="inline-flex items-center justify-center rounded-full border border-white px-6 py-3 text-sm font-medium tracking-wide text-white hover:bg-white/10"
|
||||
className="inline-flex items-center justify-center rounded-md border border-white px-6 py-3 text-sm font-medium tracking-wide text-white hover:bg-white/10"
|
||||
>
|
||||
{secondaryCta.label}
|
||||
</Link>
|
||||
|
||||
@@ -97,7 +97,7 @@ export function Hero({
|
||||
<Link
|
||||
to={primaryCta.href || "#"}
|
||||
className={cn(
|
||||
"inline-flex items-center justify-center rounded-full px-6 py-3 text-sm font-medium tracking-wide transition-opacity hover:opacity-90",
|
||||
"inline-flex items-center justify-center rounded-md px-6 py-3 text-sm font-medium tracking-wide transition-opacity hover:opacity-90",
|
||||
isDark ? "bg-white text-black" : "bg-foreground text-background",
|
||||
)}
|
||||
>
|
||||
@@ -108,7 +108,7 @@ export function Hero({
|
||||
<Link
|
||||
to={secondaryCta.href || "#"}
|
||||
className={cn(
|
||||
"inline-flex items-center justify-center rounded-full border px-6 py-3 text-sm font-medium tracking-wide transition-opacity hover:opacity-80",
|
||||
"inline-flex items-center justify-center rounded-md border px-6 py-3 text-sm font-medium tracking-wide transition-opacity hover:opacity-80",
|
||||
isDark ? "border-white text-white" : "border-foreground text-foreground",
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -22,8 +22,6 @@ export const navigationEditor: ComponentConfig<NavigationProps> = {
|
||||
showCart: "yes",
|
||||
sticky: "yes",
|
||||
tone: "default",
|
||||
bannerText: "",
|
||||
bannerTone: "accent",
|
||||
},
|
||||
fields: {
|
||||
brand: { label: "Brand", type: "text", contentEditable: true },
|
||||
@@ -38,20 +36,6 @@ export const navigationEditor: ComponentConfig<NavigationProps> = {
|
||||
href: { label: "Link", type: "text" },
|
||||
},
|
||||
},
|
||||
bannerText: {
|
||||
label: "Banner text",
|
||||
type: "text",
|
||||
contentEditable: true,
|
||||
},
|
||||
bannerTone: {
|
||||
label: "Banner tone",
|
||||
type: "select",
|
||||
options: [
|
||||
{ label: "Default", value: "default" },
|
||||
{ label: "Accent", value: "accent" },
|
||||
{ label: "Inverse (dark)", value: "inverse" },
|
||||
],
|
||||
},
|
||||
showSearch: {
|
||||
label: "Search icon",
|
||||
type: "radio",
|
||||
|
||||
@@ -13,8 +13,6 @@ export type NavigationProps = {
|
||||
showCart: "yes" | "no";
|
||||
sticky: "yes" | "no";
|
||||
tone: "default" | "muted" | "inverse";
|
||||
bannerText: string;
|
||||
bannerTone: "default" | "accent" | "inverse";
|
||||
};
|
||||
|
||||
export function Navigation({
|
||||
@@ -25,8 +23,6 @@ export function Navigation({
|
||||
showCart,
|
||||
sticky,
|
||||
tone,
|
||||
bannerText,
|
||||
bannerTone,
|
||||
}: NavigationProps) {
|
||||
const [mobileOpen, setMobileOpen] = useState(false);
|
||||
const cart = useShopifyCart();
|
||||
@@ -38,14 +34,6 @@ export function Navigation({
|
||||
inverse: "bg-foreground text-background",
|
||||
};
|
||||
|
||||
const bannerToneClass: Record<NavigationProps["bannerTone"], string> = {
|
||||
default: "bg-muted text-foreground",
|
||||
accent: "bg-primary text-primary-foreground",
|
||||
inverse: "bg-foreground text-background",
|
||||
};
|
||||
|
||||
const hasBanner = typeof bannerText === "string" && bannerText.trim().length > 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
@@ -54,13 +42,6 @@ export function Navigation({
|
||||
sticky === "yes" && "sticky top-0 z-40",
|
||||
)}
|
||||
>
|
||||
{hasBanner && (
|
||||
<div className={cn("w-full", bannerToneClass[bannerTone])}>
|
||||
<div className="container mx-auto max-w-7xl px-6 py-2 text-center text-xs tracking-wide md:text-sm">
|
||||
{bannerText}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<header
|
||||
className={cn(
|
||||
"w-full",
|
||||
|
||||
Reference in New Issue
Block a user