Footer Meshkee credit widget, fix carousel title row alignment/action button
- Footer bottom-right credit link now matches the badge used on other Meshkee storefronts (reference: safeteb.com) — logo + two-line label inside an animated corner-drawing border on hover, linking to https://meshkee.com. Added the shared credit-widget logo asset (public/images/meshkee-logo-white.png). - SectionTitle: title/action row uses items-center instead of items-end (was visibly offset once a carousel title could wrap or carry a caption); the action button ("مشاهده همه" etc.) is now styled like the site's other primary buttons (filled red, white text, rounded) instead of a plain text link. - Carousel English captions (SPECIAL SALE, TOP SELLING, FAVORITE SELL) moved back from a below-title "enSubtitle" line to the existing inline enTitle treatment, matching every other section heading's convention on the site. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
ab1b07ff28
commit
7a78adc7f3
+34
-8
@@ -222,14 +222,17 @@ time the page renders, with zero code changes.
|
||||
|
||||
`SectionTitle`'s `enTitle` prop is optional for exactly this reason — these
|
||||
dynamic groups only have one `title` string from the API, not a Persian/
|
||||
English pair, so the inline English-caps subtitle just doesn't render for
|
||||
them. Instead, each carousel shows an English caption *under* the title
|
||||
(`SectionTitle`'s separate `enSubtitle` prop, `opacity-50`, its own line) —
|
||||
`StoreSpecialCarousels.englishLabelFromKey()` formats the group's `key`
|
||||
(e.g. `top-selling` → "TOP SELLING") rather than inventing a translation of
|
||||
`title`; there's no real localized-English field to translate from, and a
|
||||
made-up translation would be fabricated data. Skips rendering if the key
|
||||
has no letters at all (fell back to a bare numeric id).
|
||||
English pair. Each carousel still shows an English caption using that same
|
||||
`enTitle` slot (inline, beside the title — the same treatment as every
|
||||
other section heading on the site, e.g. BlogCarousel's "آخرین مطالب وبلاگ /
|
||||
LATEST BLOG"; there was a brief detour through a separate "below the title,
|
||||
opacity-50, own line" `enSubtitle` prop, which the user then asked to match
|
||||
the existing inline convention instead — don't reintroduce that below-title
|
||||
variant). `StoreSpecialCarousels.englishLabelFromKey()` formats the group's
|
||||
`key` (e.g. `top-selling` → "TOP SELLING") rather than inventing a
|
||||
translation of `title`; there's no real localized-English field to
|
||||
translate from, and a made-up translation would be fabricated data. Skips
|
||||
rendering if the key has no letters at all (fell back to a bare numeric id).
|
||||
|
||||
**Banner interleaving**: the two static-image banner sections (`TwoBanners`,
|
||||
`ThreeBanners`) are rendered *inside* `StoreSpecialCarousels`, one inserted
|
||||
@@ -238,6 +241,14 @@ cycling through the two if there end up being more than two carousels. Don't
|
||||
move them back out to `page.tsx` as fixed-position siblings — that only
|
||||
works for a known, fixed carousel count, which this deliberately isn't.
|
||||
|
||||
`SectionTitle`'s title/action row uses `items-center` (not `items-end`) —
|
||||
needed once carousel titles could carry more content (the inline `enTitle`
|
||||
caption) than a single line, so bottom-aligning the row left the action
|
||||
button visibly offset from the title block. The `action` button itself is
|
||||
styled like the site's other primary buttons (filled `bg-red`, white text,
|
||||
`rounded-lg` — the same look as `ProductCard`'s "افزودن به سبد"), not a
|
||||
plain text link.
|
||||
|
||||
**"مشاهده همه" (view all)**: each carousel's action button links to
|
||||
`/products?specialId={group.id}`. `store-specials` groups are admin-curated,
|
||||
already-complete lists (the endpoint has no pagination) — there's no
|
||||
@@ -263,6 +274,21 @@ render a `<link rel="icon">` and browsers aren't guaranteed to prefer the
|
||||
second one, so keeping both was silently serving the stale static icon.
|
||||
Don't add `app/favicon.ico` (or `public/favicon.ico`) back.
|
||||
|
||||
## Footer: Meshkee credit widget
|
||||
|
||||
The footer's bottom-right link ("Designed And Developed By Meshkee
|
||||
E-Commerce Team" → `https://meshkee.com`) intentionally matches the credit
|
||||
badge Meshkee's own storefronts use elsewhere (reference: safeteb.com) —
|
||||
same markup shape (frame + logo + two-line label), same animated corner
|
||||
border (four 1px lines that draw in on hover, staggered L→B→R→T, and
|
||||
un-draw in reverse on mouse-leave via matching `transition-delay`s on the
|
||||
resting state). `public/images/meshkee-logo-white.png` is that reference
|
||||
site's own logo asset, pulled down and committed here since it's the
|
||||
platform's shared credit-widget logo, not something unique to safeteb.com.
|
||||
If this ever needs to change, re-derive the exact hover-timing values from
|
||||
a live Meshkee site rather than guessing new ones — the staggered reverse
|
||||
un-draw is the distinctive part, not just "a border that appears."
|
||||
|
||||
## Route map
|
||||
|
||||
| Route | Notes |
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
@@ -116,10 +116,30 @@ export function Footer({
|
||||
<a
|
||||
href="https://meshkee.com"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="font-display tracking-wide text-white/50 uppercase transition-colors hover:text-white"
|
||||
rel="noopener noreferrer"
|
||||
dir="ltr"
|
||||
className="group relative inline-flex items-center gap-2.5 px-2.5 py-1.5 text-[#9c9c9c] transition-colors duration-300 hover:text-[#e0e0e0]"
|
||||
>
|
||||
Powered by meshkee.com
|
||||
<span className="pointer-events-none absolute inset-0" aria-hidden="true">
|
||||
<span className="absolute top-0 left-0 h-full w-px origin-top scale-y-0 bg-[#777] transition-transform duration-[280ms] delay-[420ms] group-hover:scale-y-100 group-hover:delay-0" />
|
||||
<span className="absolute bottom-0 left-0 h-px w-full origin-left scale-x-0 bg-[#777] transition-transform duration-[280ms] delay-[280ms] group-hover:scale-x-100 group-hover:delay-[140ms]" />
|
||||
<span className="absolute top-0 right-0 h-full w-px origin-bottom scale-y-0 bg-[#777] transition-transform duration-[280ms] delay-[140ms] group-hover:scale-y-100 group-hover:delay-[280ms]" />
|
||||
<span className="absolute top-0 left-0 h-px w-full origin-right scale-x-0 bg-[#777] transition-transform duration-[280ms] delay-0 group-hover:scale-x-100 group-hover:delay-[420ms]" />
|
||||
</span>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/images/meshkee-logo-white.png"
|
||||
alt="Meshkee"
|
||||
width={42}
|
||||
height={42}
|
||||
className="relative block h-[42px] w-auto shrink-0 object-contain opacity-70 transition-opacity duration-300 group-hover:opacity-100"
|
||||
/>
|
||||
<span className="relative flex min-h-[42px] flex-col justify-center leading-[1.25]">
|
||||
<span className="text-[11px]">Designed And Developed By</span>
|
||||
<span className="text-[13px] font-semibold text-[#cfcfcf] transition-colors duration-300 group-hover:text-white">
|
||||
Meshkee E-Commerce Team
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,8 +11,9 @@ import { productHref, type ProductGroup, type StaticImageWithUrl } from "@/lib/m
|
||||
// localized English field to pull a real translation from, and inventing
|
||||
// one would be fabricated data. `key` is real data and usually a readable
|
||||
// English slug (e.g. "top-selling"), so it's what gets formatted into the
|
||||
// English caption under the title. Skip it if the key has no letters at
|
||||
// all (e.g. it fell back to a bare numeric id).
|
||||
// English caption beside the title (same inline treatment as every other
|
||||
// section heading on the site, e.g. BlogCarousel's "LATEST BLOG"). Skip it
|
||||
// if the key has no letters at all (e.g. it fell back to a bare numeric id).
|
||||
function englishLabelFromKey(key: string): string | undefined {
|
||||
const label = key.replace(/[-_]+/g, " ").trim();
|
||||
return /[a-zA-Z]/.test(label) ? label.toUpperCase() : undefined;
|
||||
@@ -58,7 +59,7 @@ export function StoreSpecialCarousels({
|
||||
<div className="mx-auto max-w-7xl px-4">
|
||||
<SectionTitle
|
||||
title={group.title}
|
||||
enSubtitle={englishLabelFromKey(group.key)}
|
||||
enTitle={englishLabelFromKey(group.key)}
|
||||
action="مشاهده همه"
|
||||
actionHref={`/products?specialId=${group.id}`}
|
||||
/>
|
||||
|
||||
@@ -1,24 +1,14 @@
|
||||
type SectionTitleProps = {
|
||||
title: string;
|
||||
enTitle?: string;
|
||||
// Shown on its own line under the title (not inline like enTitle), at 50%
|
||||
// opacity — used for the homepage's dynamic store-specials carousels.
|
||||
enSubtitle?: string;
|
||||
subtitle?: string;
|
||||
action?: string;
|
||||
actionHref?: string;
|
||||
};
|
||||
|
||||
export function SectionTitle({
|
||||
title,
|
||||
enTitle,
|
||||
enSubtitle,
|
||||
subtitle,
|
||||
action,
|
||||
actionHref,
|
||||
}: SectionTitleProps) {
|
||||
export function SectionTitle({ title, enTitle, subtitle, action, actionHref }: SectionTitleProps) {
|
||||
return (
|
||||
<div className="mb-6 flex items-end justify-between gap-4">
|
||||
<div className="mb-6 flex items-center justify-between gap-4">
|
||||
<div>
|
||||
<div className="flex flex-wrap items-baseline gap-x-3 gap-y-1">
|
||||
<h2 className="text-xl font-bold text-red-dark md:text-2xl">{title}</h2>
|
||||
@@ -32,15 +22,6 @@ export function SectionTitle({
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{enSubtitle && (
|
||||
<p
|
||||
className="font-display mt-1 text-xs font-semibold tracking-wide text-foreground uppercase opacity-50 md:text-sm"
|
||||
lang="en"
|
||||
dir="ltr"
|
||||
>
|
||||
{enSubtitle}
|
||||
</p>
|
||||
)}
|
||||
{subtitle && (
|
||||
<p className="mt-1 text-sm text-muted">{subtitle}</p>
|
||||
)}
|
||||
@@ -48,7 +29,7 @@ export function SectionTitle({
|
||||
{action && actionHref && (
|
||||
<a
|
||||
href={actionHref}
|
||||
className="shrink-0 text-sm font-medium text-red transition-colors hover:text-red-dark"
|
||||
className="shrink-0 rounded-lg bg-red px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-red-dark"
|
||||
>
|
||||
{action} ←
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user