Extract a shared Logo component for the header and footer

The header inlined its own logo/wordmark fallback markup. Pull it into
components/logo.tsx so the footer can show the same mark, and drop the
now-unneeded 'use client' from the root layout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUttSNLkLPvvR6Xf75QA1K
This commit is contained in:
Rami Bitar
2026-08-04 14:58:20 -04:00
co-authored by Claude Opus 5
parent b139b30273
commit ebdb0bee2f
4 changed files with 61 additions and 15 deletions
-2
View File
@@ -1,5 +1,3 @@
'use client';
import React from 'react'; import React from 'react';
import './globals.css'; import './globals.css';
import { Geist, Geist_Mono } from 'next/font/google'; import { Geist, Geist_Mono } from 'next/font/google';
+49
View File
@@ -0,0 +1,49 @@
import React from 'react';
import Link from 'next/link';
interface LogoProps {
/** Logo image URL. Falls back to the store name as a wordmark when absent. */
src?: string | null;
/** Wordmark text, and the image's alt text. */
storeName?: string;
/** Where the logo links to. Pass null to render it unwrapped. */
href?: string | null;
/** Sizing for the image — height only, so the aspect ratio is preserved. */
imageClassName?: string;
/** Sizing and weight for the wordmark fallback. */
textClassName?: string;
}
const Logo: React.FC<LogoProps> = ({
src,
storeName = 'Shop',
href = '/',
imageClassName = 'h-6',
textClassName = 'text-xl',
}) => {
const mark = src ? (
<img
src={src}
alt={storeName}
className={`w-auto object-contain ${imageClassName}`}
/>
) : (
<span
className={`font-medium tracking-tight text-foreground ${textClassName}`}
>
{storeName}
</span>
);
if (href === null) {
return <span className="flex items-center">{mark}</span>;
}
return (
<Link href={href} className="flex items-center">
{mark}
</Link>
);
};
export default Logo;
+10
View File
@@ -4,6 +4,7 @@ import {
RiTiktokLine, RiTiktokLine,
RiFacebookFill, RiFacebookFill,
} from '@remixicon/react'; } from '@remixicon/react';
import Logo from '@/components/logo';
export interface FooterLink { export interface FooterLink {
label: string; label: string;
@@ -12,6 +13,7 @@ export interface FooterLink {
interface FooterProps { interface FooterProps {
storeName?: string; storeName?: string;
logoUrl?: string;
copyright?: string; copyright?: string;
links?: FooterLink[]; links?: FooterLink[];
instagramUrl?: string; instagramUrl?: string;
@@ -21,6 +23,7 @@ interface FooterProps {
const Footer: React.FC<FooterProps> = ({ const Footer: React.FC<FooterProps> = ({
storeName = 'Shop', storeName = 'Shop',
logoUrl,
copyright, copyright,
links = [ links = [
{ label: 'Terms of Service', url: '/policies/terms-of-service' }, { label: 'Terms of Service', url: '/policies/terms-of-service' },
@@ -46,6 +49,13 @@ const Footer: React.FC<FooterProps> = ({
assistant launcher. Links and socials sit on separate rows so the assistant launcher. Links and socials sit on separate rows so the
icons aren't crammed onto the end of the link list. */} icons aren't crammed onto the end of the link list. */}
<div className="flex flex-col items-center gap-y-5 sm:items-start"> <div className="flex flex-col items-center gap-y-5 sm:items-start">
<Logo
src={logoUrl}
storeName={storeName}
imageClassName="h-5"
textClassName="text-base"
/>
<nav className="flex flex-wrap items-center justify-center gap-x-5 gap-y-2 sm:justify-start"> <nav className="flex flex-wrap items-center justify-center gap-x-5 gap-y-2 sm:justify-start">
{links.map((link) => ( {links.map((link) => (
<a <a
+2 -13
View File
@@ -8,6 +8,7 @@ import SearchDialog from '@/components/shopify/search-dialog';
import AccountMenu from '@/components/shopify/account-menu'; import AccountMenu from '@/components/shopify/account-menu';
import { RiShoppingBagLine, RiCloseLine, RiMenu3Line } from '@remixicon/react'; import { RiShoppingBagLine, RiCloseLine, RiMenu3Line } from '@remixicon/react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import Logo from '@/components/logo';
const CartIcon: React.FC = () => { const CartIcon: React.FC = () => {
const toggleCart = useCartStore((s) => s.toggleCart); const toggleCart = useCartStore((s) => s.toggleCart);
@@ -83,19 +84,7 @@ const Header: React.FC<HeaderProps> = ({
<div className="max-w-screen-2xl mx-auto px-8"> <div className="max-w-screen-2xl mx-auto px-8">
<div className="flex justify-between items-center h-14"> <div className="flex justify-between items-center h-14">
{/* Logo */} {/* Logo */}
<Link href="/" className="flex items-center"> <Logo src={logoUrl} storeName={storeName} />
{logoUrl ? (
<img
src={logoUrl}
alt={storeName}
className="h-6 w-auto object-contain"
/>
) : (
<span className="text-xl font-medium tracking-tight text-foreground">
{storeName}
</span>
)}
</Link>
{/* Desktop Navigation */} {/* Desktop Navigation */}
<div className="hidden md:flex items-center gap-x-8 text-sm"> <div className="hidden md:flex items-center gap-x-8 text-sm">