Compare commits
8 Commits
version_3_
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d80983360 | |||
| 41c93b1d4f | |||
| 1034ff2459 | |||
| 536fc821cd | |||
| 9fd8e43953 | |||
| eb62fd34cc | |||
| 410fd1e658 | |||
| 2d98c8e419 |
@@ -1,9 +1,7 @@
|
||||
import { motion } from "motion/react";
|
||||
import { useState } from "react";
|
||||
import Button from "@/components/ui/Button";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
import { getRandomFact } from "@/lib/facts";
|
||||
|
||||
type AboutMediaOverlayProps = {
|
||||
tag: string;
|
||||
@@ -22,7 +20,6 @@ const AboutMediaOverlay = ({
|
||||
imageSrc,
|
||||
videoSrc,
|
||||
}: AboutMediaOverlayProps) => {
|
||||
const [fact] = useState(getRandomFact);
|
||||
return (
|
||||
<section aria-label="About section" className="py-20">
|
||||
<div className="relative flex items-center justify-center py-8 md:py-12 mx-auto w-content-width rounded overflow-hidden">
|
||||
@@ -33,6 +30,9 @@ const AboutMediaOverlay = ({
|
||||
|
||||
<div className="relative z-10 flex items-center justify-center px-5 py-10 mx-auto min-h-100 md:min-h-120 md:w-1/2 w-content-width">
|
||||
<div className="flex flex-col items-center gap-3 md:gap-1 text-center">
|
||||
<div className="mb-2">
|
||||
<div className="inline-block px-3 py-1 text-sm rounded-full bg-white/20 backdrop-blur-sm border border-white/30 text-foreground">We have a rubber duck for debugging. His name is Sir Quacks-A-Lot.</div>
|
||||
</div>
|
||||
<motion.span
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
@@ -50,16 +50,6 @@ const AboutMediaOverlay = ({
|
||||
className="text-6xl font-medium text-balance"
|
||||
/>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-15%" }}
|
||||
transition={{ duration: 0.4, ease: "easeOut", delay: 0.2 }}
|
||||
className="backdrop-blur-md bg-white/30 border border-white/20 rounded-lg p-4 my-6 text-center max-w-md"
|
||||
>
|
||||
<p className="text-sm italic text-foreground">"{fact}"</p>
|
||||
</motion.div>
|
||||
|
||||
<TextAnimation
|
||||
text={description}
|
||||
variant="slide-up"
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState } from "react";
|
||||
import { motion } from "motion/react";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
import { sendContactEmail } from "@/lib/api/email";
|
||||
import { companyFacts } from "../../../data/facts";
|
||||
|
||||
type InputField = {
|
||||
name: string;
|
||||
@@ -40,12 +39,6 @@ const ContactSplitForm = ({
|
||||
imageSrc,
|
||||
videoSrc,
|
||||
}: ContactSplitFormProps) => {
|
||||
const [currentFact, setCurrentFact] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentFact(companyFacts[Math.floor(Math.random() * companyFacts.length)]);
|
||||
}, []);
|
||||
|
||||
const [formData, setFormData] = useState<Record<string, string>>(() => {
|
||||
const initial: Record<string, string> = {};
|
||||
inputs.forEach((input) => {
|
||||
@@ -86,6 +79,9 @@ const ContactSplitForm = ({
|
||||
<div className="p-5 md:p-10 card rounded">
|
||||
<form onSubmit={handleSubmit} className="flex flex-col gap-5">
|
||||
<div className="flex flex-col items-center gap-1 text-center">
|
||||
<div className="mb-2">
|
||||
<div className="inline-block px-3 py-1 text-sm rounded-full bg-card/20 backdrop-blur-sm border border-card/30 text-foreground">Our contact form is powered by a hamster on a wheel. Please be patient.</div>
|
||||
</div>
|
||||
<span className="card rounded px-3 py-1 text-sm">{tag}</span>
|
||||
|
||||
<TextAnimation
|
||||
@@ -95,18 +91,6 @@ const ContactSplitForm = ({
|
||||
className="text-4xl font-medium text-balance"
|
||||
/>
|
||||
|
||||
{currentFact && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-15%" }}
|
||||
transition={{ duration: 0.4, ease: "easeOut", delay: 0.2 }}
|
||||
className="backdrop-blur-md bg-white/30 border border-white/20 rounded-lg p-4 my-6 text-center max-w-md"
|
||||
>
|
||||
<p className="text-sm italic text-foreground">"{currentFact}"</p>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
<TextAnimation
|
||||
text={description}
|
||||
variant="slide-up"
|
||||
|
||||
@@ -5,7 +5,6 @@ import Button from "@/components/ui/Button";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
import { cls } from "@/lib/utils";
|
||||
import GlassmorphicBadge from "@/components/ui/GlassmorphicBadge";
|
||||
|
||||
type FaqItem = {
|
||||
question: string;
|
||||
@@ -41,6 +40,9 @@ const FaqSplitMedia = ({
|
||||
<section aria-label="FAQ section" className="py-20">
|
||||
<div className="w-content-width mx-auto flex flex-col gap-8">
|
||||
<div className="flex flex-col items-center gap-3 md:gap-2">
|
||||
<div className="mb-2">
|
||||
<div className="inline-block px-3 py-1 text-sm rounded-full bg-card/20 backdrop-blur-sm border border-card/30 text-foreground">FAQ: Do you sleep? Answer: Rarely.</div>
|
||||
</div>
|
||||
<span className="card rounded px-3 py-1 text-sm">{tag}</span>
|
||||
|
||||
<TextAnimation
|
||||
@@ -57,8 +59,6 @@ const FaqSplitMedia = ({
|
||||
className="md:max-w-6/10 text-lg leading-tight text-center"
|
||||
/>
|
||||
|
||||
<GlassmorphicBadge />
|
||||
|
||||
{(primaryButton || secondaryButton) && (
|
||||
<div className="flex flex-wrap justify-center gap-3 mt-1 md:mt-2">
|
||||
{primaryButton && <Button text={primaryButton.text} href={primaryButton.href} variant="primary" animate />}
|
||||
|
||||
@@ -3,7 +3,6 @@ import Button from "@/components/ui/Button";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
import GridOrCarousel from "@/components/ui/GridOrCarousel";
|
||||
import FunnyFactBadge from "@/components/ui/FunnyFactBadge";
|
||||
|
||||
type FeatureItem = {
|
||||
title: string;
|
||||
@@ -31,6 +30,9 @@ const FeaturesMediaCards = ({
|
||||
<section aria-label="Features section" className="py-20">
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col items-center w-content-width mx-auto gap-3 md:gap-2">
|
||||
<div className="mb-2">
|
||||
<div className="inline-block px-3 py-1 text-sm rounded-full bg-card/20 backdrop-blur-sm border border-card/30 text-foreground">Our secret feature is a button that orders pizza. It's still in beta.</div>
|
||||
</div>
|
||||
<span className="px-3 py-1 text-sm card rounded">{tag}</span>
|
||||
|
||||
<TextAnimation
|
||||
@@ -47,8 +49,6 @@ const FeaturesMediaCards = ({
|
||||
className="md:max-w-6/10 text-lg leading-tight text-center"
|
||||
/>
|
||||
|
||||
<FunnyFactBadge />
|
||||
|
||||
{(primaryButton || secondaryButton) && (
|
||||
<div className="flex flex-wrap justify-center gap-3 mt-1 md:mt-2">
|
||||
{primaryButton && <Button text={primaryButton.text} href={primaryButton.href} variant="primary" animate />}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useButtonClick } from "@/hooks/useButtonClick";
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
type FooterLink = {
|
||||
label: string;
|
||||
@@ -34,28 +33,12 @@ const FooterBasic = ({
|
||||
leftText: string;
|
||||
rightText: string;
|
||||
}) => {
|
||||
const funnyFacts = [
|
||||
"Our office coffee machine is sentient and demands tribute in the form of spare USB cables.",
|
||||
"We once solved a major server outage by turning it off and on again. The client thinks we're wizards.",
|
||||
"The company's first server was a modified gaming console. It ran surprisingly well.",
|
||||
"Our AI assistant has developed a passion for writing poetry about database schemas.",
|
||||
"Legend says our lead developer codes in binary. We haven't disproven it."
|
||||
];
|
||||
|
||||
const [randomFact, setRandomFact] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setRandomFact(funnyFacts[Math.floor(Math.random() * funnyFacts.length)]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<footer aria-label="Site footer" className="w-full pt-20 pb-10">
|
||||
<div className="w-content-width mx-auto">
|
||||
{randomFact && (
|
||||
<div className="backdrop-blur-md bg-white/30 border border-white/20 rounded-xl shadow-lg p-4 text-foreground mb-8 text-center">
|
||||
<p className="italic">"{randomFact}"</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="w-full flex justify-center mb-8">
|
||||
<div className="inline-block px-3 py-1 text-sm rounded-full bg-card/20 backdrop-blur-sm border border-card/30 text-foreground">Made with ❤️ and too many energy drinks.</div>
|
||||
</div>
|
||||
<div className="w-full flex flex-wrap justify-between gap-y-10 mb-10">
|
||||
{columns.map((column) => (
|
||||
<div key={column.title} className="w-1/2 md:w-auto flex flex-col items-start gap-3">
|
||||
|
||||
@@ -2,8 +2,6 @@ import Button from "@/components/ui/Button";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
import AutoFillText from "@/components/ui/AutoFillText";
|
||||
import GlassmorphicBadge from "@/components/ui/GlassmorphicBadge";
|
||||
import { motion } from "motion/react";
|
||||
|
||||
type HeroBrandProps = {
|
||||
brand: string;
|
||||
@@ -37,14 +35,10 @@ const HeroBrand = ({
|
||||
/>
|
||||
|
||||
<div className="relative z-10 w-content-width mx-auto pb-5">
|
||||
<div className="flex flex-col gap-4">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, ease: "easeOut" }}
|
||||
>
|
||||
<GlassmorphicBadge />
|
||||
</motion.div>
|
||||
<div className="flex flex-col">
|
||||
<div className="mb-4">
|
||||
<div className="inline-block px-3 py-1 text-sm rounded-full bg-white/20 backdrop-blur-sm border border-white/30 text-primary-cta-text">Powered by caffeine and the occasional reboot.</div>
|
||||
</div>
|
||||
<div className="w-full flex flex-col md:flex-row md:justify-between items-start md:items-end gap-3 md:gap-5">
|
||||
<TextAnimation
|
||||
text={description}
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { motion } from "motion/react";
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import Button from "@/components/ui/Button";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import GridOrCarousel from "@/components/ui/GridOrCarousel";
|
||||
import { resolveIcon } from "@/utils/resolve-icon";
|
||||
import { getRandomFact } from "@/lib/facts";
|
||||
|
||||
type Metric = {
|
||||
value: string;
|
||||
@@ -30,12 +26,13 @@ const MetricsGradientCards = ({
|
||||
primaryButton?: { text: string; href: string };
|
||||
secondaryButton?: { text: string; href: string };
|
||||
metrics: Metric[];
|
||||
}) => {
|
||||
const [fact] = useState(getRandomFact);
|
||||
return (
|
||||
}) => (
|
||||
<section aria-label="Metrics section" className="py-20">
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col items-center gap-3 md:gap-2 w-content-width mx-auto">
|
||||
<div className="mb-2">
|
||||
<div className="inline-block px-3 py-1 text-sm rounded-full bg-card/20 backdrop-blur-sm border border-card/30 text-foreground">Our uptime is 99.9%, but our coffee machine's is closer to 50%.</div>
|
||||
</div>
|
||||
<span className="px-3 py-1 text-sm card rounded">{tag}</span>
|
||||
|
||||
<TextAnimation
|
||||
@@ -52,16 +49,6 @@ const MetricsGradientCards = ({
|
||||
className="md:max-w-6/10 text-lg leading-tight text-center"
|
||||
/>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-15%" }}
|
||||
transition={{ duration: 0.4, ease: "easeOut", delay: 0.2 }}
|
||||
className="backdrop-blur-md bg-white/30 border border-white/20 rounded-lg p-4 my-6 text-center max-w-md"
|
||||
>
|
||||
<p className="text-sm italic text-foreground">"{fact}"</p>
|
||||
</motion.div>
|
||||
|
||||
{(primaryButton || secondaryButton) && (
|
||||
<div className="flex flex-wrap justify-center gap-3 mt-1 md:mt-2">
|
||||
{primaryButton && <Button text={primaryButton.text} href={primaryButton.href} variant="primary" animate />}
|
||||
@@ -104,7 +91,6 @@ const MetricsGradientCards = ({
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
);
|
||||
|
||||
export default MetricsGradientCards;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { motion } from "motion/react";
|
||||
import { useState } from "react";
|
||||
import Button from "@/components/ui/Button";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import { getRandomFact } from "@/lib/facts";
|
||||
|
||||
const SocialProofMarquee = ({
|
||||
tag,
|
||||
@@ -19,12 +17,13 @@ const SocialProofMarquee = ({
|
||||
secondaryButton?: { text: string; href: string };
|
||||
names: string[];
|
||||
}) => {
|
||||
const [fact] = useState(getRandomFact);
|
||||
|
||||
return (
|
||||
<section aria-label="Social proof section" className="py-20">
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col items-center gap-3 md:gap-2 w-content-width mx-auto">
|
||||
<div className="mb-2">
|
||||
<div className="inline-block px-3 py-1 text-sm rounded-full bg-card/20 backdrop-blur-sm border border-card/30 text-foreground">Even our CEO's mom thinks we're a big deal.</div>
|
||||
</div>
|
||||
<span className="px-3 py-1 text-sm rounded card">{tag}</span>
|
||||
|
||||
<TextAnimation
|
||||
@@ -41,16 +40,6 @@ const SocialProofMarquee = ({
|
||||
className="md:max-w-6/10 text-lg leading-tight text-center"
|
||||
/>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-15%" }}
|
||||
transition={{ duration: 0.4, ease: "easeOut", delay: 0.2 }}
|
||||
className="backdrop-blur-md bg-white/30 border border-white/20 rounded-lg p-4 my-4 text-center max-w-md mx-auto"
|
||||
>
|
||||
<p className="text-sm italic text-foreground">"{fact}"</p>
|
||||
</motion.div>
|
||||
|
||||
{(primaryButton || secondaryButton) && (
|
||||
<div className="flex flex-wrap justify-center gap-3 mt-1 md:mt-2">
|
||||
{primaryButton && <Button text={primaryButton.text} href={primaryButton.href} variant="primary" animate />}
|
||||
|
||||
@@ -3,7 +3,6 @@ import Button from "@/components/ui/Button";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
import GridOrCarousel from "@/components/ui/GridOrCarousel";
|
||||
import GlassmorphicBadge from "@/components/ui/GlassmorphicBadge";
|
||||
|
||||
type Testimonial = {
|
||||
name: string;
|
||||
@@ -29,6 +28,9 @@ const TestimonialQuoteCards = ({
|
||||
<section aria-label="Testimonials section" className="py-20">
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col items-center gap-3 md:gap-2 w-content-width mx-auto">
|
||||
<div className="mb-2">
|
||||
<div className="inline-block px-3 py-1 text-sm rounded-full bg-card/20 backdrop-blur-sm border border-card/30 text-foreground">Our clients love us. We have the thank-you cards to prove it.</div>
|
||||
</div>
|
||||
<span className="px-3 py-1 text-sm card rounded">{tag}</span>
|
||||
|
||||
<TextAnimation
|
||||
@@ -45,8 +47,6 @@ const TestimonialQuoteCards = ({
|
||||
className="md:max-w-6/10 text-lg leading-tight text-center"
|
||||
/>
|
||||
|
||||
<GlassmorphicBadge />
|
||||
|
||||
{(primaryButton || secondaryButton) && (
|
||||
<div className="flex flex-wrap justify-center gap-3 mt-1 md:mt-2">
|
||||
{primaryButton && <Button text={primaryButton.text} href={primaryButton.href} variant="primary" animate />}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { motion } from "motion/react";
|
||||
|
||||
const funnyFacts = [
|
||||
"Our office coffee machine is sentient and occasionally offers career advice.",
|
||||
"We once solved a major bug by turning the server off and on again. It's now our official policy.",
|
||||
"The company mascot is a rubber duck named 'Sir Quacks-a-Lot'. He has his own email address.",
|
||||
"All our code is written in Comic Sans for 'improved readability'.",
|
||||
"Our CTO's cat is listed as a senior developer on our internal directory.",
|
||||
];
|
||||
|
||||
const getRandomFact = () => funnyFacts[Math.floor(Math.random() * funnyFacts.length)];
|
||||
|
||||
const FunnyFactBadge = () => {
|
||||
const [fact] = useState(getRandomFact);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-15%" }}
|
||||
transition={{ duration: 0.4, ease: "easeOut", delay: 0.2 }}
|
||||
className="backdrop-blur-md bg-white/30 border border-white/20 rounded-lg p-4 my-4 text-center max-w-md mx-auto"
|
||||
>
|
||||
<p className="text-sm italic text-foreground">"{fact}"</p>
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FunnyFactBadge;
|
||||
@@ -1,37 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { motion } from "motion/react";
|
||||
|
||||
const funnyFacts = [
|
||||
"Our office coffee machine is rumored to be sentient. It only makes good coffee for its favorites.",
|
||||
"We once named a server 'Zeus' and it was promptly struck by a lightning-induced power surge. We stick to boring names now.",
|
||||
"The office plant has been promoted more times than some of our interns.",
|
||||
"Our first 'office' was a garage that we shared with a surprisingly musical raccoon.",
|
||||
"We settled a heated debate on tabs vs. spaces with a company-wide rock-paper-scissors tournament.",
|
||||
"The company mascot is a rubber duck named 'Kernel Panic'. He oversees all code deployments.",
|
||||
];
|
||||
|
||||
const GlassmorphicBadge = () => {
|
||||
const [fact, setFact] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
setFact(funnyFacts[Math.floor(Math.random() * funnyFacts.length)]);
|
||||
}, []);
|
||||
|
||||
if (!fact) return null;
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-15%" }}
|
||||
transition={{ duration: 0.4, ease: "easeOut", delay: 0.2 }}
|
||||
className="backdrop-blur-md bg-white/30 border border-white/20 rounded-lg p-4 my-6 text-center max-w-md mx-auto"
|
||||
>
|
||||
<p className="text-sm italic text-foreground">"{fact}"</p>
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GlassmorphicBadge;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { motion, AnimatePresence } from "motion/react";
|
||||
import { Plus, ArrowRight } from "lucide-react";
|
||||
@@ -45,45 +45,23 @@ const NavLink = ({
|
||||
);
|
||||
};
|
||||
|
||||
const funnyFacts = [
|
||||
"Our office coffee is powered by pure optimism.",
|
||||
"We once named a server 'Titanic'. It was unsinkable.",
|
||||
"Our first 'office' was a garage. We still have oil stains.",
|
||||
"The office plant is our longest-serving employee.",
|
||||
"Our mascot is a rubber duck named 'Sir Quacks-a-lot'.",
|
||||
];
|
||||
|
||||
const NavbarCentered = ({ logo, navItems, ctaButton }: NavbarCenteredProps) => {
|
||||
const [isScrolled, setIsScrolled] = useState(false);
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const [fact, setFact] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
setFact(funnyFacts[Math.floor(Math.random() * funnyFacts.length)]);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => setIsScrolled(window.scrollY > 50);
|
||||
window.addEventListener("scroll", handleScroll, { passive: true });
|
||||
return () => window.removeEventListener("scroll", handleScroll);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav
|
||||
className={cls(
|
||||
"fixed z-1000 top-0 left-0 w-full transition-all duration-500 ease-in-out",
|
||||
isScrolled ? "h-15 bg-background/80 backdrop-blur-sm" : "h-20 bg-background/0 backdrop-blur-0"
|
||||
"sticky top-0 z-50 w-full transition-all duration-500 ease-in-out h-20 bg-background/80 backdrop-blur-md border-b border-foreground/10"
|
||||
)}
|
||||
>
|
||||
<div className="relative flex items-center justify-between h-full w-content-width mx-auto">
|
||||
<div className="flex items-center gap-4">
|
||||
<Link to="/" className="text-xl font-medium text-foreground">{logo}</Link>
|
||||
{fact && (
|
||||
<div className="hidden lg:block backdrop-blur-md bg-white/20 border border-white/10 rounded-full px-3 py-1 text-xs shadow-lg text-foreground whitespace-nowrap">
|
||||
{fact}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center gap-1 px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs font-medium">
|
||||
<span className="w-2 h-2 rounded-full bg-green-500 animate-[pulse-green_2s_infinite]"></span>
|
||||
Active Now
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="hidden md:flex absolute left-1/2 items-center gap-6 -translate-x-1/2">
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
export const companyFacts = [
|
||||
"Our office coffee machine is rumored to be sentient. We haven't confirmed it, but it makes a great latte.",
|
||||
"We once held a meeting entirely in pirate speak. Productivity was questionable, but morale was high.",
|
||||
"The office plant, 'Fern-ando', has been promoted to Senior Vice President of Photosynthesis.",
|
||||
"Our first server was a potato. It was surprisingly reliable.",
|
||||
"We have a rubber duck for debugging. It's our most senior developer.",
|
||||
];
|
||||
@@ -1,13 +0,0 @@
|
||||
export const facts = [
|
||||
"Our office coffee machine is rumored to be sentient. It only makes good coffee for its favorites.",
|
||||
"We once held a meeting entirely in emojis. It was surprisingly productive.",
|
||||
"The company's first server was a modified gaming console. It still holds the high score in Tetris.",
|
||||
"Our CEO's dog is an official board member with the title 'Chief Morale Officer'.",
|
||||
"We have a rubber duck for debugging. It's been promoted twice.",
|
||||
"The office plant has more followers on Instagram than most of our employees.",
|
||||
"Our team-building exercise involved assembling IKEA furniture without instructions. We're still not talking about it.",
|
||||
];
|
||||
|
||||
export const getRandomFact = () => {
|
||||
return facts[Math.floor(Math.random() * facts.length)];
|
||||
};
|
||||
@@ -169,3 +169,14 @@
|
||||
.animate-progress {
|
||||
animation: progress linear forwards;
|
||||
}
|
||||
|
||||
@keyframes pulse-green {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user