This commit is contained in:
amirhosein.ashourloo
2026-08-20 09:29:01 +03:30
parent 5f9ab22fd0
commit 82e73c47cf
9 changed files with 73 additions and 57 deletions
+45 -13
View File
@@ -39,20 +39,26 @@
--container-boxed: 1320px;
}
body {
background: var(--background);
color: var(--color-body);
font-family: var(--font-fa), Tahoma, sans-serif;
font-weight: 300;
}
/* Base element defaults belong in Tailwind's base layer so utility
classes (text-white, font-bold, etc.) can always override them —
unlayered CSS beats utilities regardless of specificity, which was
silently breaking text-color utilities on every heading. */
@layer base {
body {
background: var(--background);
color: var(--color-body);
font-family: var(--font-fa), Tahoma, sans-serif;
font-weight: 300;
}
h1,
h2,
h3,
h4,
h5,
h6 {
color: var(--color-ink);
h1,
h2,
h3,
h4,
h5,
h6 {
color: var(--color-ink);
}
}
.font-en {
@@ -98,6 +104,32 @@ h6 {
background: var(--color-gold) !important;
}
/* Fixed height bands on mobile/tablet (predictable layout, no odd
cropping); reverts to the slide's real aspect ratio on desktop where a
fixed height would look wrong on wide screens. */
.hero-slide-media {
height: 140px;
}
@media (min-width: 376px) {
.hero-slide-media {
height: 180px;
}
}
@media (min-width: 441px) {
.hero-slide-media {
height: 280px;
}
}
@media (min-width: 769px) {
.hero-slide-media {
height: auto;
aspect-ratio: var(--hero-aspect);
}
}
/* Minimal styling for CMS-authored HTML (product/blog descriptions) */
.rich-text p {
margin-bottom: 1em;
+1 -1
View File
@@ -28,7 +28,7 @@ export default async function RootLayout({ children }: LayoutProps<"/">) {
dir="rtl"
className={`${iranYekan.variable} ${rajdhani.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col bg-white text-ink">
<body className="min-h-full flex flex-col">
<Header categoryColumns={categoryColumns} />
{children}
<Footer categoryColumns={categoryColumns} />
+5 -5
View File
@@ -19,18 +19,18 @@ export default function Categories({ categoryColumns }: { categoryColumns: Categ
if (items.length === 0) return null;
return (
<section className="py-10 md:py-14">
<section className="pt-5 md:pt-7 pb-10 md:pb-14">
<div className="boxed">
<SectionHeading kicker="Categories" title="دسته‌بندی محصولات" />
<div className="bg-gold rounded-2xl md:rounded-3xl py-8 px-4 md:px-8">
<Swiper
spaceBetween={10}
slidesPerView={4}
slidesPerView={2}
breakpoints={{
480: { slidesPerView: 5 },
640: { slidesPerView: 6 },
1024: { slidesPerView: 9, spaceBetween: 14 },
768: { slidesPerView: 3 },
1024: { slidesPerView: 6, spaceBetween: 14 },
1280: { slidesPerView: 8, spaceBetween: 14 },
}}
>
{items.map((cat, i) => (
+1 -1
View File
@@ -11,7 +11,7 @@ export default function FullBanner({ slot }: { slot?: StaticImageSlot }) {
return (
<section className="boxed py-2 md:py-4">
<a href={href} className="block overflow-hidden rounded-lg border border-line">
<a href={href} className="block overflow-hidden rounded-2xl border border-line">
<img
src={src}
alt=""
+1 -1
View File
@@ -29,7 +29,7 @@ export default function Header({ categoryColumns }: { categoryColumns: CategoryN
const [mobileCategoriesOpen, setMobileCategoriesOpen] = useState(false);
return (
<header className="sticky top-0 z-50 bg-surface pt-2 md:pt-3 pb-0">
<header className="sticky top-0 z-50 pt-2 md:pt-3 pb-0">
<div className="boxed">
<div className="rounded-2xl shadow-sm border border-line/60">
{/* Row 1: logo / search / actions */}
+15 -33
View File
@@ -4,6 +4,7 @@ import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay, Pagination } from "swiper/modules";
import "swiper/css";
import "swiper/css/pagination";
import type { CSSProperties } from "react";
import type { StaticImageSlot } from "@/lib/types";
import { toCssAspectRatio } from "@/lib/format";
@@ -13,10 +14,12 @@ const fallbackSlides = [
"/images/hero/slide-3.svg",
];
const DEFAULT_ASPECT_RATIO = "32/9";
export default function HeroSlider({ slot }: { slot?: StaticImageSlot }) {
const slides = slot?.images ?? [];
const cssAspectRatio = toCssAspectRatio(slot?.aspectRatio);
const aspectStyle = cssAspectRatio ? { aspectRatio: cssAspectRatio } : undefined;
const cssAspectRatio = toCssAspectRatio(slot?.aspectRatio) ?? DEFAULT_ASPECT_RATIO;
const mediaStyle = { "--hero-aspect": cssAspectRatio } as CSSProperties;
return (
<section className="boxed pt-4 md:pt-6">
@@ -25,41 +28,20 @@ export default function HeroSlider({ slot }: { slot?: StaticImageSlot }) {
autoplay={{ delay: 4500, disableOnInteraction: false }}
pagination={{ clickable: true }}
loop
className="hero-swiper rounded-lg overflow-hidden"
className="hero-swiper rounded-2xl overflow-hidden border border-line"
>
{slides.length > 0
? slides.map((img) => (
<SwiperSlide key={img.id}>
{img.linkUrl ? (
<a href={img.linkUrl}>
<img
src={img.url}
alt=""
style={aspectStyle}
className={`w-full object-cover ${
aspectStyle ? "" : "aspect-[16/6] md:aspect-[32/9]"
}`}
/>
</a>
) : (
<img
src={img.url}
alt=""
style={aspectStyle}
className={`w-full object-cover ${
aspectStyle ? "" : "aspect-[16/6] md:aspect-[32/9]"
}`}
/>
)}
</SwiperSlide>
))
? slides.map((img) => {
const media = (
<img src={img.url} alt="" style={mediaStyle} className="hero-slide-media w-full object-cover" />
);
return (
<SwiperSlide key={img.id}>{img.linkUrl ? <a href={img.linkUrl}>{media}</a> : media}</SwiperSlide>
);
})
: fallbackSlides.map((src) => (
<SwiperSlide key={src}>
<img
src={src}
alt=""
className="w-full aspect-[16/6] md:aspect-[32/9] object-cover"
/>
<img src={src} alt="" style={mediaStyle} className="hero-slide-media w-full object-cover" />
</SwiperSlide>
))}
</Swiper>
+3 -1
View File
@@ -2,12 +2,14 @@ import Link from "next/link";
import { siteInfo } from "@/data/site";
export default function Logo({ dark = false }: { dark?: boolean }) {
const sizeClasses = dark ? "h-[72px] md:h-20" : "h-9 md:h-10";
return (
<Link href="/" className="flex items-center shrink-0" aria-label={siteInfo.name}>
<img
src="/images/logo.png"
alt={siteInfo.name}
className={`h-9 md:h-10 w-auto object-contain ${
className={`${sizeClasses} w-auto object-contain ${
dark ? "bg-white rounded-md px-2 py-1" : ""
}`}
/>
+1 -1
View File
@@ -25,7 +25,7 @@ export default function TwoBanners({ slot }: { slot?: StaticImageSlot }) {
<Wrapper
key={i}
{...(b.href ? { href: b.href } : {})}
className="group block overflow-hidden rounded-lg border border-line"
className="group block overflow-hidden rounded-2xl border border-line"
>
<img
src={b.image}
+1 -1
View File
@@ -14,7 +14,7 @@ export default function ProductCard({ product }: { product: ApiProduct }) {
className="group flex flex-col h-full bg-white border border-line rounded-lg overflow-hidden"
>
<div className="relative">
<img src={image} alt={title} className="w-full aspect-[4/5] object-cover" />
<img src={image} alt={title} className="w-full aspect-square object-cover" />
{store && !store.inStock && (
<span className="absolute inset-0 flex items-center justify-center bg-white/70">