فوتر با اسمِ درشت
پیشنمایش تمامصفحهبخشِ فوترِ تیره: تیتر، عضویتِ خبرنامه، برند و سه ستونِ لینک، و اسمِ برند با گرادیانِ نقرهای که پایینِ کارت نیمهبریده مینشیند.
۱. نصب کامپوننتها
این بلاک از ۴ آیتم دیگ استفاده میکند: buttoncontrol-sizeiconsinput
پکیجمنیجر پیشفرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیجمنیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/input.jsonpnpm dlx digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/input.jsonyarn dlx digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/input.jsonbunx --bun digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/input.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
footer-wordmark.tsx
"use client"
import * as React from "react"
import { CheckCircleIcon, SparklesIcon } from "@/components/icons"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { Input } from "@/components/ui/input"
const COLUMNS = [
{ title: "محصول", links: ["چطور کار میکند", "تعرفه", "امنیت", "اپِ موبایل"] },
{ title: "یادگیری", links: ["مرکزِ راهنما", "وضعیتِ سرویس", "مستنداتِ API", "انجمن"] },
{ title: "شرکت", links: ["درباره ما", "فرصتهای شغلی", "حریمِ خصوصی", "مرکزِ اعتماد"] },
]
/**
* فوترِ پایانی با اسمِ درشتِ برند: کارتِ تیره با درخششِ سبزِ محو، تیترِ «رشدِ آنچه ساختهاید»،
* عضویتِ خبرنامهٔ ماهانه با دکمهٔ سبزِ روشن، برند و سه ستونِ لینک؛ اسمِ برند با گرادیانِ
* نقرهای پایینِ کارت نیمهبریده مینشیند. همیشه تیره است.
*/
export default function FooterWordmarkBlock() {
const [state, setState] = React.useState<"idle" | "error" | "done">("idle")
return (
<ControlSizeProvider size="xl" asChild>
<footer className="w-full bg-[var(--dig-graphite-950)] p-3 sm:p-6">
<div className="relative isolate mx-auto flex w-full max-w-6xl flex-col gap-12 overflow-hidden rounded-xl border border-[var(--dig-graphite-800)] bg-[radial-gradient(ellipse_at_50%_110%,var(--dig-green-800),var(--dig-graphite-950)_60%)] px-5 pt-10 text-[var(--dig-white)] sm:px-10 sm:pt-14">
<div className="grid grid-cols-1 gap-10 lg:grid-cols-[1fr_24rem]">
<div className="flex flex-col items-start gap-4">
<span className="flex items-center gap-2 rounded-full bg-[var(--dig-graphite-800)] px-3 py-1 text-xs font-semibold">
<span aria-hidden className="size-1.5 rounded-full bg-[var(--dig-green-300)]" />
شروعِ کار
</span>
<h2 className="text-3xl leading-snug font-black sm:text-4xl">
رشدِ آنچه <span className="text-[var(--dig-green-300)]">ساختهاید</span>
</h2>
<p className="text-[var(--dig-neutral-400)]">همهچیز در یک جا؛ و همهچیز همانطور که باید.</p>
</div>
<div className="flex flex-col gap-2">
<span className="font-bold">خلاصهٔ ماهانهٔ بازار</span>
{state === "done" ? (
<p role="status" className="flex items-center gap-2 text-[var(--dig-green-300)]">
<CheckCircleIcon aria-hidden className="size-5" />
عضو شدید؛ اولین شماره اولِ ماه میرسد.
</p>
) : (
<form
noValidate
onSubmit={(event) => {
event.preventDefault()
const email = String(new FormData(event.currentTarget).get("email"))
setState(/^\S+@\S+\.\S+$/.test(email) ? "done" : "error")
}}
className="flex gap-2"
>
<Input
name="email"
type="email"
dir="ltr"
aria-label="ایمیل"
placeholder="name@mail.com"
aria-invalid={state === "error"}
className="flex-1 border-[var(--dig-graphite-700)] bg-[var(--dig-graphite-900)] text-[var(--dig-white)] placeholder:text-[var(--dig-neutral-500)]"
/>
<Button type="submit" className="[--primary-foreground:var(--dig-graphite-950)] [--primary:var(--dig-green-300)] hover:[--primary:var(--dig-green-200)]">
عضویت
</Button>
</form>
)}
{state === "error" ? (
<p role="alert" className="text-sm text-[var(--dig-red-300)]">
ایمیل را کامل بنویسید.
</p>
) : (
<p className="text-xs text-[var(--dig-neutral-500)]">
با عضویت <a href="#" className="underline">حریمِ خصوصی</a> را میپذیرید.
</p>
)}
</div>
</div>
<div className="grid grid-cols-2 gap-8 border-t border-[var(--dig-graphite-800)] pt-10 md:grid-cols-[1.5fr_1fr_1fr_1fr]">
<div className="col-span-2 flex flex-col gap-3 md:col-span-1">
<span className="flex items-center gap-2 text-lg font-black">
<span aria-hidden className="flex size-8 items-center justify-center rounded-lg bg-[var(--dig-green-300)] text-[var(--dig-graphite-950)]">
<SparklesIcon className="size-4" />
</span>
کوهسار
</span>
<p className="max-w-60 text-sm leading-6 text-[var(--dig-neutral-400)]">پیگیریِ داراییها، سرمایهگذاری و رشدِ مالی در یک جا.</p>
</div>
{COLUMNS.map((column) => (
<nav key={column.title} aria-label={column.title} className="flex flex-col gap-3 text-sm">
<span className="text-[var(--dig-neutral-500)]">{column.title}</span>
{column.links.map((link) => (
<a key={link} href="#" className="text-[var(--dig-neutral-300)] hover:text-[var(--dig-white)]">
{link}
</a>
))}
</nav>
))}
</div>
<div className="flex flex-wrap justify-between gap-2 text-xs text-[var(--dig-neutral-500)]">
<span>© ۱۴۰۵ کوهسار. همهٔ حقوق محفوظ است.</span>
<a href="#" className="hover:text-[var(--dig-white)]">
شرایطِ استفاده
</a>
</div>
<span aria-hidden className="-mb-[0.32em] block bg-[linear-gradient(180deg,var(--dig-neutral-100),var(--dig-neutral-500)_70%,transparent)] bg-clip-text text-center text-[clamp(5rem,22vw,16rem)] leading-[0.9] font-black text-transparent select-none">
کوهسار
</span>
</div>
</footer>
</ControlSizeProvider>
)
}