Fix
This commit is contained in:
@@ -39,6 +39,11 @@
|
|||||||
--container-boxed: 1320px;
|
--container-boxed: 1320px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 {
|
body {
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
color: var(--color-body);
|
color: var(--color-body);
|
||||||
@@ -54,6 +59,7 @@ h5,
|
|||||||
h6 {
|
h6 {
|
||||||
color: var(--color-ink);
|
color: var(--color-ink);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.font-en {
|
.font-en {
|
||||||
font-family: var(--font-en), sans-serif;
|
font-family: var(--font-en), sans-serif;
|
||||||
@@ -98,6 +104,32 @@ h6 {
|
|||||||
background: var(--color-gold) !important;
|
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) */
|
/* Minimal styling for CMS-authored HTML (product/blog descriptions) */
|
||||||
.rich-text p {
|
.rich-text p {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ export default async function RootLayout({ children }: LayoutProps<"/">) {
|
|||||||
dir="rtl"
|
dir="rtl"
|
||||||
className={`${iranYekan.variable} ${rajdhani.variable} h-full antialiased`}
|
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} />
|
<Header categoryColumns={categoryColumns} />
|
||||||
{children}
|
{children}
|
||||||
<Footer categoryColumns={categoryColumns} />
|
<Footer categoryColumns={categoryColumns} />
|
||||||
|
|||||||
@@ -19,18 +19,18 @@ export default function Categories({ categoryColumns }: { categoryColumns: Categ
|
|||||||
if (items.length === 0) return null;
|
if (items.length === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="py-10 md:py-14">
|
<section className="pt-5 md:pt-7 pb-10 md:pb-14">
|
||||||
<div className="boxed">
|
<div className="boxed">
|
||||||
<SectionHeading kicker="Categories" title="دستهبندی محصولات" />
|
<SectionHeading kicker="Categories" title="دستهبندی محصولات" />
|
||||||
|
|
||||||
<div className="bg-gold rounded-2xl md:rounded-3xl py-8 px-4 md:px-8">
|
<div className="bg-gold rounded-2xl md:rounded-3xl py-8 px-4 md:px-8">
|
||||||
<Swiper
|
<Swiper
|
||||||
spaceBetween={10}
|
spaceBetween={10}
|
||||||
slidesPerView={4}
|
slidesPerView={2}
|
||||||
breakpoints={{
|
breakpoints={{
|
||||||
480: { slidesPerView: 5 },
|
768: { slidesPerView: 3 },
|
||||||
640: { slidesPerView: 6 },
|
1024: { slidesPerView: 6, spaceBetween: 14 },
|
||||||
1024: { slidesPerView: 9, spaceBetween: 14 },
|
1280: { slidesPerView: 8, spaceBetween: 14 },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{items.map((cat, i) => (
|
{items.map((cat, i) => (
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default function FullBanner({ slot }: { slot?: StaticImageSlot }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="boxed py-2 md:py-4">
|
<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
|
<img
|
||||||
src={src}
|
src={src}
|
||||||
alt=""
|
alt=""
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default function Header({ categoryColumns }: { categoryColumns: CategoryN
|
|||||||
const [mobileCategoriesOpen, setMobileCategoriesOpen] = useState(false);
|
const [mobileCategoriesOpen, setMobileCategoriesOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
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="boxed">
|
||||||
<div className="rounded-2xl shadow-sm border border-line/60">
|
<div className="rounded-2xl shadow-sm border border-line/60">
|
||||||
{/* Row 1: logo / search / actions */}
|
{/* Row 1: logo / search / actions */}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Swiper, SwiperSlide } from "swiper/react";
|
|||||||
import { Autoplay, Pagination } from "swiper/modules";
|
import { Autoplay, Pagination } from "swiper/modules";
|
||||||
import "swiper/css";
|
import "swiper/css";
|
||||||
import "swiper/css/pagination";
|
import "swiper/css/pagination";
|
||||||
|
import type { CSSProperties } from "react";
|
||||||
import type { StaticImageSlot } from "@/lib/types";
|
import type { StaticImageSlot } from "@/lib/types";
|
||||||
import { toCssAspectRatio } from "@/lib/format";
|
import { toCssAspectRatio } from "@/lib/format";
|
||||||
|
|
||||||
@@ -13,10 +14,12 @@ const fallbackSlides = [
|
|||||||
"/images/hero/slide-3.svg",
|
"/images/hero/slide-3.svg",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const DEFAULT_ASPECT_RATIO = "32/9";
|
||||||
|
|
||||||
export default function HeroSlider({ slot }: { slot?: StaticImageSlot }) {
|
export default function HeroSlider({ slot }: { slot?: StaticImageSlot }) {
|
||||||
const slides = slot?.images ?? [];
|
const slides = slot?.images ?? [];
|
||||||
const cssAspectRatio = toCssAspectRatio(slot?.aspectRatio);
|
const cssAspectRatio = toCssAspectRatio(slot?.aspectRatio) ?? DEFAULT_ASPECT_RATIO;
|
||||||
const aspectStyle = cssAspectRatio ? { aspectRatio: cssAspectRatio } : undefined;
|
const mediaStyle = { "--hero-aspect": cssAspectRatio } as CSSProperties;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="boxed pt-4 md:pt-6">
|
<section className="boxed pt-4 md:pt-6">
|
||||||
@@ -25,41 +28,20 @@ export default function HeroSlider({ slot }: { slot?: StaticImageSlot }) {
|
|||||||
autoplay={{ delay: 4500, disableOnInteraction: false }}
|
autoplay={{ delay: 4500, disableOnInteraction: false }}
|
||||||
pagination={{ clickable: true }}
|
pagination={{ clickable: true }}
|
||||||
loop
|
loop
|
||||||
className="hero-swiper rounded-lg overflow-hidden"
|
className="hero-swiper rounded-2xl overflow-hidden border border-line"
|
||||||
>
|
>
|
||||||
{slides.length > 0
|
{slides.length > 0
|
||||||
? slides.map((img) => (
|
? slides.map((img) => {
|
||||||
<SwiperSlide key={img.id}>
|
const media = (
|
||||||
{img.linkUrl ? (
|
<img src={img.url} alt="" style={mediaStyle} className="hero-slide-media w-full object-cover" />
|
||||||
<a href={img.linkUrl}>
|
);
|
||||||
<img
|
return (
|
||||||
src={img.url}
|
<SwiperSlide key={img.id}>{img.linkUrl ? <a href={img.linkUrl}>{media}</a> : media}</SwiperSlide>
|
||||||
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>
|
|
||||||
))
|
|
||||||
: fallbackSlides.map((src) => (
|
: fallbackSlides.map((src) => (
|
||||||
<SwiperSlide key={src}>
|
<SwiperSlide key={src}>
|
||||||
<img
|
<img src={src} alt="" style={mediaStyle} className="hero-slide-media w-full object-cover" />
|
||||||
src={src}
|
|
||||||
alt=""
|
|
||||||
className="w-full aspect-[16/6] md:aspect-[32/9] object-cover"
|
|
||||||
/>
|
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
))}
|
))}
|
||||||
</Swiper>
|
</Swiper>
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ import Link from "next/link";
|
|||||||
import { siteInfo } from "@/data/site";
|
import { siteInfo } from "@/data/site";
|
||||||
|
|
||||||
export default function Logo({ dark = false }: { dark?: boolean }) {
|
export default function Logo({ dark = false }: { dark?: boolean }) {
|
||||||
|
const sizeClasses = dark ? "h-[72px] md:h-20" : "h-9 md:h-10";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href="/" className="flex items-center shrink-0" aria-label={siteInfo.name}>
|
<Link href="/" className="flex items-center shrink-0" aria-label={siteInfo.name}>
|
||||||
<img
|
<img
|
||||||
src="/images/logo.png"
|
src="/images/logo.png"
|
||||||
alt={siteInfo.name}
|
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" : ""
|
dark ? "bg-white rounded-md px-2 py-1" : ""
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default function TwoBanners({ slot }: { slot?: StaticImageSlot }) {
|
|||||||
<Wrapper
|
<Wrapper
|
||||||
key={i}
|
key={i}
|
||||||
{...(b.href ? { href: b.href } : {})}
|
{...(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
|
<img
|
||||||
src={b.image}
|
src={b.image}
|
||||||
|
|||||||
@@ -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"
|
className="group flex flex-col h-full bg-white border border-line rounded-lg overflow-hidden"
|
||||||
>
|
>
|
||||||
<div className="relative">
|
<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 && (
|
{store && !store.inStock && (
|
||||||
<span className="absolute inset-0 flex items-center justify-center bg-white/70">
|
<span className="absolute inset-0 flex items-center justify-center bg-white/70">
|
||||||
|
|||||||
Reference in New Issue
Block a user