Skip to content

Commit d49bed8

Browse files
committed
fix(shop): drawer on shop routes, link everywhere else
Cart drawer only mounts inside ShopLayout (/shop/*). On non-shop routes the navbar cart button is now a Link to /shop/cart instead of a drawer trigger — the drawer doesn't exist there, so clicking did nothing.
1 parent 8d30dd1 commit d49bed8

3 files changed

Lines changed: 59 additions & 37 deletions

File tree

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,35 @@
1-
import { useLocation } from '@tanstack/react-router'
1+
import { Link, useLocation } from '@tanstack/react-router'
22
import { ShoppingCart } from 'lucide-react'
33
import { twMerge } from 'tailwind-merge'
44
import { useCart } from '~/hooks/useCart'
55
import { useCartDrawerStore } from '~/components/shop/cartDrawerStore'
66

7+
const badgeClasses = twMerge(
8+
'absolute -top-1 -right-1 min-w-[1.125rem] h-[1.125rem] px-1',
9+
'flex items-center justify-center rounded-full',
10+
'text-[0.65rem] font-bold leading-none',
11+
'bg-black text-white dark:bg-white dark:text-black',
12+
)
13+
14+
const buttonClasses = twMerge(
15+
'relative flex items-center justify-center',
16+
'h-9 w-9 rounded-lg transition-colors',
17+
'hover:bg-gray-500/10 text-gray-700 dark:text-gray-300',
18+
)
19+
720
/**
821
* Cart button in the main Navbar.
922
*
10-
* Visibility rules:
23+
* Behaviour:
24+
* • On /shop/* routes → opens the cart drawer (drawer is mounted in
25+
* ShopLayout, so it exists on these routes)
26+
* • Everywhere else → navigates to /shop/cart (no drawer mounted
27+
* outside the shop, and full navigation is the right UX anyway)
28+
*
29+
* Visibility:
1130
* • Always visible on /shop/* routes (even at zero items)
1231
* • Site-wide when the cart has at least one item
1332
* • Hidden elsewhere when the cart is empty
14-
*
15-
* Click opens the global CartDrawer — no navigation, so the user keeps
16-
* their place in the docs or blog while reviewing their cart.
1733
*/
1834
export function NavbarCartButton() {
1935
const { pathname } = useLocation()
@@ -23,30 +39,35 @@ export function NavbarCartButton() {
2339

2440
if (!onShopRoute && totalQuantity === 0) return null
2541

42+
const badge =
43+
totalQuantity > 0 ? (
44+
<span className={badgeClasses}>
45+
{totalQuantity > 99 ? '99+' : totalQuantity}
46+
</span>
47+
) : null
48+
49+
const label = totalQuantity > 0 ? `Cart (${totalQuantity} items)` : 'Cart'
50+
51+
// On shop routes: open the drawer (it's mounted in ShopLayout)
52+
if (onShopRoute) {
53+
return (
54+
<button
55+
type="button"
56+
onClick={openDrawer}
57+
aria-label={label}
58+
className={buttonClasses}
59+
>
60+
<ShoppingCart className="w-4 h-4" />
61+
{badge}
62+
</button>
63+
)
64+
}
65+
66+
// Everywhere else: navigate to the cart page
2667
return (
27-
<button
28-
type="button"
29-
onClick={openDrawer}
30-
aria-label={totalQuantity > 0 ? `Cart (${totalQuantity} items)` : 'Cart'}
31-
className={twMerge(
32-
'relative flex items-center justify-center',
33-
'h-9 w-9 rounded-lg transition-colors',
34-
'hover:bg-gray-500/10 text-gray-700 dark:text-gray-300',
35-
)}
36-
>
68+
<Link to="/shop/cart" aria-label={label} className={buttonClasses}>
3769
<ShoppingCart className="w-4 h-4" />
38-
{totalQuantity > 0 ? (
39-
<span
40-
className={twMerge(
41-
'absolute -top-1 -right-1 min-w-[1.125rem] h-[1.125rem] px-1',
42-
'flex items-center justify-center rounded-full',
43-
'text-[0.65rem] font-bold leading-none',
44-
'bg-black text-white dark:bg-white dark:text-black',
45-
)}
46-
>
47-
{totalQuantity > 99 ? '99+' : totalQuantity}
48-
</span>
49-
) : null}
50-
</button>
70+
{badge}
71+
</Link>
5172
)
5273
}

src/components/shop/ShopLayout.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
import { twMerge } from 'tailwind-merge'
1515
import { useLocalStorage } from '~/utils/useLocalStorage'
1616
import type { CollectionListItem } from '~/utils/shopify-queries'
17+
import { CartDrawer } from './CartDrawer'
18+
import { useCartDrawerStore } from './cartDrawerStore'
1719

1820
type ShopLayoutProps = {
1921
collections: Array<CollectionListItem>
@@ -148,10 +150,18 @@ export function ShopLayout({ collections, children }: ShopLayoutProps) {
148150
>
149151
{children}
150152
</main>
153+
154+
<ShopCartDrawer />
151155
</div>
152156
)
153157
}
154158

159+
function ShopCartDrawer() {
160+
const open = useCartDrawerStore((s) => s.open)
161+
const setOpen = useCartDrawerStore((s) => s.setOpen)
162+
return <CartDrawer open={open} onOpenChange={setOpen} />
163+
}
164+
155165
function ShopSidebarNav({
156166
collections,
157167
showLabels,

src/routes/__root.tsx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,6 @@ import { THEME_COLORS } from '~/utils/utils'
3939
import { useHubSpotChat } from '~/hooks/useHubSpotChat'
4040
import { trackPageView } from '~/utils/analytics'
4141
import { twMerge } from 'tailwind-merge'
42-
import { CartDrawer } from '~/components/shop/CartDrawer'
43-
import { useCartDrawerStore } from '~/components/shop/cartDrawerStore'
44-
45-
function GlobalCartDrawer() {
46-
const open = useCartDrawerStore((s) => s.open)
47-
const setOpen = useCartDrawerStore((s) => s.setOpen)
48-
return <CartDrawer open={open} onOpenChange={setOpen} />
49-
}
5042

5143
const GOOGLE_ANALYTICS_ID = 'G-JMT1Z50SPS'
5244
const GOOGLE_ANALYTICS_SCRIPT_SRC = `https://www.googletagmanager.com/gtag/js?id=${GOOGLE_ANALYTICS_ID}`
@@ -226,7 +218,6 @@ function ShellComponent({ children }: { children: React.ReactNode }) {
226218
<ToastProvider>
227219
<PageViewTracker />
228220
{hideNavbar ? children : <Navbar>{children}</Navbar>}
229-
<GlobalCartDrawer />
230221
{showDevtools && LazyAppDevtools ? (
231222
<React.Suspense fallback={null}>
232223
<LazyAppDevtools />

0 commit comments

Comments
 (0)