design: improved site-wide light/dark theme, home footer is looking normal again, misc tweaks

This commit is contained in:
Aidan 2025-03-15 15:43:44 -04:00
parent 6cd5d6051f
commit 1463722a84
9 changed files with 73 additions and 67 deletions

View File

@ -71,10 +71,10 @@
@utility container { @utility container {
margin-inline: auto; margin-inline: auto;
padding-inline: 2rem; padding-inline: 2rem;
@media (width >= --theme(--breakpoint-sm)) { @media (min-width: theme('screens.sm')) {
max-width: none; max-width: none;
} }
@media (width >= 1400px) { @media (min-width: 1400px) {
max-width: 1400px; max-width: 1400px;
} }
} }
@ -99,7 +99,7 @@
@layer base { @layer base {
:root { :root {
--background: 0 0% 100%; --background: 30 20% 98%;
--foreground: 222.2 84% 4.9%; --foreground: 222.2 84% 4.9%;
--muted: 210 40% 96.1%; --muted: 210 40% 96.1%;
@ -120,7 +120,7 @@
--secondary: 210 40% 96.1%; --secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%; --secondary-foreground: 222.2 47.4% 11.2%;
--accent: 210 40% 96.1%; --accent: 210 60% 95%;
--accent-foreground: 222.2 47.4% 11.2%; --accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%; --destructive: 0 84.2% 60.2%;
@ -130,20 +130,13 @@
--radius: 0.5rem; --radius: 0.5rem;
--sidebar-background: 0 0% 98%; --sidebar-background: 215 25% 97%;
--sidebar-foreground: 240 5.3% 26.1%; --sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%; --sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%; --sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 215 10% 92%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%; --sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 88%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%; --sidebar-ring: 217.2 91.2% 59.8%;
} }

View File

@ -42,13 +42,13 @@ export default function Home() {
] ]
return ( return (
<div className="min-h-screen bg-linear-to-b from-gray-950 to-gray-900"> <div className="min-h-screen dark:bg-linear-to-b dark:from-gray-950 dark:to-gray-900">
<Navbar /> <Navbar />
<main> <main>
<Hero /> <Hero />
<section id="services"> <section id="services">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<h2 className="text-4xl font-extrabold text-center mb-12 text-white">Our Services</h2> <h2 className="text-4xl font-extrabold text-center mb-12 text-foreground">Our Services</h2>
<div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3"> <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
{features.map((feature, index) => ( {features.map((feature, index) => (
<FeatureCard key={index} {...feature} /> <FeatureCard key={index} {...feature} />

View File

@ -6,7 +6,7 @@ import Link from "next/link"
export default function Privacy() { export default function Privacy() {
return ( return (
<div className="min-h-screen bg-linear-to-b from-gray-950 to-gray-900"> <div className="min-h-screen dark:bg-linear-to-b dark:from-gray-950 dark:to-gray-900">
<Navbar /> <Navbar />
<main> <main>
<div className="pt-20 pb-10"> <div className="pt-20 pb-10">

View File

@ -7,17 +7,20 @@ interface FeatureCardProps {
icon: React.ElementType icon: React.ElementType
} }
/* TODO: I plan to add a better animation in the future, hover effects are not
good here, in my opinion. */
const FeatureCard = ({ title, description, icon: Icon }: FeatureCardProps) => { const FeatureCard = ({ title, description, icon: Icon }: FeatureCardProps) => {
return ( return (
<Card className="bg-gray-800 border-gray-700 hover:bg-gray-700 transition-colors duration-300"> <Card className="bg-background border-accent transition-colors duration-300">
<CardHeader> <CardHeader>
<CardTitle className="flex items-center text-white"> <CardTitle className="flex items-center">
<Icon className="h-6 w-6 mr-2 text-blue-400" /> <Icon className="h-6 w-6 mr-2 text-blue-400" />
<span className="text-xl">{title}</span> <span className="text-xl">{title}</span>
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<CardDescription className="text-gray-300">{description}</CardDescription> <CardDescription>{description}</CardDescription>
</CardContent> </CardContent>
</Card> </Card>
) )

View File

@ -1,39 +1,48 @@
"use client"
import { RiOpenSourceFill } from "react-icons/ri" import { RiOpenSourceFill } from "react-icons/ri"
import { ArrowUp } from "lucide-react" import { ArrowUp } from "lucide-react"
import Link from "next/link" import Link from "next/link"
export default function Footer() { export default function Footer() {
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
})
}
return ( return (
<div> <footer className="bg-gray-200 dark:bg-gray-900 py-4 mt-auto">
<footer className="bg-gray-950/70">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex flex-col items-center py-4 md:flex-row md:justify-between md:items-center"> <div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4">
<div className="flex items-center mt-8 md:mt-0 md:order-1"> <div className="flex items-center justify-center sm:justify-start">
<RiOpenSourceFill className="text-muted-foreground mr-1" /> <RiOpenSourceFill className="text-gray-600 dark:text-gray-400 mr-2 text-lg" aria-hidden="true" />
<Link <Link
href="https://git.pontusmail.org/librecloud/web" href="https://git.pontusmail.org/librecloud/web"
className="text-muted-foreground hover:text-foreground transition-all" className="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors"
aria-label="View source code"
> >
Open Source & Public Domain Open Source & Public Domain
</Link> </Link>
</div> </div>
<div className="flex items-center justify-center space-x-6 md:order-2"> <div className="flex items-center justify-center space-x-6">
<Link <Link
href="/privacy" href="/privacy"
className="text-muted-foreground hover:text-foreground transition-all" className="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors"
> >
Privacy Policy Privacy Policy
</Link> </Link>
<Link <button
href="#" onClick={scrollToTop}
className="text-muted-foreground hover:text-foreground transition-all" className="flex items-center justify-center p-2 rounded-full bg-gray-300 dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-gray-400 dark:hover:bg-gray-700 hover:text-gray-900 dark:hover:text-gray-100 transition-colors focus:outline-none focus:ring-2 focus:ring-gray-500"
aria-label="Scroll to top"
> >
<ArrowUp /> <ArrowUp className="w-4 h-4" />
</Link> </button>
</div> </div>
</div> </div>
</div> </div>
</footer> </footer>
</div>
) )
} }

View File

@ -9,7 +9,7 @@ const Hero = () => {
const phrases = ["everyone", "developers", "students", "non-profits", "teachers", "workers", "friends"] const phrases = ["everyone", "developers", "students", "non-profits", "teachers", "workers", "friends"]
return ( return (
<div className="pt-20 pb-30 text-white"> <div className="pt-20 pb-30 text-foreground">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center"> <div className="text-center">
<h1 className="text-4xl tracking-tight font-extrabold sm:text-5xl md:text-6xl"> <h1 className="text-4xl tracking-tight font-extrabold sm:text-5xl md:text-6xl">
@ -18,7 +18,7 @@ const Hero = () => {
for <ReactTyped strings={phrases} typeSpeed={60} backSpeed={50} loop className="text-blue-400" /> for <ReactTyped strings={phrases} typeSpeed={60} backSpeed={50} loop className="text-blue-400" />
</span> </span>
</h1> </h1>
<p className="mt-6 max-w-md mx-auto text-xl text-gray-300 sm:max-w-3xl"> <p className="mt-6 max-w-md mx-auto text-xl text-muted-foreground sm:max-w-3xl">
Experience FOSS at its best with LibreCloud, a free service provider built with everyone in mind. Experience FOSS at its best with LibreCloud, a free service provider built with everyone in mind.
</p> </p>
<div className="mt-10 max-w-md mx-auto sm:flex sm:justify-center"> <div className="mt-10 max-w-md mx-auto sm:flex sm:justify-center">

View File

@ -8,12 +8,12 @@ const Navbar = () => {
const [isOpen, setIsOpen] = useState(false) const [isOpen, setIsOpen] = useState(false)
return ( return (
<nav className="bg-gray-950/70 sticky top-0 z-50"> <nav className="bg-gray-300 dark:bg-gray-950/70 sticky top-0 z-50">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="relative flex items-center justify-between h-16"> <div className="relative flex items-center justify-between h-16">
<div className="shrink-0 flex items-center"> <div className="shrink-0 flex items-center">
<Link href="/" className="flex items-center"> <Link href="/" className="flex items-center">
<span className="text-white text-xl font-bold">LibreCloud</span> <span className="text-xl font-bold">LibreCloud</span>
</Link> </Link>
</div> </div>
<div className="hidden md:block"> <div className="hidden md:block">
@ -80,7 +80,7 @@ interface NavLinkProps {
const NavLink: React.FC<NavLinkProps> = ({ href, icon: Icon, children }) => ( const NavLink: React.FC<NavLinkProps> = ({ href, icon: Icon, children }) => (
<Link <Link
href={href} href={href}
className="flex items-center text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium transition-colors duration-200" className="flex items-center hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium transition-colors duration-200"
> >
<Icon className="mr-2 h-5 w-5" /> {children} <Icon className="mr-2 h-5 w-5" /> {children}
</Link> </Link>
@ -95,7 +95,7 @@ interface MobileNavLinkProps {
const MobileNavLink: React.FC<MobileNavLinkProps> = ({ href, icon: Icon, children }) => ( const MobileNavLink: React.FC<MobileNavLinkProps> = ({ href, icon: Icon, children }) => (
<Link <Link
href={href} href={href}
className="flex items-center text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-base font-medium" className="flex items-center hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-base font-medium"
> >
<Icon className="mr-2 h-5 w-5" /> {children} <Icon className="mr-2 h-5 w-5" /> {children}
</Link> </Link>

View File

@ -1,5 +1,5 @@
import { RiOpenSourceFill } from "react-icons/ri"; import { RiOpenSourceFill } from "react-icons/ri";
import { Ampersand } from "lucide-react"; import { TbAmpersand } from "react-icons/tb";
import { HiMiniHeart } from "react-icons/hi2"; import { HiMiniHeart } from "react-icons/hi2";
const PoweredBySection = () => { const PoweredBySection = () => {
@ -8,12 +8,12 @@ const PoweredBySection = () => {
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<h2 className="text-5xl md:text-6xl font-extrabold text-center mb-8 ">Powered by</h2> <h2 className="text-5xl md:text-6xl font-extrabold text-center mb-8 ">Powered by</h2>
<div className="flex flex-col sm:flex-row justify-center items-center"> <div className="flex flex-col sm:flex-row justify-center items-center">
<div className="bg-green-400 rounded-full flex items-center p-4 lg:px-8 sm:mb-0"> <div className="bg-green-400 text-green-800 rounded-full flex items-center p-4 lg:px-8 sm:mb-0">
<RiOpenSourceFill size={40} className="my-auto mr-2 lg:size-22" /> <RiOpenSourceFill size={40} className="my-auto mr-2 lg:size-22" />
<h1 className="text-4xl lg:text-8xl font-extrabold">libre</h1> <h1 className="text-4xl lg:text-8xl font-extrabold">libre</h1>
</div> </div>
<Ampersand size={40} className="m-4 lg:my-8 lg:size-22" /> <TbAmpersand size={40} className="m-4 lg:my-8 lg:size-22" />
<div className="bg-red-400 rounded-full flex items-center p-4 lg:px-8"> <div className="bg-red-400 text-red-800 rounded-full flex items-center p-4 lg:px-8">
<HiMiniHeart size={40} className="my-auto mr-2 lg:size-24" /> <HiMiniHeart size={40} className="my-auto mr-2 lg:size-24" />
<h1 className="text-4xl lg:text-8xl font-extrabold">love</h1> <h1 className="text-4xl lg:text-8xl font-extrabold">love</h1>
</div> </div>

View File

@ -49,10 +49,10 @@ export default function Pricing() {
} }
return ( return (
<section id="love" className="pt-24 pb-10"> <section id="pricing" className="pb-10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-16"> <div className="text-center mb-16">
<h2 className="text-4xl font-extrabold text-white mb-4">Pricing You&#39;ll Love</h2> <h2 className="text-4xl font-extrabold text-foreground mb-4">Pricing You&#39;ll Love</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto"> <p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Simple, transparent pricing with zero additional fees. Simple, transparent pricing with zero additional fees.
</p> </p>
@ -60,7 +60,7 @@ export default function Pricing() {
<div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3"> <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
<motion.div <motion.div
className={`relative overflow-hidden rounded-xl border bg-gray-800 text-card-foreground shadow transition-all duration-300 ${hoveredCard === 0 ? "border-gray-700" : "border-border"}`} className={`relative overflow-hidden rounded-xl border bg-slate-200 dark:bg-gray-800 text-card-foreground shadow transition-all duration-300 ${hoveredCard === 0 ? "border-gray-700" : "border-border"} text-background`}
variants={cardVariants} variants={cardVariants}
initial="default" initial="default"
animate={hoveredCard === 0 ? "hover" : "default"} animate={hoveredCard === 0 ? "hover" : "default"}
@ -70,7 +70,7 @@ export default function Pricing() {
<div className="p-6"> <div className="p-6">
<div className="mb-4 flex items-center justify-between"> <div className="mb-4 flex items-center justify-between">
<h3 className="text-2xl font-bold">Everything</h3> <h3 className="text-2xl font-bold">Everything</h3>
<Badge variant="outline" className="text-xs font-medium bg-gray-900"> <Badge variant="outline" className="text-xs font-medium bg-background">
Most Popular Most Popular
</Badge> </Badge>
</div> </div>
@ -78,8 +78,8 @@ export default function Pricing() {
<span className="text-6xl font-bold">$0.00</span> <span className="text-6xl font-bold">$0.00</span>
<span className="text-muted-foreground ml-2">/mo</span> <span className="text-muted-foreground ml-2">/mo</span>
</div> </div>
<p className="text-sm text-muted-foreground mb-6"> <p className="text-sm text-secondary-foreground mb-6">
All the essential services you need, completely free. All the services we offer, completely free.
</p> </p>
<Link href="/account/login"> <Link href="/account/login">
<Button className="w-full" size="lg"> <Button className="w-full" size="lg">
@ -87,7 +87,8 @@ export default function Pricing() {
</Button> </Button>
</Link> </Link>
</div> </div>
<Separator /> {/* TODO: this seperator be improved in the future, i can't find a good color for this */}
<Separator className="bg-gray-700" />
<div className="p-6 space-y-4"> <div className="p-6 space-y-4">
<h4 className="text-sm font-medium">What&#39;s included:</h4> <h4 className="text-sm font-medium">What&#39;s included:</h4>
<div> <div>
@ -149,7 +150,7 @@ export default function Pricing() {
<span className="text-6xl font-bold">$0.00</span> <span className="text-6xl font-bold">$0.00</span>
<span className="text-muted-foreground ml-2">/M tokens</span> <span className="text-muted-foreground ml-2">/M tokens</span>
</div> </div>
<p className="text-sm text-muted-foreground mb-6">Access powerful AI models at cost price.</p> <p className="text-sm text-muted-foreground mb-6">Access powerful AI models at the best price.</p>
<Button className="w-full" size="lg" variant="outline" disabled> <Button className="w-full" size="lg" variant="outline" disabled>
<Clock /> Coming Soon <Clock /> Coming Soon
</Button> </Button>