fixed the navbar and edited the themes config and edited the home page and enhancced the canves background joints and lines with more shapes
All checks were successful
Build frontend / build (push) Successful in 37s

This commit is contained in:
mouazkh
2026-01-22 17:37:39 +03:00
parent 28d089534b
commit 4ec438b9f5
8 changed files with 516 additions and 328 deletions

View File

@ -1,4 +1,3 @@
import React, { useState, useEffect } from "react";
import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom";
import { AnimatePresence, LayoutGroup } from "framer-motion";
@ -25,7 +24,6 @@ import DepartmentDetail7 from "./Components/Sections/DepartmentDetail7/Departmen
import DepartmentDetail8 from "./Components/Sections/DepartmentDetail8/DepartmentDetail8";
import DepartmentDetail9 from "./Components/Sections/DepartmentDetail9/DepartmentDetail9";
const MainPage = ({ theme }) => {
return (
<div className="min-h-screen bg-transparent">
@ -70,7 +68,6 @@ function RouterView({ theme, toggleTheme }) {
<Route path="/department-detail8" element={<DepartmentDetail8 />} />
<Route path="/department-detail9" element={<DepartmentDetail9 />} />
</Routes>
</AnimatePresence>
</LayoutGroup>
@ -88,13 +85,15 @@ function Layout({ theme, toggleTheme }) {
"/department-detail6",
"/department-detail7",
"/department-detail8",
"/department-detail9"
"/department-detail9",
];
const excludedPrefixes = ["/departments/"];
const isExcludedExact = excludedExactPaths.includes(location.pathname);
const isExcludedPrefix = excludedPrefixes.some((p) => location.pathname.startsWith(p));
const isExcludedPrefix = excludedPrefixes.some((p) =>
location.pathname.startsWith(p),
);
const hideNavbar = isExcludedExact || isExcludedPrefix;
@ -114,13 +113,16 @@ function Layout({ theme, toggleTheme }) {
}
const App = () => {
const [theme, setTheme] = useState("light");
const [theme, setTheme] = useState("dark");
useEffect(() => {
console.log("Current theme:", theme);
console.log("HTML has dark class:", document.documentElement.classList.contains('dark'));
console.log(
"HTML has dark class:",
document.documentElement.classList.contains("dark"),
);
const canvas = document.querySelector('.background-canvas');
const canvas = document.querySelector(".background-canvas");
if (canvas) {
console.log("Canvas found:", canvas);
console.log("Canvas dimensions:", canvas.width, "x", canvas.height);
@ -131,14 +133,16 @@ const App = () => {
useEffect(() => {
const savedTheme = localStorage.getItem("theme");
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
if (savedTheme === "dark" || (!savedTheme && prefersDark)) {
if (savedTheme === "light") {
setTheme("light");
document.documentElement.classList.remove("dark");
} else {
setTheme("dark");
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
setTheme("light");
}
}, []);

View File

@ -18,10 +18,14 @@ body {
top: 0 !important;
left: 0 !important;
width: 100vw !important;
height: 100vh !important;
height: 100vh !important; /* Fallback */
height: 100dvh !important; /* Dynamic Viewport Height for mobile */
z-index: -1 !important;
pointer-events: none !important;
overflow: hidden !important;
background-color: var(
--bg-color
); /* Ensure background color is consistent even if canvas lags */
}
::-webkit-scrollbar {

View File

@ -1,7 +1,7 @@
import React, { useRef, useEffect, useState } from 'react';
import './BackgroundCanvas.css';
import React, { useRef, useEffect, useState } from "react";
import "./BackgroundCanvas.css";
const BackgroundCanvas = ({ theme = 'light' }) => {
const BackgroundCanvas = ({ theme = "light" }) => {
const canvasRef = useRef(null);
const animationRef = useRef(null);
const jointsRef = useRef([]);
@ -23,10 +23,14 @@ const BackgroundCanvas = ({ theme = 'light' }) => {
constructor(position, vector) {
this.position = position;
this.vector = vector;
this.speed = 0.5;
this.w = 2;
this.h = 2;
this.speed = Math.random() * 1.5 + 0.5;
this.bone_length = 150;
const shapes = ["circle", "triangle", "square", "pentagon"];
this.shape = shapes[Math.floor(Math.random() * shapes.length)];
this.size = Math.random() * 4 + 3;
this.angle = 0;
this.angularSpeed = (Math.random() - 0.5) * 0.1;
this.pulse = Math.random() * Math.PI * 2;
}
}
@ -41,7 +45,7 @@ const BackgroundCanvas = ({ theme = 'light' }) => {
{
x: Math.random() * 2 - 1,
y: Math.random() * 2 - 1,
}
},
);
});
return arr;
@ -52,6 +56,9 @@ const BackgroundCanvas = ({ theme = 'light' }) => {
joint.position.x += joint.vector.x * joint.speed;
joint.position.y += joint.vector.y * joint.speed;
joint.angle += joint.angularSpeed;
joint.pulse += 0.05;
if (joint.position.x < 0) joint.position.x = world.width;
if (joint.position.x > world.width) joint.position.x = 0;
if (joint.position.y < 0) joint.position.y = world.height;
@ -63,14 +70,14 @@ const BackgroundCanvas = ({ theme = 'light' }) => {
const len = joints.length;
let lineColor, pointColor, backgroundColor;
if (theme === 'dark') {
backgroundColor = '#446a85';
lineColor = '#FFFFFF';
pointColor = '#F5EEE6';
if (theme === "dark") {
backgroundColor = "#313131";
lineColor = "#F5EEE6";
pointColor = "#e06923";
} else {
backgroundColor = '#d3dde3';
lineColor = '#131313';
pointColor = '#041c40';
backgroundColor = "#f1f1f1ff";
lineColor = "rgba(49, 49, 49, 0.3)"; // More subtle lines
pointColor = "#041c40";
}
ctx.fillStyle = backgroundColor;
@ -80,7 +87,7 @@ const BackgroundCanvas = ({ theme = 'light' }) => {
for (let j = i + 1; j < len; j += 3) {
const length = Math.hypot(
joints[j].position.x - joints[i].position.x,
joints[j].position.y - joints[i].position.y
joints[j].position.y - joints[i].position.y,
);
if (length <= joints[i].bone_length) {
@ -88,25 +95,57 @@ const BackgroundCanvas = ({ theme = 'light' }) => {
ctx.strokeStyle = lineColor;
ctx.lineWidth = camera.zoom * (30 / length);
ctx.moveTo(
view.width / 2 + (joints[i].position.x - camera.position.x) * camera.zoom,
view.height / 2 + (joints[i].position.y - camera.position.y) * camera.zoom
view.width / 2 +
(joints[i].position.x - camera.position.x) * camera.zoom,
view.height / 2 +
(joints[i].position.y - camera.position.y) * camera.zoom,
);
ctx.lineTo(
view.width / 2 + (joints[j].position.x - camera.position.x) * camera.zoom,
view.height / 2 + (joints[j].position.y - camera.position.y) * camera.zoom
view.width / 2 +
(joints[j].position.x - camera.position.x) * camera.zoom,
view.height / 2 +
(joints[j].position.y - camera.position.y) * camera.zoom,
);
ctx.stroke();
ctx.closePath();
}
}
ctx.fillStyle = pointColor;
ctx.fillRect(
view.width / 2 + ((joints[i].position.x - camera.position.x) - joints[i].w / 2) * camera.zoom,
view.height / 2 + ((joints[i].position.y - camera.position.y) - joints[i].w / 2) * camera.zoom,
joints[i].w * camera.zoom,
joints[i].h * camera.zoom
const currentSize =
(joints[i].size + Math.sin(joints[i].pulse) * 1.5) * camera.zoom;
ctx.save();
ctx.translate(
view.width / 2 +
(joints[i].position.x - camera.position.x) * camera.zoom,
view.height / 2 +
(joints[i].position.y - camera.position.y) * camera.zoom,
);
ctx.rotate(joints[i].angle);
ctx.fillStyle = pointColor;
ctx.beginPath();
if (joints[i].shape === "circle") {
ctx.arc(0, 0, currentSize, 0, Math.PI * 2);
} else if (joints[i].shape === "triangle") {
ctx.moveTo(0, -currentSize);
ctx.lineTo(currentSize, currentSize);
ctx.lineTo(-currentSize, currentSize);
} else if (joints[i].shape === "square") {
ctx.rect(-currentSize / 2, -currentSize / 2, currentSize, currentSize);
} else if (joints[i].shape === "pentagon") {
for (let k = 0; k < 5; k++) {
ctx.lineTo(
currentSize * Math.cos((k * 2 * Math.PI) / 5 - Math.PI / 2),
currentSize * Math.sin((k * 2 * Math.PI) / 5 - Math.PI / 2),
);
}
}
ctx.fill();
ctx.closePath();
ctx.restore();
}
};
@ -131,7 +170,7 @@ const initCanvas = () => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
const ctx = canvas.getContext("2d");
const view = {
width: window.innerWidth,
height: window.innerHeight,
@ -150,15 +189,19 @@ const initCanvas = () => {
x: worldRef.current.width / 2,
y: worldRef.current.height / 2,
},
1
1,
);
const isMobile = window.innerWidth < 768;
const numberOfJoints = isMobile ? 80 : 300;
jointsRef.current = generateJoints(numberOfJoints, worldRef.current.width, worldRef.current.height);
const numberOfJoints = isMobile ? 150 : 600;
jointsRef.current = generateJoints(
numberOfJoints,
worldRef.current.width,
worldRef.current.height,
);
if (isMobile) {
jointsRef.current.forEach(joint => {
jointsRef.current.forEach((joint) => {
joint.bone_length = 120;
joint.speed = 0.4;
});
@ -169,7 +212,7 @@ const initCanvas = () => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
const ctx = canvas.getContext("2d");
const view = {
width: canvas.width,
height: canvas.height,
@ -178,7 +221,13 @@ const initCanvas = () => {
moveCamera(cameraRef.current, keysRef.current);
moveJoints(jointsRef.current, worldRef.current);
drawJoints(ctx, jointsRef.current, cameraRef.current, view, themeRef.current);
drawJoints(
ctx,
jointsRef.current,
cameraRef.current,
view,
themeRef.current,
);
animationRef.current = requestAnimationFrame(animate);
};
@ -196,12 +245,12 @@ const initCanvas = () => {
keysRef.current[e.keyCode] = 0;
};
window.addEventListener('keydown', handleKeyDown);
window.addEventListener('keyup', handleKeyUp);
window.addEventListener("keydown", handleKeyDown);
window.addEventListener("keyup", handleKeyUp);
return () => {
window.removeEventListener('keydown', handleKeyDown);
window.removeEventListener('keyup', handleKeyUp);
window.removeEventListener("keydown", handleKeyDown);
window.removeEventListener("keyup", handleKeyUp);
};
}, []);
@ -219,8 +268,8 @@ const initCanvas = () => {
};
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
useEffect(() => {
@ -235,11 +284,7 @@ const initCanvas = () => {
}, []);
return (
<canvas
ref={canvasRef}
className="background-canvas"
aria-hidden="true"
/>
<canvas ref={canvasRef} className="background-canvas" aria-hidden="true" />
);
};

View File

@ -9,7 +9,7 @@ const StyledWrapper = styled.div`
.theme-toggle-btn {
background: transparent;
border: none;
color: ${props => props.theme === 'dark' ? '#FFD700' : '#FF8C00'};
color: ${(props) => (props.theme === "dark" ? "#FFD700" : "#FF8C00")};
cursor: pointer;
padding: 0.5rem;
border-radius: 50%;
@ -20,7 +20,10 @@ const StyledWrapper = styled.div`
font-size: 1.5rem;
&:hover {
background: ${props => props.theme === 'dark' ? 'rgba(255, 215, 0, 0.1)' : 'rgba(255, 140, 0, 0.1)'};
background: ${(props) =>
props.theme === "dark"
? "rgba(255, 215, 0, 0.1)"
: "rgba(255, 140, 0, 0.1)"};
transform: scale(1.1);
}
@ -46,10 +49,11 @@ const ThemeToggle = ({ currentTheme, toggleTheme }) => {
);
};
const LanguageSwitcher = ({ i18n }) => {
const LanguageSwitcher = ({ i18n, currentTheme }) => {
const [open, setOpen] = useState(false);
const ref = useRef(null);
const current = i18n.language?.startsWith("ar") ? "ar" : "en";
const isDark = currentTheme === "dark";
useEffect(() => {
const onDocClick = (e) => {
@ -66,7 +70,14 @@ const LanguageSwitcher = ({ i18n }) => {
};
return (
<div ref={ref} style={{ position: "relative", display: "inline-flex", alignItems: "center" }}>
<div
ref={ref}
style={{
position: "relative",
display: "inline-flex",
alignItems: "center",
}}
>
<button
type="button"
aria-haspopup="true"
@ -77,7 +88,7 @@ const LanguageSwitcher = ({ i18n }) => {
borderRadius: "50%",
border: "none",
background: "transparent",
color: "inherit",
color: isDark ? "#e6e6e6" : "#313131",
cursor: "pointer",
display: "inline-flex",
alignItems: "center",
@ -98,12 +109,15 @@ const LanguageSwitcher = ({ i18n }) => {
position: "absolute",
top: "calc(100% + 8px)",
right: 0,
background: "linear-gradient(180deg,#111827,#0b1220)",
background: isDark
? "linear-gradient(180deg, #446a85, #2d4b5f)"
: "#ffffff",
borderRadius: 8,
boxShadow: "0 8px 30px rgba(2,6,23,0.5)",
padding: "6px",
zIndex: 60,
minWidth: 96,
border: isDark ? "none" : "1px solid #e5e7eb",
}}
>
<button
@ -117,8 +131,13 @@ const LanguageSwitcher = ({ i18n }) => {
textAlign: "left",
padding: "8px 10px",
borderRadius: 6,
background: current === "en" ? "rgba(255,183,77,0.12)" : "transparent",
color: "inherit",
background:
current === "en"
? isDark
? "rgba(255,183,77,0.12)"
: "#f3f4f6"
: "transparent",
color: isDark ? "inherit" : "#313131",
border: "none",
cursor: "pointer",
transition: "all 0.2s ease",
@ -139,8 +158,13 @@ const LanguageSwitcher = ({ i18n }) => {
textAlign: "left",
padding: "8px 10px",
borderRadius: 6,
background: current === "ar" ? "rgba(255,183,77,0.12)" : "transparent",
color: "inherit",
background:
current === "ar"
? isDark
? "rgba(255,183,77,0.12)"
: "#f3f4f6"
: "transparent",
color: isDark ? "inherit" : "#313131",
border: "none",
cursor: "pointer",
transition: "all 0.2s ease",
@ -169,11 +193,16 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
const scrollPosition = window.scrollY + 140;
for (const section of sections) {
const element = document.getElementById(section) || document.querySelector(`[name="${section}"]`);
const element =
document.getElementById(section) ||
document.querySelector(`[name="${section}"]`);
if (element) {
const offsetTop = element.offsetTop;
const offsetHeight = element.offsetHeight;
if (scrollPosition >= offsetTop && scrollPosition < offsetTop + offsetHeight) {
if (
scrollPosition >= offsetTop &&
scrollPosition < offsetTop + offsetHeight
) {
setActiveSection(section);
break;
}
@ -224,11 +253,13 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
}
.glass-nav {
background: linear-gradient(180deg, rgba(75,85,99,0.96), rgba(55,65,81,0.9));
color: #e6e6e6;
border-bottom: 1px solid rgba(255,255,255,0.05);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
background: rgba(227, 232, 236, 0.9);
color: #313131;
border-bottom: 1px solid rgba(4, 28, 64, 0.1);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
}
.nav-link {
@ -260,35 +291,35 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
.nav-link:hover .nav-pill {
transform: translateY(-6px) scale(1.06);
box-shadow:
0 14px 40px rgba(2,6,23,0.28),
0 6px 20px rgba(255,122,24,0.08);
background: linear-gradient(90deg, #ffd27a, #ff8a00);
color: #050505;
0 14px 40px rgba(224, 105, 35, 0.28),
0 6px 20px rgba(224, 105, 35, 0.08);
background: #e06923;
color: #ffffff;
}
.nav-link.active .nav-pill,
.mobile-drawer .nav-pill.active {
background: radial-gradient(circle at 30% 30%, #ffb347, #ff7a18) !important;
color: #0b0b0b !important;
background: #e06923 !important;
color: #ffffff !important;
transform: translateY(-3px) scale(1.03);
box-shadow: 0 8px 26px rgba(255, 122, 24, 0.16), 0 2px 6px rgba(0,0,0,0.12);
box-shadow: 0 8px 26px rgba(224, 105, 35, 0.25), 0 2px 6px rgba(0,0,0,0.12);
}
.nav-link:active .nav-pill,
.mobile-drawer a:active .nav-pill {
transition-duration: 0s !important;
transform: translateY(-3px) scale(1.03) !important;
background: radial-gradient(circle at 30% 30%, #ffb347, #ff7a18) !important;
color: #0b0b0b !important;
box-shadow: 0 8px 26px rgba(255, 122, 24, 0.16) !important;
background: #e06923 !important;
color: #ffffff !important;
box-shadow: 0 8px 26px rgba(224, 105, 35, 0.25) !important;
}
.nav-link:focus-visible .nav-pill,
.mobile-drawer a:focus-visible .nav-pill {
outline: none;
box-shadow: 0 0 0 6px rgba(255,165,0,0.14), 0 8px 30px rgba(255,122,24,0.12);
background: radial-gradient(circle at 30% 30%, #ffb347, #ff7a18);
color: #0b0b0b;
box-shadow: 0 0 0 6px rgba(224, 105, 35, 0.14), 0 8px 30px rgba(224, 105, 35, 0.12);
background: #e06923;
color: #ffffff;
transform: translateY(-3px) scale(1.02);
}
@ -345,7 +376,11 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
<div className="mx-auto max-w-screen-xl">
<div className="flex items-center justify-between h-14 px-2 md:px-4">
<div className="flex items-center gap-3">
<div aria-hidden className="logo-placeholder" style={{ width: 36, height: 36 }} />
<div
aria-hidden
className="logo-placeholder"
style={{ width: 36, height: 36 }}
/>
<div className="hidden md:flex items-center space-x-6 rtl:space-x-reverse ml-6">
<ul className="flex items-center gap-6">
{navItems.map((item) => {
@ -361,13 +396,25 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
onSetActive={() => setActiveSection(item.key)}
onClick={() => {
setActiveSection(item.key);
if (item.key === "home") scroll.scrollToTop({ duration: 600 });
if (item.key === "home")
scroll.scrollToTop({ duration: 600 });
if (menuOpen) setMenuOpen(false);
}}
className={`nav-link cursor-pointer text-sm md:text-lg ${isActive ? "active" : "text-slate-200 dark:text-slate-200/90"}`}
className={`nav-link cursor-pointer text-sm md:text-lg ${isActive ? "active" : ""}`}
style={{
color: isActive
? ""
: currentTheme === "dark"
? "rgba(229,231,235,0.95)"
: "#313131",
}}
aria-current={isActive ? "page" : undefined}
>
<span className={`nav-pill ${isActive ? "active" : ""}`}>{item.label}</span>
<span
className={`nav-pill ${isActive ? "active" : ""}`}
>
{item.label}
</span>
</Link>
</li>
);
@ -378,13 +425,22 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
<div className="flex items-center gap-3 md:gap-5">
<div className="hidden md:flex items-center gap-3">
<LanguageSwitcher i18n={i18n} />
<ThemeToggle currentTheme={currentTheme} toggleTheme={toggleTheme} />
<LanguageSwitcher i18n={i18n} currentTheme={currentTheme} />
<ThemeToggle
currentTheme={currentTheme}
toggleTheme={toggleTheme}
/>
</div>
<div className="md:hidden w-full">
{!isRtl ? (
<div style={{ display: "flex", alignItems: "center", width: "100%" }}>
<div
style={{
display: "flex",
alignItems: "center",
width: "100%",
}}
>
<div style={{ display: "flex", alignItems: "center" }}>
<button
onClick={() => setMenuOpen((s) => !s)}
@ -394,23 +450,56 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
style={{ marginRight: 8 }}
>
<span className="sr-only">Open main menu</span>
<svg className="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
{menuOpen ? <path d="M6 18L18 6M6 6l12 12" /> : <><path d="M3 6h18" /><path d="M3 12h18" /><path d="M3 18h18" /></>}
<svg
className="h-6 w-6"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden
>
{menuOpen ? (
<path d="M6 18L18 6M6 6l12 12" />
) : (
<>
<path d="M3 6h18" />
<path d="M3 12h18" />
<path d="M3 18h18" />
</>
)}
</svg>
</button>
</div>
<div style={{ flex: 1 }} />
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
<ThemeToggle currentTheme={currentTheme} toggleTheme={toggleTheme} />
<div
style={{ display: "flex", alignItems: "center", gap: 8 }}
>
<ThemeToggle
currentTheme={currentTheme}
toggleTheme={toggleTheme}
/>
<LanguageSwitcher i18n={i18n} />
</div>
</div>
) : (
<div style={{ display: "flex", alignItems: "center", width: "100%" }}>
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
<ThemeToggle currentTheme={currentTheme} toggleTheme={toggleTheme} />
<div
style={{
display: "flex",
alignItems: "center",
width: "100%",
}}
>
<div
style={{ display: "flex", alignItems: "center", gap: 8 }}
>
<ThemeToggle
currentTheme={currentTheme}
toggleTheme={toggleTheme}
/>
<LanguageSwitcher i18n={i18n} />
</div>
@ -425,8 +514,25 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
style={{ marginLeft: 8 }}
>
<span className="sr-only">Open main menu</span>
<svg className="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
{menuOpen ? <path d="M6 18L18 6M6 6l12 12" /> : <><path d="M3 6h18" /><path d="M3 12h18" /><path d="M3 18h18" /></>}
<svg
className="h-6 w-6"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden
>
{menuOpen ? (
<path d="M6 18L18 6M6 6l12 12" />
) : (
<>
<path d="M3 6h18" />
<path d="M3 12h18" />
<path d="M3 18h18" />
</>
)}
</svg>
</button>
</div>
@ -455,13 +561,18 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
onSetActive={() => setActiveSection(item.key)}
onClick={() => {
setActiveSection(item.key);
if (item.key === "home") scroll.scrollToTop({ duration: 600 });
if (item.key === "home")
scroll.scrollToTop({ duration: 600 });
setMenuOpen(false);
}}
className={`block w-full text-right px-3 py-2 rounded-md font-semibold text-base ${isActive ? "text-amber-400" : "text-slate-200 hover:text-amber-400"}`}
className={`block w-full text-right px-3 py-2 rounded-md font-semibold text-base ${isActive ? "text-amber-400" : "text-[#313131] dark:text-slate-200 hover:text-amber-400"}`}
aria-current={isActive ? "page" : undefined}
>
<span className={`nav-pill ${isActive ? "active" : ""}`}>{item.label}</span>
<span
className={`nav-pill ${isActive ? "active" : ""}`}
>
{item.label}
</span>
</Link>
</li>
);

View File

@ -14,11 +14,13 @@ export default function EngineeringHeroFlowbite() {
const { t, i18n } = useTranslation();
const defaultConfig = {
main_title: "عندما تطلب الرؤية مستشارًا، ويحتاج المخطط منفذًا استراتيجيًا…\nنكون القرار بالقيادة من الرؤية حتى التسليم",
main_title:
"عندما تطلب الرؤية مستشارًا، ويحتاج المخطط منفذًا استراتيجيًا…\nنكون القرار بالقيادة من الرؤية حتى التسليم",
subtitle:
"حلول متكاملة تشمل التصميم، التنفيذ، التشغيل، والصيانة\nللمشاريع الصناعية والمدنية، وفق أحدث المعايير والتقنيات",
primary_color: "#e67e22",
background_color: "#000000",
// background_color: "transparent",
background_color: "#7c2a2aff",
text_color: "#ffffff",
secondary_surface: "#95a5a6",
secondary_action: "#34495e",
@ -106,6 +108,7 @@ export default function EngineeringHeroFlowbite() {
const maxFont = 68;
const minFont = Math.max(Math.round(responsiveBase * 1.6), 14);
const root = document.documentElement;
const isDark = root.classList.contains("dark");
root.style.setProperty("--base", `${responsiveBase}px`);
if (main) {
@ -126,12 +129,14 @@ export default function EngineeringHeroFlowbite() {
const computedSize = Math.min(
Math.max(
Math.round(responsiveBase * headingMultiplier * lengthFactor),
minFont
minFont,
),
maxFont
maxFont,
);
main.style.fontSize = `${computedSize}px`;
main.style.color = config.text_color || defaultConfig.text_color;
main.style.color = isDark
? config.text_color || defaultConfig.text_color
: config.light_text_color || defaultConfig.light_text_color;
main.style.fontWeight = 800;
main.style.textAlign = isArabic ? "right" : "left";
main.style.whiteSpace = "normal";
@ -139,6 +144,7 @@ export default function EngineeringHeroFlowbite() {
main.style.overflowWrap = "anywhere";
main.style.direction = isArabic ? "rtl" : "ltr";
main.style.display = "block";
main.style.textShadow = isDark ? "0 4px 10px rgba(0,0,0,0.5)" : "none";
}
if (sub) {
@ -149,7 +155,9 @@ export default function EngineeringHeroFlowbite() {
sub.style.fontFamily = font;
const subSize = Math.round(responsiveBase * subtitleMultiplier);
sub.style.fontSize = `${subSize}px`;
sub.style.color = config.text_color || defaultConfig.text_color;
sub.style.color = isDark
? config.text_color || defaultConfig.text_color
: config.light_text_color || defaultConfig.light_text_color;
sub.style.textAlign = isArabic ? "right" : "left";
sub.style.maxWidth = "800px";
sub.style.whiteSpace = "normal";
@ -161,19 +169,19 @@ export default function EngineeringHeroFlowbite() {
root.style.setProperty(
"--ehb-primary",
config.primary_color || defaultConfig.primary_color
config.primary_color || defaultConfig.primary_color,
);
root.style.setProperty(
"--ehb-background",
config.background_color || defaultConfig.background_color
config.background_color || defaultConfig.background_color,
);
root.style.setProperty(
"--ehb-surface",
config.secondary_surface || defaultConfig.secondary_surface
config.secondary_surface || defaultConfig.secondary_surface,
);
root.style.setProperty(
"--ehb-action",
config.secondary_action || defaultConfig.secondary_action
config.secondary_action || defaultConfig.secondary_action,
);
};
@ -230,7 +238,19 @@ export default function EngineeringHeroFlowbite() {
:root { --ehb-primary: #e67e22; --ehb-background: #000000; --ehb-surface: #95a5a6; --ehb-action: #34495e; --base: 16px }
.hero-section{position:relative;width:100%;height:100%;overflow:hidden}
.hero-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(35deg, #57acd900 0%, rgb(151 162 179 / 0%) 50%, #47718b 100%);z-index:3}
.hero-overlay{
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
z-index:3;
background: transparent;
transition: background 0.3s ease;
}
.dark .hero-overlay {
background: linear-gradient(35deg, transparent 0%, transparent 50%, rgba(71, 113, 139, 0.2) 100%);
}
.hero-layout{position:relative;z-index:10;height:100%;display:flex;align-items:center;justify-content:space-between;padding:clamp(12px,4vw,40px);gap:2rem;direction:ltr;flex-direction:row}
.hero-layout.layout-ltr{flex-direction:row-reverse}
.hero-left{flex:1;display:flex;align-items:center;justify-content:flex-start;padding:20px;position:relative;flex-direction:column}

View File

@ -1,14 +1,14 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;600;700;800&display=swap');
@import url("https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;600;700;800&display=swap");
@layer base {
:root {
overflow-y: scroll !important;
--primary: #041c40;
--secondary: #e06923;
--tertiary: #313131;
--bg-color: #F5EEE6;
--bg-color: #e3e8ec;
--text-color: #313131;
--border-color: #d1c9be;
}
@ -18,7 +18,7 @@
--secondary: #e06923;
--tertiary: #313131;
--bg-color: #313131;
--text-color: #F5EEE6;
--text-color: #f5eee6;
--border-color: #4a4a4a;
}
body {
@ -28,9 +28,16 @@
min-height: 100vh;
width: 100vw;
overflow-x: hidden;
font-family: 'Cairo', system-ui, -apple-system, sans-serif;
font-family:
"Cairo",
system-ui,
-apple-system,
sans-serif;
color: var(--text-color);
transition: background-color 0.3s ease, color 0.3s ease;
background-color: var(--bg-color);
transition:
background-color 0.3s ease,
color 0.3s ease;
}
html {
overflow-y: scroll !important;

View File

@ -1,15 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
import './App.css';
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";
import "./App.css";
document.documentElement.style.setProperty('--bg-color', '#F5EEE6');
document.documentElement.style.setProperty('--text-color', '#131313');
document.documentElement.style.setProperty("--bg-color", "#F5EEE6");
document.documentElement.style.setProperty("--text-color", "#131313");
const root = ReactDOM.createRoot(document.getElementById('root'));
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
</React.StrictMode>,
);

View File

@ -1,25 +1,22 @@
module.exports = {
darkMode: 'class',
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
darkMode: "class",
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
colors: {
primary: '#041c40',
secondary: '#e06923',
'dark-bg': '#313131',
'light-bg': '#F5EEE6',
primary: "#041c40",
secondary: "#e06923",
"dark-bg": "#313131",
"light-bg": "#E3E8EC",
},
backdropBlur: {
'xs': '2px',
'sm': '4px',
'md': '8px',
'lg': '12px',
'xl': '20px',
xs: "2px",
sm: "4px",
md: "8px",
lg: "12px",
xl: "20px",
},
},
},
plugins: [],
}
};