feat: change color
This commit is contained in:
@@ -43,7 +43,7 @@ export function BlogCard({
|
||||
</div>
|
||||
|
||||
<CardHeader className="flex-1 flex flex-col">
|
||||
<h3 className="text-xl font-bold leading-tight tracking-normal group-hover:text-primary transition-colors line-clamp-2">
|
||||
<h3 className="text-base py-2 font-bold leading-tight tracking-normal group-hover:text-primary transition-colors line-clamp-2">
|
||||
{title}
|
||||
</h3>
|
||||
</CardHeader>
|
||||
|
||||
@@ -92,7 +92,7 @@ export function BlogPostCard({
|
||||
</div>
|
||||
)}
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-xl font-bold leading-tight line-clamp-2 mt-2">
|
||||
<CardTitle className="text-base font-bold leading-tight line-clamp-2 my-2">
|
||||
{post.title.rendered}
|
||||
</CardTitle>
|
||||
<div className="flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground bg-muted inline-flex p-1 rounded-sm">
|
||||
|
||||
+9
-15
@@ -6,6 +6,10 @@ const links = [
|
||||
title: "درباره ما",
|
||||
href: "/about",
|
||||
},
|
||||
{
|
||||
title: "بلاگ",
|
||||
href: "/blog",
|
||||
},
|
||||
{
|
||||
title: "راه حلها",
|
||||
href: "/solutions",
|
||||
@@ -14,11 +18,11 @@ const links = [
|
||||
|
||||
export default function FooterSection() {
|
||||
return (
|
||||
<footer className="py-16 md:py-32">
|
||||
<div className="mx-auto max-w-5xl px-6">
|
||||
<Logo />
|
||||
<footer className="py-16 md:py-16 bg-muted border-t">
|
||||
<div className="mx-auto max-w-5xl px-6 flex items-center flex-col">
|
||||
<Logo className="mx-auto" />
|
||||
|
||||
<div className="my-8 flex flex-wrap justify-center gap-6 text-sm">
|
||||
<div className="my-4 flex flex-wrap justify-center gap-6 text-sm">
|
||||
{links.map((link, index) => (
|
||||
<Link
|
||||
key={index}
|
||||
@@ -29,18 +33,8 @@ export default function FooterSection() {
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="my-8 flex flex-wrap justify-center items-center gap-2 text-sm">
|
||||
<span className="text-muted-foreground">تماس با تیم فیپ:</span>
|
||||
<a
|
||||
href="tel:09162949770"
|
||||
className="text-foreground hover:text-accent transition-colors duration-150 font-medium"
|
||||
>
|
||||
09162949770
|
||||
</a>
|
||||
</div>
|
||||
<span className="text-muted-foreground block text-center text-sm">
|
||||
{" "}
|
||||
© {new Date().getFullYear()} فیپ، تمامی حقوق محفوظ است
|
||||
© 1404 فیپ، تمامی حقوق محفوظ است
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
+22
-24
@@ -38,21 +38,22 @@ export const HeroHeader = () => {
|
||||
<nav
|
||||
data-state={menuState && 'active'}
|
||||
className="fixed z-20 w-full px-2">
|
||||
<div className={cn('mx-auto mt-2 max-w-6xl px-6 transition-all duration-300 lg:px-12 bg-background/80 backdrop-blur-md rounded-2xl border border-border/50', isScrolled && 'bg-background/95 max-w-4xl shadow-lg lg:px-5')}>
|
||||
<div className="relative flex flex-wrap items-center justify-between gap-6 py-2 lg:gap-0 lg:py-3">
|
||||
<div className={cn('mx-auto mt-2 max-w-6xl px-2 transition-all duration-300 lg:px-2 bg-background/30 backdrop-blur-md rounded-md border border-border/10', isScrolled && 'bg-background/20 max-w-4xl shadow-lg lg:px-5')}>
|
||||
<div className="relative flex flex-wrap items-center justify-between gap-2 lg:gap-0">
|
||||
<div className="flex w-full justify-between lg:w-auto">
|
||||
<Logo />
|
||||
<button
|
||||
onClick={() => setMenuState(!menuState)}
|
||||
aria-label={menuState == true ? 'بستن منو' : 'باز کردن منو'}
|
||||
className="relative z-20 -m-2.5 -mr-4 block cursor-pointer p-2.5 lg:hidden">
|
||||
<Menu className="in-data-[state=active]:rotate-180 in-data-[state=active]:scale-0 in-data-[state=active]:opacity-0 m-auto size-6 duration-200" />
|
||||
<X className="in-data-[state=active]:rotate-0 in-data-[state=active]:scale-100 in-data-[state=active]:opacity-100 absolute inset-0 m-auto size-6 -rotate-180 scale-0 opacity-0 duration-200" />
|
||||
<Menu className="in-data-[state=active]:rotate-180 in-data-[state=active]:scale-0 in-data-[state=active]:opacity-0 m-auto size-4 duration-200" />
|
||||
<X className="in-data-[state=active]:rotate-0 in-data-[state=active]:scale-100 in-data-[state=active]:opacity-100 absolute inset-0 m-auto size-4 -rotate-180 scale-0 opacity-0 duration-200" />
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="absolute inset-0 m-auto hidden size-fit lg:flex items-center gap-8">
|
||||
<ul className="flex gap-8 text-sm">
|
||||
<div className="absolute inset-0 m-auto hidden size-fit lg:flex items-center">
|
||||
<ul className="flex gap-2 text-sm">
|
||||
{menuItems.map((item, index) => {
|
||||
const active = isLinkActive(pathname ?? '', item.href)
|
||||
return (
|
||||
@@ -60,51 +61,48 @@ export const HeroHeader = () => {
|
||||
<Link
|
||||
href={item.href}
|
||||
className={cn(
|
||||
'text-muted-foreground hover:text-foreground transition-all duration-300 relative group',
|
||||
active && 'text-foreground'
|
||||
'text-muted-foreground hover:text-foreground hover:bg-accent/20 transition-all duration-300 relative group p-2 px-4 rounded-md',
|
||||
active && 'text-foreground bg-accent/40'
|
||||
)}>
|
||||
<span className="relative z-10">{item.name}</span>
|
||||
<span className={cn(
|
||||
'absolute bottom-0 right-0 h-0.5 bg-accent transition-all duration-300 group-hover:w-full',
|
||||
active ? 'w-full' : 'w-0'
|
||||
)} />
|
||||
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
<ThemeToggle />
|
||||
|
||||
</div>
|
||||
|
||||
<div className="bg-background in-data-[state=active]:block lg:in-data-[state=active]:flex mb-6 hidden w-full flex-wrap items-center justify-end space-y-8 rounded-3xl border p-6 shadow-2xl shadow-zinc-300/20 md:flex-nowrap lg:m-0 lg:flex lg:w-fit lg:gap-6 lg:space-y-0 lg:border-transparent lg:bg-transparent lg:p-0 lg:shadow-none dark:shadow-none dark:lg:bg-transparent">
|
||||
<div className="in-data-[state=active]:block lg:in-data-[state=active]:flex mb-3 hidden w-full flex-wrap items-center justify-end space-y-8 md:flex-nowrap lg:m-0 lg:flex lg:w-fit lg:gap-6 lg:space-y-0 lg:border-transparent lg:bg-transparent lg:p-0 lg:shadow-none dark:shadow-none dark:lg:bg-transparent">
|
||||
<div className="lg:hidden w-full">
|
||||
<ul className="space-y-6 text-base">
|
||||
|
||||
<ul className="text-base flex flex-col items-stretch">
|
||||
{menuItems.map((item, index) => {
|
||||
const active = isLinkActive(pathname ?? '', item.href)
|
||||
return (
|
||||
<li key={index}>
|
||||
<Link
|
||||
href={item.href}
|
||||
onClick={() => setMenuState(false)}
|
||||
className={cn(
|
||||
'text-muted-foreground hover:text-foreground transition-all duration-300 relative group block',
|
||||
active && 'text-foreground'
|
||||
'text-muted-foreground block w-full hover:text-foreground hover:bg-accent/20 transition-all duration-300 relative group p-2 px-4 rounded-md',
|
||||
active && 'text-foreground bg-accent/40'
|
||||
)}>
|
||||
<span className="relative z-10">{item.name}</span>
|
||||
<span className={cn(
|
||||
'absolute bottom-0 right-0 h-0.5 bg-accent transition-all duration-300 group-hover:w-full',
|
||||
active ? 'w-full' : 'w-0'
|
||||
)} />
|
||||
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
<div className="mt-6 flex justify-end">
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className={`flex justify-end max-md:absolute top-0.5 left-8 in-data-[state=active]:block`}>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
+8
-8
@@ -10,9 +10,9 @@ export const Logo = ({
|
||||
uniColor?: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<Link href="/" className="flex items-center space-x-2">
|
||||
<Link href="/" className="flex items-center">
|
||||
<LogoIcon className={className} uniColor={uniColor} />
|
||||
<span className="font-bold text-sm">فیپ</span>
|
||||
<span className="font-bold text-xl">فـــیــپ</span>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
@@ -25,12 +25,12 @@ export const LogoIcon = ({
|
||||
uniColor?: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<Image
|
||||
src="/assets/feep-Logo.svg"
|
||||
alt="Logo"
|
||||
width={50}
|
||||
height={50}
|
||||
className={cn("h-10 w-auto md:h-12 dark:invert", className)}
|
||||
<Image
|
||||
src="/assets/feep-Logo.svg"
|
||||
alt="Logo"
|
||||
width={50}
|
||||
height={50}
|
||||
className={cn("h-10 w-auto md:h-12 dark:invert", className)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
"use client";
|
||||
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
const TOP_BAR_HEIGHT = 3;
|
||||
const MAX_PERCENT = 90;
|
||||
const COMPLETE_PERCENT = 100;
|
||||
const TICK_MS = 50;
|
||||
const INCREMENT = 2;
|
||||
const COMPLETE_DURATION = 200;
|
||||
|
||||
export function TopProgressBar() {
|
||||
const pathname = usePathname();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [percent, setPercent] = useState(0);
|
||||
const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
const completeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const prevPathnameRef = useRef(pathname);
|
||||
|
||||
const clearTimers = useCallback(() => {
|
||||
if (timerRef.current) {
|
||||
clearInterval(timerRef.current);
|
||||
timerRef.current = null;
|
||||
}
|
||||
if (completeTimeoutRef.current) {
|
||||
clearTimeout(completeTimeoutRef.current);
|
||||
completeTimeoutRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const startProgress = useCallback(() => {
|
||||
clearTimers();
|
||||
setVisible(true);
|
||||
setPercent(0);
|
||||
timerRef.current = setInterval(() => {
|
||||
setPercent((p) => {
|
||||
if (p >= MAX_PERCENT) {
|
||||
if (timerRef.current) {
|
||||
clearInterval(timerRef.current);
|
||||
timerRef.current = null;
|
||||
}
|
||||
return MAX_PERCENT;
|
||||
}
|
||||
return Math.min(p + INCREMENT, MAX_PERCENT);
|
||||
});
|
||||
}, TICK_MS);
|
||||
}, [clearTimers]);
|
||||
|
||||
const completeProgress = useCallback(() => {
|
||||
clearTimers();
|
||||
setPercent(COMPLETE_PERCENT);
|
||||
completeTimeoutRef.current = setTimeout(() => {
|
||||
setVisible(false);
|
||||
setPercent(0);
|
||||
completeTimeoutRef.current = null;
|
||||
}, COMPLETE_DURATION);
|
||||
}, [clearTimers]);
|
||||
|
||||
// Start bar when user clicks an internal link
|
||||
useEffect(() => {
|
||||
const handleClick = (e: MouseEvent) => {
|
||||
const target = (e.target as Element).closest("a");
|
||||
if (!target?.href) return;
|
||||
try {
|
||||
const url = new URL(target.href);
|
||||
if (url.origin === window.location.origin && url.pathname !== pathname) {
|
||||
startProgress();
|
||||
}
|
||||
} catch {
|
||||
// ignore invalid URLs
|
||||
}
|
||||
};
|
||||
document.addEventListener("click", handleClick, true);
|
||||
return () => document.removeEventListener("click", handleClick, true);
|
||||
}, [pathname, startProgress]);
|
||||
|
||||
// Complete bar when pathname changes (route loaded)
|
||||
useEffect(() => {
|
||||
if (prevPathnameRef.current !== pathname) {
|
||||
prevPathnameRef.current = pathname;
|
||||
if (visible) completeProgress();
|
||||
}
|
||||
}, [pathname, visible, completeProgress]);
|
||||
|
||||
useEffect(() => {
|
||||
return clearTimers;
|
||||
}, [clearTimers]);
|
||||
|
||||
if (!visible) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed left-0 right-0 z-[9999] overflow-hidden bg-transparent"
|
||||
style={{ height: TOP_BAR_HEIGHT }}
|
||||
aria-hidden
|
||||
>
|
||||
<div
|
||||
className="h-full bg-primary transition-[width] duration-150 ease-out"
|
||||
style={{ width: `${percent}%` }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user