diff --git a/components/ThemeProvider.tsx b/components/ThemeProvider.tsx index 6e5d461..6c15686 100644 --- a/components/ThemeProvider.tsx +++ b/components/ThemeProvider.tsx @@ -14,9 +14,8 @@ export type ThemeProps = { mutedForegroundColor?: string; borderColor?: string; radius?: "none" | "sm" | "md" | "lg" | "xl"; - buttonRadius?: "none" | "sm" | "md" | "lg" | "xl"; shadow?: "none" | "sm" | "md" | "lg" | "xl"; - maxWidth?: "sm" | "md" | "lg" | "xl" | "2xl" | "full"; + maxWidth?: "sm" | "md" | "lg" | "xl" | "full"; }; const radiusMap: Record, string> = { @@ -27,12 +26,12 @@ const radiusMap: Record, string> = { xl: "1rem", }; -const buttonRadiusMap: Record, string> = { - none: "0px", - sm: "0.25rem", - md: "0.5rem", - lg: "0.75rem", - xl: "1rem", +const maxWidthMap: Record, string> = { + sm: "64rem", + md: "72rem", + lg: "80rem", + xl: "96rem", + full: "100%", }; const shadowMap: Record, string> = { @@ -67,8 +66,8 @@ export function ThemeProvider({ mutedForegroundColor, borderColor, radius, - buttonRadius, shadow, + maxWidth, children, }: ThemeProps & { children?: React.ReactNode }) { // Recompute CSS-variable map only when a relevant prop changes. @@ -84,8 +83,8 @@ export function ThemeProvider({ if (mutedForegroundColor) vars["--muted-foreground"] = mutedForegroundColor; if (borderColor) vars["--border"] = borderColor; if (radius) vars["--radius"] = radiusMap[radius]; - if (buttonRadius) vars["--button-radius"] = buttonRadiusMap[buttonRadius]; if (shadow) vars["--shadow"] = shadowMap[shadow]; + if (maxWidth) vars["--container-max-width"] = maxWidthMap[maxWidth]; if (headerFont) vars["--font-header"] = `"${headerFont}", system-ui, sans-serif`; if (bodyFont) vars["--font-body"] = `"${bodyFont}", system-ui, sans-serif`; return vars; @@ -102,8 +101,8 @@ export function ThemeProvider({ mutedForegroundColor, borderColor, radius, - buttonRadius, shadow, + maxWidth, ]); // Imperatively push every CSS var onto :root inside the host document @@ -157,6 +156,12 @@ export function ThemeProvider({ @theme { --font-family-heading: var(--font-header), system-ui, -apple-system, sans-serif; --font-family-body: var(--font-body), system-ui, -apple-system, sans-serif; + --radius-sm: calc(var(--radius) * 0.5); + --radius-md: calc(var(--radius) * 0.75); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) * 1.5); + --radius-2xl: calc(var(--radius) * 2); + --radius-3xl: calc(var(--radius) * 3); } `; diff --git a/components/commerce/collection-grid.tsx b/components/commerce/collection-grid.tsx index 08fdf52..41545de 100644 --- a/components/commerce/collection-grid.tsx +++ b/components/commerce/collection-grid.tsx @@ -3,6 +3,7 @@ import { Link } from "react-router"; import { shopifyFetch } from "@/services/shopify/client"; import { GET_COLLECTIONS_QUERY } from "@/graphql/collections"; import { Typography } from "@/components/Typography"; +import { Container } from "@/components/layout/Container"; export type CollectionGridProps = { tagline: string; @@ -45,7 +46,7 @@ export function CollectionGrid({ return (
-
+
{tagline ? (

@@ -110,7 +111,7 @@ export function CollectionGrid({ ))}

-
+
); } diff --git a/components/commerce/collection.tsx b/components/commerce/collection.tsx index 2051e64..a77a4f3 100644 --- a/components/commerce/collection.tsx +++ b/components/commerce/collection.tsx @@ -13,6 +13,7 @@ import { Skeleton } from '@/components/ui/skeleton'; import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@/components/ui/select'; import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger, SheetFooter } from '@/components/ui/sheet'; import { Button } from '@/components/ui/button'; +import { Container } from '@/components/layout/Container'; import { cn } from '@/lib/utils'; type FilterOption = { label: string }; @@ -425,7 +426,7 @@ export function CollectionView(props: CollectionProps) { if (!selected && !paramHandle) { return (
-
+
@@ -435,14 +436,14 @@ export function CollectionView(props: CollectionProps) { ))}
- +
); } return (
-
+ {/* Cover image */} {showCoverImage === 'yes' && collectionImage && (
@@ -545,7 +546,7 @@ export function CollectionView(props: CollectionProps) {
)} -
+
); } diff --git a/components/commerce/featured-product.tsx b/components/commerce/featured-product.tsx index e7c837c..04e8e3b 100644 --- a/components/commerce/featured-product.tsx +++ b/components/commerce/featured-product.tsx @@ -4,6 +4,7 @@ import { useProduct } from "@/hooks/use-shopify-products"; import { useShopifyCart } from "@/hooks/use-shopify-cart"; import { Typography } from "@/components/Typography"; import { Skeleton } from "@/components/ui/skeleton"; +import { Container } from "@/components/layout/Container"; import { cn } from "@/lib/utils"; export type FeaturedProductProps = { @@ -33,7 +34,7 @@ export function FeaturedProductView({ tone === "muted" ? "bg-muted/40" : "bg-background", )} > -
+
@@ -51,7 +52,7 @@ export function FeaturedProductView({
- + ); } @@ -75,7 +76,7 @@ export function FeaturedProductView({ : "bg-background py-20 md:py-28" } > -
+
{image ? (
- + ); } diff --git a/components/commerce/product-details.tsx b/components/commerce/product-details.tsx index f38f5cd..cd86384 100644 --- a/components/commerce/product-details.tsx +++ b/components/commerce/product-details.tsx @@ -7,6 +7,7 @@ import { Typography } from "@/components/Typography"; import { cn } from "@/lib/utils"; import { Skeleton } from "@/components/ui/skeleton"; import { Loader } from "@/components/ui/loader"; +import { Container } from "@/components/layout/Container"; export type ProductDetailsProps = { product: ShopifyProduct | null; @@ -31,7 +32,7 @@ export function ProductDetailsView({ product: selected }: ProductDetailsProps) { if (!handle || loading || !product) { return (
-
+
@@ -62,7 +63,7 @@ export function ProductDetailsView({ product: selected }: ProductDetailsProps) {
-
+
); } @@ -90,7 +91,7 @@ export function ProductDetailsView({ product: selected }: ProductDetailsProps) { return (
-
+
{main ? ( @@ -214,7 +215,7 @@ export function ProductDetailsView({ product: selected }: ProductDetailsProps) {
) : null}
-
+
); } diff --git a/components/commerce/products-carousel.tsx b/components/commerce/products-carousel.tsx index a2412d7..70f478a 100644 --- a/components/commerce/products-carousel.tsx +++ b/components/commerce/products-carousel.tsx @@ -12,6 +12,7 @@ import { CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; +import { Container } from "@/components/layout/Container"; export type ProductsCarouselProps = { collection: ShopifyCollection | null; @@ -71,7 +72,7 @@ export function ProductsCarousel({ return (
-
+
{tagline ? ( @@ -120,7 +121,7 @@ export function ProductsCarousel({ -
+
); } diff --git a/components/commerce/products-grid.tsx b/components/commerce/products-grid.tsx index f153f25..e90c775 100644 --- a/components/commerce/products-grid.tsx +++ b/components/commerce/products-grid.tsx @@ -5,6 +5,7 @@ import { getProducts } from "@/hooks/use-shopify-products"; import { getCollectionProducts } from "@/hooks/use-shopify-collections"; import { ProductCard } from "./product-card"; import { Typography } from "@/components/Typography"; +import { Container } from "@/components/layout/Container"; export type ProductsGridProps = { collection: ShopifyCollection | null; @@ -59,7 +60,7 @@ export function ProductsGrid({ return (
-
+
{tagline ? ( @@ -94,7 +95,7 @@ export function ProductsGrid({ )) : products.map((p) => )}
-
+
); } diff --git a/components/commerce/recommended-products.tsx b/components/commerce/recommended-products.tsx index bd51d0c..081c5c0 100644 --- a/components/commerce/recommended-products.tsx +++ b/components/commerce/recommended-products.tsx @@ -6,6 +6,7 @@ import { import { ProductCard } from "./product-card"; import { Typography } from "@/components/Typography"; import { Skeleton } from "@/components/ui/skeleton"; +import { Container } from "@/components/layout/Container"; export type RecommendedProductsProps = { product: ShopifyProduct | null; @@ -27,7 +28,7 @@ export function RecommendedProductsView({ if (!selected) { return (
-
+
{tagline ? : null} @@ -37,14 +38,14 @@ export function RecommendedProductsView({ ))}
-
+
); } return (
-
+
{tagline ? (

@@ -61,7 +62,7 @@ export function RecommendedProductsView({ )) : items.map((p: any) => )}

-
+
); } diff --git a/components/commerce/search-products.tsx b/components/commerce/search-products.tsx index b0c856b..042cd4f 100644 --- a/components/commerce/search-products.tsx +++ b/components/commerce/search-products.tsx @@ -8,6 +8,7 @@ import { Skeleton } from '@/components/ui/skeleton'; import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@/components/ui/select'; import { Button } from '@/components/ui/button'; import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger, SheetFooter } from '@/components/ui/sheet'; +import { Container } from '@/components/layout/Container'; import { cn } from '@/lib/utils'; type FilterOption = { label: string }; @@ -397,7 +398,7 @@ export function SearchProductsView(props: SearchProductsProps) { return (
-
+ {/* Page header */}
@@ -523,7 +524,7 @@ export function SearchProductsView(props: SearchProductsProps) {
)} -
+
); } diff --git a/components/features/features.tsx b/components/features/features.tsx index cd77adc..1bad0b3 100644 --- a/components/features/features.tsx +++ b/components/features/features.tsx @@ -1,4 +1,5 @@ import { Typography } from "@/components/Typography"; +import { Container } from "@/components/layout/Container"; export type FeaturesProps = { tagline: string; @@ -17,7 +18,7 @@ const colClass: Record = { export function Features({ tagline, heading, subheading, columns, items }: FeaturesProps) { return (
-
+
{tagline ? (

@@ -45,7 +46,7 @@ export function Features({ tagline, heading, subheading, columns, items }: Featu

))}
- +
); } diff --git a/components/footer/footer.tsx b/components/footer/footer.tsx index 016c84c..5ac98cb 100644 --- a/components/footer/footer.tsx +++ b/components/footer/footer.tsx @@ -1,6 +1,7 @@ import { useState } from "react"; import { Link } from "react-router"; import { Typography } from "@/components/Typography"; +import { Container } from "@/components/layout/Container"; export type FooterProps = { brand: string; @@ -45,7 +46,7 @@ export function Footer({ return (
-
+
@@ -123,7 +124,7 @@ export function Footer({ ))}
-
+
); } diff --git a/components/landing/image-gallery.tsx b/components/landing/image-gallery.tsx index ddf02b1..f1db197 100644 --- a/components/landing/image-gallery.tsx +++ b/components/landing/image-gallery.tsx @@ -1,5 +1,6 @@ import { cn } from "@/lib/utils"; import { Typography } from "@/components/Typography"; +import { Container } from "@/components/layout/Container"; export type ImageGalleryProps = { tagline: string; @@ -12,7 +13,7 @@ export type ImageGalleryProps = { export function ImageGallery({ tagline, heading, subheading, layout, items }: ImageGalleryProps) { return (
-
+ {(tagline || heading || subheading) && (
{tagline ? ( @@ -86,7 +87,7 @@ export function ImageGallery({ tagline, heading, subheading, layout, items }: Im ))}
)} -
+
); } diff --git a/components/landing/newsletter-cta.tsx b/components/landing/newsletter-cta.tsx index b372709..59b54da 100644 --- a/components/landing/newsletter-cta.tsx +++ b/components/landing/newsletter-cta.tsx @@ -1,6 +1,7 @@ import { useState } from "react"; import { cn } from "@/lib/utils"; import { Typography } from "@/components/Typography"; +import { Container } from "@/components/layout/Container"; export type EmailProvider = "none" | "mailchimp" | "klaviyo"; @@ -131,7 +132,7 @@ export function NewsletterCta({ if (layout === "split") { return (
-
+
{imageUrl ? ( @@ -165,7 +166,7 @@ export function NewsletterCta({
- +
); } diff --git a/components/layout/Container.tsx b/components/layout/Container.tsx new file mode 100644 index 0000000..2ece77a --- /dev/null +++ b/components/layout/Container.tsx @@ -0,0 +1,21 @@ +import * as React from "react"; +import { cn } from "@/lib/utils"; + +export type ContainerProps = React.HTMLAttributes & { + as?: React.ElementType; +}; + +export function Container({ + as: Comp = "div", + className, + style, + ...props +}: ContainerProps) { + return ( + + ); +} diff --git a/components/logos/logos.tsx b/components/logos/logos.tsx index f48120d..7f98105 100644 --- a/components/logos/logos.tsx +++ b/components/logos/logos.tsx @@ -1,3 +1,5 @@ +import { Container } from "@/components/layout/Container"; + export type LogosProps = { tagline: string; items: Array<{ src: string; alt: string }>; @@ -7,7 +9,7 @@ export type LogosProps = { export function Logos({ tagline, items, layout }: LogosProps) { return (
-
+ {tagline ? (

{tagline} @@ -38,7 +40,7 @@ export function Logos({ tagline, items, layout }: LogosProps) { ))}

)} - +
); } diff --git a/components/navigation/navigation.tsx b/components/navigation/navigation.tsx index 794b206..01cf28e 100644 --- a/components/navigation/navigation.tsx +++ b/components/navigation/navigation.tsx @@ -3,6 +3,7 @@ import { useState } from "react"; import { Link } from "react-router"; import { useShopifyCart } from "@/hooks/use-shopify-cart"; import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet"; +import { Container } from "@/components/layout/Container"; import { cn } from "@/lib/utils"; export type NavigationProps = { @@ -49,7 +50,7 @@ export function Navigation({ toneClass[tone], )} > -
+
- + diff --git a/components/ui/button.tsx b/components/ui/button.tsx index efed0d1..52e318e 100644 --- a/components/ui/button.tsx +++ b/components/ui/button.tsx @@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[var(--radius-button)] text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-ring", + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-ring", { variants: { variant: { diff --git a/config/root.tsx b/config/root.tsx index df67fe8..2bdcbac 100644 --- a/config/root.tsx +++ b/config/root.tsx @@ -32,9 +32,8 @@ export const Root: RootConfig<{ fgColor: "#0a0a0a", mutedColor: "#f5f5f5", radius: "md", - buttonRadius: "md", shadow: "sm", - maxWidth: "xl", + maxWidth: "lg", }, fields: { title: { label: "Page title", type: "text" }, @@ -59,17 +58,6 @@ export const Root: RootConfig<{ { label: "Extra large", value: "xl" }, ], }, - buttonRadius: { - label: "Button radius", - type: "select", - options: [ - { label: "None (square)", value: "none" }, - { label: "Small", value: "sm" }, - { label: "Medium", value: "md" }, - { label: "Large", value: "lg" }, - { label: "Extra large", value: "xl" }, - ], - }, shadow: { label: "Shadow", type: "select", @@ -89,7 +77,6 @@ export const Root: RootConfig<{ { label: "Medium", value: "md" }, { label: "Large", value: "lg" }, { label: "Extra large", value: "xl" }, - { label: "2X large", value: "2xl" }, { label: "Full bleed", value: "full" }, ], }, @@ -105,8 +92,8 @@ export const Root: RootConfig<{ fgColor, mutedColor, radius, - buttonRadius, shadow, + maxWidth, }) => { return ( {children} diff --git a/src/globals.css b/src/globals.css index fad2a86..0c1c589 100644 --- a/src/globals.css +++ b/src/globals.css @@ -32,7 +32,6 @@ --radius-md: calc(var(--radius) * 0.75); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) * 1.5); - --radius-button: var(--button-radius, var(--radius)); --animate-marquee: marquee var(--duration) infinite linear; --animate-marquee-vertical: marquee-vertical var(--duration) linear infinite;