diff --git a/public/special-cake.png b/public/special-cake.png new file mode 100644 index 0000000..2d39363 Binary files /dev/null and b/public/special-cake.png differ diff --git a/src/components/CategoriesDock.css b/src/components/CategoriesDock.css index 8aae8e5..0629e22 100644 --- a/src/components/CategoriesDock.css +++ b/src/components/CategoriesDock.css @@ -1,4 +1,4 @@ -.categories-dock { +.categories-dock-stack { position: fixed; bottom: 18px; left: 0; @@ -6,6 +6,16 @@ z-index: 80; width: min(var(--max-container), calc(100vw - 48px)); margin-inline: auto; + display: flex; + flex-direction: column; + align-items: stretch; + gap: 10px; + pointer-events: none; +} + +.categories-dock { + position: relative; + width: 100%; padding: 14px 24px; border-radius: 28px; background: transparent; @@ -16,7 +26,8 @@ /* Glass layer without transform — backdrop-filter breaks when combined with transform / overflow-hidden ancestors in Chromium. */ -.categories-dock__glass { +.categories-dock__glass, +.categories-dock-cart__glass { position: absolute; inset: 0; z-index: 0; @@ -111,9 +122,107 @@ opacity: 0.75; } +/* Cart shortcut — same glass language, shorter row above the dock */ +.categories-dock-cart { + position: relative; + display: block; + width: 100%; + padding: 0; + border: none; + border-radius: 999px; + background: transparent; + cursor: pointer; + pointer-events: auto; + appearance: none; + font: inherit; + color: var(--color-primary); + transition: transform 0.2s ease; +} + +.categories-dock-cart:hover { + transform: translateY(-2px); +} + +.categories-dock-cart:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 3px; +} + +.categories-dock-cart__inner { + position: relative; + z-index: 1; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: 12px; + width: 100%; + padding: 10px 22px; +} + +.categories-dock-cart__icon { + position: relative; + flex-shrink: 0; + display: inline-flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + border-radius: 50%; + background: var(--color-primary); + color: #fff; +} + +.categories-dock-cart__badge { + position: absolute; + top: -4px; + left: -4px; + min-width: 22px; + height: 22px; + padding: 0 6px; + border-radius: 999px; + display: inline-flex; + align-items: center; + justify-content: center; + background: #fff; + color: var(--color-primary); + border: 1.5px solid var(--color-primary); + font-size: 12px; + font-weight: 700; + line-height: 1; +} + +.categories-dock-cart__label { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 2px; + text-align: start; +} + +.categories-dock-cart__name-fa { + font-size: 15px; + font-weight: 600; + line-height: 1.2; + color: var(--color-primary); +} + +.categories-dock-cart__name-en { + font-family: Cailyne, serif; + font-size: 12px; + font-weight: 300; + line-height: 1.2; + color: var(--color-secondary); + opacity: 0.75; +} + @media (max-width: 900px) { - .categories-dock { + .categories-dock-stack { width: calc(100vw - 24px); + gap: 8px; + } + + .categories-dock { padding: 12px 14px; } @@ -131,9 +240,13 @@ } @media (max-width: 640px) { - .categories-dock { + .categories-dock-stack { bottom: 10px; width: calc(100vw - 12px); + gap: 8px; + } + + .categories-dock { padding: 8px 8px; border-radius: 22px; } @@ -163,4 +276,29 @@ .categories-dock__name-en { display: none; } + + .categories-dock-cart { + width: 100%; + border-radius: 22px; + } + + .categories-dock-cart__inner { + width: 100%; + justify-content: center; + gap: 10px; + padding: 8px 14px; + } + + .categories-dock-cart__icon { + width: 40px; + height: 40px; + } + + .categories-dock-cart__name-fa { + font-size: 13px; + } + + .categories-dock-cart__name-en { + display: none; + } } diff --git a/src/components/CategoriesDock.tsx b/src/components/CategoriesDock.tsx index 4ebd3eb..f9a1e67 100644 --- a/src/components/CategoriesDock.tsx +++ b/src/components/CategoriesDock.tsx @@ -1,5 +1,12 @@ +import { useEffect, useState } from 'react' import { createPortal } from 'react-dom' import { Link } from 'react-router-dom' +import { ShoppingCart } from 'lucide-react' +import { + getCartCount, + openCartDrawer, + subscribeCart, +} from '../lib/cart' import './CategoriesDock.css' /** @@ -47,37 +54,79 @@ const DOCK_CATEGORIES = [ }, ] as const +const glassStyle = { + backdropFilter: 'blur(20px) saturate(170%)', + WebkitBackdropFilter: 'blur(20px) saturate(170%)', +} as const + export default function CategoriesDock() { + const [cartCount, setCartCount] = useState(() => getCartCount()) + + useEffect(() => subscribeCart(() => setCartCount(getCartCount())), []) + return createPortal( - , + + + سبد خرید + Cart + + + + )} + + + , document.body, ) } diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index a6e1e36..cc398d1 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -248,7 +248,7 @@ export default function HomePage() {
- کیک و شیرینی سفارشی + کیک و شیرینی سفارشی