mirror of
https://github.com/OwethuManagedServices/oms-website-nextjs.git
synced 2025-12-17 17:18:09 +00:00
Home page completed
This commit is contained in:
@ -1,43 +1,68 @@
|
||||
// components/Footer.tsx
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
import { FaLinkedin, FaInstagram } from "react-icons/fa"; // npm install react-icons
|
||||
import { FaLinkedin, FaInstagram } from "react-icons/fa";
|
||||
import Image from "next/image";
|
||||
const omsLogoUrl = "/oms-logo.svg";
|
||||
|
||||
const omsLogoUrl = "/oms-logo.svg"; // Ensure this exists in /public
|
||||
// const omsLogoDarkUrl = "/oms-logo-dark.svg"; // Optional dark mode logo
|
||||
|
||||
const Footer = () => {
|
||||
// In a real app, you might use useTheme to get the current theme
|
||||
// import { useTheme } from 'next-themes';
|
||||
// const { resolvedTheme } = useTheme();
|
||||
// const currentLogo = resolvedTheme === 'dark' && omsLogoDarkUrl ? omsLogoDarkUrl : omsLogoUrl;
|
||||
const currentLogo = omsLogoUrl; // Using default for now
|
||||
|
||||
return (
|
||||
<footer className="bg-dark text-light pt-16 pb-8">
|
||||
<div className="container mx-auto px-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-12 mb-12">
|
||||
{/* About/Logo */}
|
||||
// --- Force Dark Background ---
|
||||
// Use a specific dark color (e.g., var(--oms-black) or a dark gray from your vars)
|
||||
// Text color will default to light here for contrast
|
||||
<footer className="bg-[var(--oms-black)] text-[var(--oms-white)] pt-16 pb-8">
|
||||
{" "}
|
||||
{/* Or use --background from .dark */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 md:gap-12 mb-12">
|
||||
{/* About/Logo Section */}
|
||||
<div>
|
||||
<div className="flex items-center space-x-2 mb-4">
|
||||
<Image
|
||||
src={omsLogoUrl} // Use your actual logo path
|
||||
src={currentLogo}
|
||||
alt="OMS Logo"
|
||||
width={40} // Adjust size as needed
|
||||
width={40}
|
||||
height={40}
|
||||
priority // Load logo quickly
|
||||
priority
|
||||
// Optional: Add filter for dark bg if logo isn't ideal
|
||||
// className="dark:invert"
|
||||
/>
|
||||
<span className="text-xl font-bold text-light">OMS</span>
|
||||
{/* Ensure prominent text is bright */}
|
||||
<span className="text-xl font-bold text-[var(--oms-white)]">
|
||||
OMS
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-gray-400">Owethu Managed Services</p>
|
||||
<p className="text-sm text-gray-400 mt-2">
|
||||
{/* Use a slightly muted bright color for less prominent text */}
|
||||
<p className="text-sm text-[var(--oms-white)]/80">
|
||||
{" "}
|
||||
{/* Example: White with 80% opacity */}
|
||||
Owethu Managed Services
|
||||
</p>
|
||||
<p className="text-sm text-[var(--oms-white)]/80 mt-2">
|
||||
Where innovation meets excellence.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Quick Links */}
|
||||
{/* Quick Links Section */}
|
||||
<div>
|
||||
{/* Use primary color for headings */}
|
||||
<h5 className="text-lg font-semibold mb-4 text-primary">
|
||||
Quick Links
|
||||
</h5>
|
||||
{/* Use muted bright color for links, primary on hover */}
|
||||
<ul className="space-y-2">
|
||||
<li>
|
||||
<Link
|
||||
href="/about"
|
||||
className="hover:text-primary transition-colors duration-300"
|
||||
className="text-sm text-[var(--oms-white)]/80 hover:text-primary transition-colors"
|
||||
>
|
||||
About Us
|
||||
</Link>
|
||||
@ -45,7 +70,7 @@ const Footer = () => {
|
||||
<li>
|
||||
<Link
|
||||
href="/services"
|
||||
className="hover:text-primary transition-colors duration-300"
|
||||
className="text-sm text-[var(--oms-white)]/80 hover:text-primary transition-colors"
|
||||
>
|
||||
Services
|
||||
</Link>
|
||||
@ -53,7 +78,7 @@ const Footer = () => {
|
||||
<li>
|
||||
<Link
|
||||
href="/products"
|
||||
className="hover:text-primary transition-colors duration-300"
|
||||
className="text-sm text-[var(--oms-white)]/80 hover:text-primary transition-colors"
|
||||
>
|
||||
Products
|
||||
</Link>
|
||||
@ -61,7 +86,7 @@ const Footer = () => {
|
||||
<li>
|
||||
<Link
|
||||
href="/join-us"
|
||||
className="hover:text-primary transition-colors duration-300"
|
||||
className="text-sm text-[var(--oms-white)]/80 hover:text-primary transition-colors"
|
||||
>
|
||||
Join Our Team
|
||||
</Link>
|
||||
@ -69,7 +94,7 @@ const Footer = () => {
|
||||
<li>
|
||||
<Link
|
||||
href="/contact"
|
||||
className="hover:text-primary transition-colors duration-300"
|
||||
className="text-sm text-[var(--oms-white)]/80 hover:text-primary transition-colors"
|
||||
>
|
||||
Contact Us
|
||||
</Link>
|
||||
@ -77,29 +102,36 @@ const Footer = () => {
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Contact Info */}
|
||||
{/* Contact Info Section */}
|
||||
<div>
|
||||
<h5 className="text-lg font-semibold mb-4 text-primary">Contact</h5>
|
||||
<p className="text-sm text-gray-400 mb-2">
|
||||
<address className="text-sm text-[var(--oms-white)]/80 mb-2 not-italic">
|
||||
Unit 10 B Centuria Park
|
||||
<br />
|
||||
265 Von Willich Avenue
|
||||
<br />
|
||||
Die Hoewes, Centurion, 0159
|
||||
</address>
|
||||
<p className="text-sm text-[var(--oms-white)]/80 mb-2">
|
||||
Phone:{" "}
|
||||
<a href="tel:+27120513282" className="hover:text-primary">
|
||||
(012) 051 3282
|
||||
</a>
|
||||
</p>
|
||||
<p className="text-sm text-gray-400 mb-2">Phone: (012) 051 3282</p>
|
||||
<p className="text-sm text-gray-400 mb-2">
|
||||
<p className="text-sm text-[var(--oms-white)]/80 mb-2">
|
||||
Email:{" "}
|
||||
<a href="mailto:hello@oms.africa" className="hover:text-primary">
|
||||
hello@oms.africa
|
||||
</a>
|
||||
</p>
|
||||
{/* Social Icons - Use muted bright color, primary on hover */}
|
||||
<div className="flex space-x-4 mt-4">
|
||||
<a
|
||||
href="https://linkedin.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-gray-400 hover:text-primary"
|
||||
className="text-[var(--oms-white)]/70 hover:text-primary transition-colors"
|
||||
aria-label="LinkedIn"
|
||||
>
|
||||
<FaLinkedin size={24} />
|
||||
</a>
|
||||
@ -107,40 +139,45 @@ const Footer = () => {
|
||||
href="https://instagram.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-gray-400 hover:text-primary"
|
||||
className="text-[var(--oms-white)]/70 hover:text-primary transition-colors"
|
||||
aria-label="Instagram"
|
||||
>
|
||||
<FaInstagram size={24} />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Newsletter */}
|
||||
{/* Newsletter Section */}
|
||||
<div>
|
||||
<h5 className="text-lg font-semibold mb-4 text-primary">
|
||||
Newsletter
|
||||
</h5>
|
||||
<p className="text-sm text-gray-400 mb-3">
|
||||
<p className="text-sm text-[var(--oms-white)]/80 mb-3">
|
||||
Stay updated with our latest news.
|
||||
</p>
|
||||
<form className="flex flex-col sm:flex-row gap-2">
|
||||
{/* Input needs dark background styles */}
|
||||
<input
|
||||
type="email"
|
||||
placeholder="Enter your email"
|
||||
className="flex-grow px-4 py-2 rounded-md bg-gray-700 text-light border border-gray-600 focus:outline-none focus:ring-2 focus:ring-primary/50"
|
||||
aria-label="Email for newsletter"
|
||||
// Use dark variable for input bg/border, bright for text
|
||||
className="flex-grow px-4 py-2 rounded-lg bg-[var(--dark-input)] border border-[var(--dark-border)] text-[var(--dark-foreground)] placeholder:text-[var(--dark-muted-foreground)] focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-[var(--oms-black)]" // Ring offset needs dark bg
|
||||
/>
|
||||
{/* Keep button styling primary */}
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-primary text-dark px-4 py-2 rounded-md font-semibold hover:bg-primary/90 transition-colors duration-300"
|
||||
className="bg-primary text-primary-foreground px-4 py-2 rounded-lg font-semibold hover:bg-opacity-90 transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-[var(--oms-black)]" // Ring offset needs dark bg
|
||||
>
|
||||
Subscribe
|
||||
</button>
|
||||
</form>
|
||||
{/* TODO: Add Badges */}
|
||||
<div className="mt-6 space-x-4">
|
||||
<span className="inline-block bg-gray-600 px-3 py-1 rounded text-xs font-semibold">
|
||||
{/* Badges - Use a subtle dark bg */}
|
||||
<div className="mt-6 space-x-2 sm:space-x-4">
|
||||
<span className="inline-block bg-[var(--dark-secondary)] text-[var(--dark-secondary-foreground)] px-3 py-1 rounded-md text-xs font-medium">
|
||||
Salesforce Partner
|
||||
</span>
|
||||
<span className="inline-block bg-gray-600 px-3 py-1 rounded text-xs font-semibold">
|
||||
<span className="inline-block bg-[var(--dark-secondary)] text-[var(--dark-secondary-foreground)] px-3 py-1 rounded-md text-xs font-medium">
|
||||
BBB-EE Level X
|
||||
</span>
|
||||
</div>
|
||||
@ -148,16 +185,24 @@ const Footer = () => {
|
||||
</div>
|
||||
|
||||
{/* Bottom Bar */}
|
||||
<div className="border-t border-gray-700 pt-8 flex flex-col md:flex-row justify-between items-center text-sm text-gray-500">
|
||||
<p>
|
||||
{/* Use specific dark border, muted bright text */}
|
||||
<div className="border-t border-[var(--dark-border)] pt-8 flex flex-col md:flex-row justify-between items-center text-sm text-[var(--oms-white)]/70">
|
||||
<p className="text-center md:text-left mb-4 md:mb-0">
|
||||
© {new Date().getFullYear()} Owethu Managed Services. All Rights
|
||||
Reserved.
|
||||
</p>
|
||||
<div className="flex space-x-4 mt-4 md:mt-0">
|
||||
<Link href="/privacy-policy" className="hover:text-primary">
|
||||
<div className="flex space-x-4">
|
||||
{/* Links still hover to primary */}
|
||||
<Link
|
||||
href="/privacy-policy"
|
||||
className="hover:text-primary transition-colors"
|
||||
>
|
||||
Privacy Policy
|
||||
</Link>
|
||||
<Link href="/paia-popia" className="hover:text-primary">
|
||||
<Link
|
||||
href="/paia-popia"
|
||||
className="hover:text-primary transition-colors"
|
||||
>
|
||||
PAIA & POPIA
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
import React, { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { usePathname } from "next/navigation";
|
||||
// Use usePathname only if needed for active state logic not shown here
|
||||
// import { usePathname } from "next/navigation";
|
||||
import {
|
||||
FiChevronDown,
|
||||
FiClipboard,
|
||||
@ -12,11 +13,12 @@ import {
|
||||
FiMenu,
|
||||
FiX,
|
||||
} from "react-icons/fi";
|
||||
import ThemeToggle from "./ThemeToggle";
|
||||
import ThemeToggle from "./ThemeToggle"; // Assuming ThemeToggle component exists
|
||||
|
||||
const omsLogoUrl = "/oms-logo.svg";
|
||||
const omsLogoUrl = "/oms-logo.svg"; // Ensure this is in your /public folder
|
||||
|
||||
// --- Basic Dropdown Placeholder ---
|
||||
// --- Basic Dropdown Component ---
|
||||
// Using semantic variables for background, text, and borders
|
||||
type DropdownMenuProps = {
|
||||
trigger: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
@ -27,16 +29,17 @@ const DropdownMenu = ({
|
||||
children,
|
||||
menuClasses = "w-48",
|
||||
}: DropdownMenuProps) => (
|
||||
// Using group-focus-within for better keyboard/touch accessibility
|
||||
<div className="relative group">
|
||||
<button className="flex items-center space-x-1 text-sm font-medium focus:outline-none inherit-color group">
|
||||
{trigger}
|
||||
<FiChevronDown className="w-4 h-4 transition-transform duration-200 group-hover:rotate-180" />
|
||||
<FiChevronDown className="w-4 h-4 transition-transform duration-200 group-hover:rotate-180 group-focus-within:rotate-180" />
|
||||
</button>
|
||||
<div
|
||||
className={`
|
||||
absolute left-0 mt-2 ${menuClasses} origin-top-left rounded-md shadow-lg z-50
|
||||
bg-light border border-gray-200 dark:bg-[var(--color-dark-bg-secondary)] dark:border-[var(--color-dark-border)]
|
||||
opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200
|
||||
bg-card border border-border {/* USE SEMANTIC VARS */}
|
||||
opacity-0 invisible group-hover:opacity-100 group-hover:visible group-focus-within:opacity-100 group-focus-within:visible transition-all duration-200
|
||||
`}
|
||||
>
|
||||
<div className="py-1">{children}</div>
|
||||
@ -44,34 +47,40 @@ const DropdownMenu = ({
|
||||
</div>
|
||||
);
|
||||
|
||||
// Dropdown Link component using semantic variables
|
||||
type DropdownLinkProps = {
|
||||
href: string;
|
||||
children: React.ReactNode;
|
||||
onClick?: () => void; // Added onClick for mobile menu closure
|
||||
};
|
||||
const DropdownLink = ({ href, children }: DropdownLinkProps) => (
|
||||
const DropdownLink = ({ href, children, onClick }: DropdownLinkProps) => (
|
||||
<Link
|
||||
href={href}
|
||||
className="block px-4 py-2 text-sm text-gray-700 dark:text-[var(--color-dark-text-secondary)] hover:bg-gray-100 hover:text-primary dark:hover:bg-gray-700 dark:hover:text-primary"
|
||||
onClick={onClick} // Call onClick if provided
|
||||
className="block w-full text-left px-4 py-2 text-sm text-card-foreground hover:bg-secondary hover:text-primary" // USE SEMANTIC VARS
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
// --- End Dropdown Placeholder ---
|
||||
// --- End Dropdown Component ---
|
||||
|
||||
const Header = () => {
|
||||
const pathname = usePathname() || "/";
|
||||
const isActive = (path: string) => pathname === path;
|
||||
// If you need pathname for active states later:
|
||||
// const pathname = usePathname() || "/";
|
||||
// const isActive = (path: string) => pathname === path;
|
||||
// const isActive = (path: string) => false; // Simple placeholder
|
||||
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
|
||||
const toggleMenu = () => setIsMenuOpen((open) => !open);
|
||||
// Close menu when a link is clicked
|
||||
const handleMobileLinkClick = () => setIsMenuOpen(false);
|
||||
|
||||
// Optionally switch logo based on a global CSS class or via next-themes
|
||||
const currentLogo = omsLogoUrl;
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-50 shadow-md bg-light dark:bg-dark-bg dark:border-b dark:border-dark-border">
|
||||
// Use semantic variables for header background and border
|
||||
<header className="sticky top-0 z-50 shadow-md bg-background border-b border-border">
|
||||
{/* Top Row */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
@ -88,40 +97,36 @@ const Header = () => {
|
||||
height={40}
|
||||
priority
|
||||
/>
|
||||
<span className="text-xl font-bold text-dark dark:text-light hidden sm:inline">
|
||||
{/* Use semantic variable for text color */}
|
||||
<span className="text-xl font-bold text-foreground hidden sm:inline">
|
||||
Owethu Managed Services
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<nav className="hidden md:flex items-center space-x-6 lg:space-x-8">
|
||||
{/* Use semantic variables for text, hover uses primary */}
|
||||
<Link
|
||||
href="/"
|
||||
className={`text-sm font-medium ${
|
||||
isActive("/")
|
||||
? "text-primary font-semibold"
|
||||
: "text-gray-700 dark:text-[var(--color-dark-text-secondary)] hover:text-primary"
|
||||
}`}
|
||||
className={`text-sm font-medium text-foreground/80 hover:text-primary`}
|
||||
/* Active state example (requires usePathname) */
|
||||
/* ${isActive("/") ? "text-primary font-semibold" : "text-foreground/80 hover:text-primary"} */
|
||||
>
|
||||
Home
|
||||
</Link>
|
||||
<Link
|
||||
href="/about"
|
||||
className={`text-sm font-medium ${
|
||||
pathname.startsWith("/about")
|
||||
? "text-primary font-semibold"
|
||||
: "text-gray-700 dark:text-[var(--color-dark-text-secondary)] hover:text-primary"
|
||||
}`}
|
||||
className={`text-sm font-medium text-foreground/80 hover:text-primary`}
|
||||
/* Active state example */
|
||||
/* ${pathname.startsWith("/about") ? "text-primary font-semibold" : "text-foreground/80 hover:text-primary"} */
|
||||
>
|
||||
About Us
|
||||
</Link>
|
||||
<Link
|
||||
href="/contact"
|
||||
className={`text-sm font-medium ${
|
||||
isActive("/contact")
|
||||
? "text-primary font-semibold"
|
||||
: "text-gray-700 dark:text-[var(--color-dark-text-secondary)] hover:text-primary"
|
||||
}`}
|
||||
className={`text-sm font-medium text-foreground/80 hover:text-primary`}
|
||||
/* Active state example */
|
||||
/* ${isActive("/contact") ? "text-primary font-semibold" : "text-foreground/80 hover:text-primary"} */
|
||||
>
|
||||
Contact Us
|
||||
</Link>
|
||||
@ -131,9 +136,10 @@ const Header = () => {
|
||||
<div className="hidden md:flex items-center space-x-4">
|
||||
<ThemeToggle />
|
||||
|
||||
{/* Use semantic variables for button */}
|
||||
<Link
|
||||
href="/request-demo"
|
||||
className="flex items-center text-sm font-medium bg-primary text-dark px-3 py-1.5 rounded-md hover:bg-opacity-90 transition-colors"
|
||||
className="flex items-center text-sm font-medium bg-primary text-primary-foreground px-3 py-1.5 rounded-lg hover:bg-opacity-90 transition-colors" // Use rounded-lg from radius
|
||||
title="Request a Demo"
|
||||
>
|
||||
<FiClipboard className="w-4 h-4 mr-1.5" />
|
||||
@ -143,12 +149,13 @@ const Header = () => {
|
||||
|
||||
{/* Mobile Buttons */}
|
||||
<div className="md:hidden flex items-center">
|
||||
<ThemeToggle />
|
||||
|
||||
<ThemeToggle /> {/* Theme toggle appears first */}
|
||||
<button
|
||||
onClick={toggleMenu}
|
||||
className="text-gray-600 dark:text-gray-400 hover:text-primary dark:hover:text-primary focus:outline-none ml-3"
|
||||
className="text-foreground/60 hover:text-primary focus:outline-none ml-3" // Use semantic muted color, hover primary
|
||||
aria-label="Toggle menu"
|
||||
aria-expanded={isMenuOpen}
|
||||
aria-controls="mobile-menu"
|
||||
>
|
||||
{isMenuOpen ? (
|
||||
<FiX className="w-6 h-6" />
|
||||
@ -161,34 +168,48 @@ const Header = () => {
|
||||
</div>
|
||||
|
||||
{/* Secondary Row */}
|
||||
<div className="bg-primary dark:bg-primary">
|
||||
<div className="bg-primary">
|
||||
{" "}
|
||||
{/* Keep gold background */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{/* Hide on mobile */}
|
||||
<div className="hidden md:flex justify-between items-center h-12">
|
||||
<nav className="flex items-center space-x-6 lg:space-x-8 text-dark">
|
||||
<DropdownMenu trigger={<span>Services</span>}>
|
||||
<DropdownLink href="/services/resource-augmentation">
|
||||
Resource Augmentation
|
||||
</DropdownLink>
|
||||
<DropdownLink href="/services/project-management">
|
||||
Project Management
|
||||
</DropdownLink>
|
||||
<DropdownLink href="/services/product-development">
|
||||
Product Development
|
||||
</DropdownLink>
|
||||
</DropdownMenu>
|
||||
<DropdownMenu trigger={<span>Products</span>}>
|
||||
<DropdownLink href="/products/obse">OBSE</DropdownLink>
|
||||
</DropdownMenu>
|
||||
<DropdownMenu trigger={<span>Join Our Team</span>}>
|
||||
<DropdownLink href="/join-us/vacancies">Vacancies</DropdownLink>
|
||||
<DropdownLink href="/join-us/portal">
|
||||
Recruitment Portal
|
||||
</DropdownLink>
|
||||
</DropdownMenu>
|
||||
{/* Use primary-foreground for text color */}
|
||||
<nav className="flex items-center space-x-6 lg:space-x-8 text-primary-foreground">
|
||||
{/* Wrap dropdown triggers for consistent hover */}
|
||||
<div className="hover:text-opacity-80 transition-opacity">
|
||||
<DropdownMenu trigger={<span>Services</span>}>
|
||||
<DropdownLink href="/services/resource-augmentation">
|
||||
Resource Augmentation
|
||||
</DropdownLink>
|
||||
<DropdownLink href="/services/project-management">
|
||||
Project Management
|
||||
</DropdownLink>
|
||||
<DropdownLink href="/services/product-development">
|
||||
Product Development
|
||||
</DropdownLink>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
<div className="hover:text-opacity-80 transition-opacity">
|
||||
<DropdownMenu trigger={<span>Products</span>}>
|
||||
<DropdownLink href="/products/obse">OBSE</DropdownLink>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
<div className="hover:text-opacity-80 transition-opacity">
|
||||
<DropdownMenu trigger={<span>Join Our Team</span>}>
|
||||
<DropdownLink href="/join-us/vacancies">
|
||||
Vacancies
|
||||
</DropdownLink>
|
||||
<DropdownLink href="/join-us/portal">
|
||||
Recruitment Portal
|
||||
</DropdownLink>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</nav>
|
||||
{/* Use primary-foreground for link */}
|
||||
<Link
|
||||
href="/services"
|
||||
className="flex items-center text-sm font-medium text-dark hover:text-opacity-80 transition-opacity group"
|
||||
className="flex items-center text-sm font-medium text-primary-foreground hover:text-opacity-80 transition-opacity group"
|
||||
>
|
||||
Explore Our Offerings
|
||||
<FiArrowRight className="w-4 h-4 ml-1.5 transition-transform duration-200 group-hover:translate-x-1" />
|
||||
@ -200,105 +221,74 @@ const Header = () => {
|
||||
{/* Mobile Menu Panel */}
|
||||
<div
|
||||
id="mobile-menu"
|
||||
className={`md:hidden absolute top-full left-0 w-full shadow-lg transition-all duration-300 ease-in-out overflow-hidden bg-light dark:bg-[var(--color-dark-bg-secondary)] border-t border-gray-200 dark:border-[var(--color-dark-border)] ${
|
||||
isMenuOpen ? "max-h-screen py-4" : "max-h-0 py-0"
|
||||
// Use semantic variables for background and border
|
||||
className={`md:hidden absolute top-full left-0 w-full shadow-lg transition-all duration-300 ease-in-out overflow-hidden bg-card border-t border-border ${
|
||||
isMenuOpen
|
||||
? "max-h-[calc(100vh-4rem)] py-4 overflow-y-auto"
|
||||
: "max-h-0 py-0" // Animate height, allow scroll
|
||||
}`}
|
||||
>
|
||||
<nav className="container mx-auto px-4 sm:px-6 lg:px-8 flex flex-col space-y-3">
|
||||
<Link
|
||||
href="/"
|
||||
onClick={handleMobileLinkClick}
|
||||
className={`block py-2 text-base font-medium ${
|
||||
isActive("/")
|
||||
? "text-primary font-semibold"
|
||||
: "text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
|
||||
}`}
|
||||
>
|
||||
{/* Use semantic variable for text color */}
|
||||
<nav className="container mx-auto px-4 sm:px-6 lg:px-8 flex flex-col space-y-1 text-foreground">
|
||||
{" "}
|
||||
{/* Reduced space-y */}
|
||||
{/* Simplified mobile links, using DropdownLink component for consistency */}
|
||||
<DropdownLink href="/" onClick={handleMobileLinkClick}>
|
||||
Home
|
||||
</Link>
|
||||
<Link
|
||||
href="/about"
|
||||
onClick={handleMobileLinkClick}
|
||||
className={`block py-2 text-base font-medium ${
|
||||
pathname.startsWith("/about")
|
||||
? "text-primary font-semibold"
|
||||
: "text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
|
||||
}`}
|
||||
>
|
||||
</DropdownLink>
|
||||
<DropdownLink href="/about" onClick={handleMobileLinkClick}>
|
||||
About Us
|
||||
</Link>
|
||||
|
||||
<span className="pt-2 text-xs uppercase text-gray-500 dark:text-gray-400">
|
||||
</DropdownLink>
|
||||
{/* Maybe use collapsible sections here in a real app, but simple list for now */}
|
||||
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
|
||||
Services
|
||||
</span>
|
||||
<Link
|
||||
<DropdownLink
|
||||
href="/services/resource-augmentation"
|
||||
onClick={handleMobileLinkClick}
|
||||
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
|
||||
>
|
||||
Resource Augmentation
|
||||
</Link>
|
||||
<Link
|
||||
</DropdownLink>
|
||||
<DropdownLink
|
||||
href="/services/project-management"
|
||||
onClick={handleMobileLinkClick}
|
||||
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
|
||||
>
|
||||
Project Management
|
||||
</Link>
|
||||
<Link
|
||||
</DropdownLink>
|
||||
<DropdownLink
|
||||
href="/services/product-development"
|
||||
onClick={handleMobileLinkClick}
|
||||
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
|
||||
>
|
||||
Product Development
|
||||
</Link>
|
||||
|
||||
<span className="pt-2 text-xs uppercase text-gray-500 dark:text-gray-400">
|
||||
</DropdownLink>
|
||||
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
|
||||
Products
|
||||
</span>
|
||||
<Link
|
||||
href="/products/obse"
|
||||
onClick={handleMobileLinkClick}
|
||||
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
|
||||
>
|
||||
<DropdownLink href="/products/obse" onClick={handleMobileLinkClick}>
|
||||
OBSE
|
||||
</Link>
|
||||
|
||||
<span className="pt-2 text-xs uppercase text-gray-500 dark:text-gray-400">
|
||||
</DropdownLink>
|
||||
<span className="pt-3 pb-1 text-xs uppercase text-muted-foreground">
|
||||
Join Us
|
||||
</span>
|
||||
<Link
|
||||
<DropdownLink
|
||||
href="/join-us/vacancies"
|
||||
onClick={handleMobileLinkClick}
|
||||
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
|
||||
>
|
||||
Vacancies
|
||||
</Link>
|
||||
<Link
|
||||
href="/join-us/portal"
|
||||
onClick={handleMobileLinkClick}
|
||||
className="block py-1 pl-3 text-base font-medium text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
|
||||
>
|
||||
</DropdownLink>
|
||||
<DropdownLink href="/join-us/portal" onClick={handleMobileLinkClick}>
|
||||
Recruitment Portal
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
href="/contact"
|
||||
onClick={handleMobileLinkClick}
|
||||
className={`block py-2 text-base font-medium ${
|
||||
isActive("/contact")
|
||||
? "text-primary font-semibold"
|
||||
: "text-gray-700 dark:text-[var(--color-dark-text)] hover:text-primary"
|
||||
}`}
|
||||
>
|
||||
</DropdownLink>
|
||||
<DropdownLink href="/contact" onClick={handleMobileLinkClick}>
|
||||
Contact Us
|
||||
</Link>
|
||||
|
||||
</DropdownLink>
|
||||
{/* Demo button at the bottom */}
|
||||
<div className="pt-4">
|
||||
<Link
|
||||
href="/request-demo"
|
||||
onClick={handleMobileLinkClick}
|
||||
className="flex w-full justify-center items-center text-sm font-medium bg-primary text-dark px-4 py-2 rounded-md hover:bg-opacity-90 transition-colors"
|
||||
// Use semantic variables for button style
|
||||
className="flex w-full justify-center items-center text-sm font-medium bg-primary text-primary-foreground px-4 py-2 rounded-lg hover:bg-opacity-90 transition-colors"
|
||||
title="Request a Demo"
|
||||
>
|
||||
<FiClipboard className="w-4 h-4 mr-1.5" />
|
||||
|
||||
@ -4,7 +4,7 @@ import Link from "next/link";
|
||||
|
||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
href?: string;
|
||||
variant?: "primary" | "secondary" | "outline";
|
||||
variant?: "primary" | "secondary" | "outline" | "ghost" | "destructive"; // Added more variants
|
||||
size?: "sm" | "md" | "lg";
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
@ -18,20 +18,25 @@ const Button: React.FC<ButtonProps> = ({
|
||||
className = "",
|
||||
...props
|
||||
}) => {
|
||||
// Base styles including focus ring using semantic vars
|
||||
const baseStyle =
|
||||
"inline-flex items-center justify-center rounded-md font-semibold transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2";
|
||||
"inline-flex items-center justify-center rounded-lg font-semibold transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background";
|
||||
|
||||
// Variant styles using semantic vars (Tailwind classes generated via @theme)
|
||||
const variantStyles = {
|
||||
primary: "bg-primary text-dark hover:bg-primary/90 focus:ring-primary/50",
|
||||
secondary: "bg-dark text-light hover:bg-gray-800 focus:ring-dark/50",
|
||||
primary: "bg-primary text-primary-foreground hover:bg-primary/90", // bg-primary generated from --primary
|
||||
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
outline:
|
||||
"border border-primary text-primary hover:bg-primary hover:text-dark focus:ring-primary/50",
|
||||
"border border-border bg-transparent hover:bg-accent hover:text-accent-foreground",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
};
|
||||
|
||||
const sizeStyles = {
|
||||
sm: "px-4 py-2 text-sm",
|
||||
md: "px-6 py-3 text-base",
|
||||
lg: "px-8 py-4 text-lg",
|
||||
sm: "px-3 py-1.5 text-sm",
|
||||
md: "px-4 py-2 text-base",
|
||||
lg: "px-6 py-3 text-lg",
|
||||
};
|
||||
|
||||
const combinedClassName = `${baseStyle} ${variantStyles[variant]} ${sizeStyles[size]} ${className}`;
|
||||
@ -45,7 +50,7 @@ const Button: React.FC<ButtonProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<button className={combinedClassName} {...props}>
|
||||
<button type="button" className={combinedClassName} {...props}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user