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
All checks were successful
Build frontend / build (push) Successful in 37s
This commit is contained in:
80
src/App.jsx
80
src/App.jsx
@ -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">
|
||||
@ -49,8 +47,8 @@ function RouterView({ theme, toggleTheme }) {
|
||||
<LayoutGroup>
|
||||
<AnimatePresence mode="wait" initial={false}>
|
||||
<Routes location={location} key={location.pathname}>
|
||||
<Route
|
||||
path="/"
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
<div className="relative min-h-screen bg-transparent">
|
||||
<BackgroundCanvas theme={theme} />
|
||||
@ -58,19 +56,18 @@ function RouterView({ theme, toggleTheme }) {
|
||||
<MainPage theme={theme} />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
/>
|
||||
<Route path="/departments/:id" element={<DepartmentDetail />} />
|
||||
<Route path="/department-detail2" element={<DepartmentDetail2 />} />
|
||||
<Route path="/department-detail3" element={<DepartmentDetail3 />} />
|
||||
<Route path="/department-detail4" element={<DepartmentDetail4 />} />
|
||||
<Route path="/department-detail5" element={<DepartmentDetail5/>} />
|
||||
<Route path="/department-detail6" element={<DepartmentDetail6/>} />
|
||||
<Route path="/department-detail7" element={<DepartmentDetail7/>} />
|
||||
|
||||
<Route path="/department-detail8" element={<DepartmentDetail8/>} />
|
||||
<Route path="/department-detail9" element={<DepartmentDetail9/>} />
|
||||
<Route path="/department-detail3" element={<DepartmentDetail3 />} />
|
||||
<Route path="/department-detail4" element={<DepartmentDetail4 />} />
|
||||
<Route path="/department-detail5" element={<DepartmentDetail5 />} />
|
||||
<Route path="/department-detail6" element={<DepartmentDetail6 />} />
|
||||
<Route path="/department-detail7" element={<DepartmentDetail7 />} />
|
||||
|
||||
<Route path="/department-detail8" element={<DepartmentDetail8 />} />
|
||||
<Route path="/department-detail9" element={<DepartmentDetail9 />} />
|
||||
</Routes>
|
||||
</AnimatePresence>
|
||||
</LayoutGroup>
|
||||
@ -82,19 +79,21 @@ function Layout({ theme, toggleTheme }) {
|
||||
|
||||
const excludedExactPaths = [
|
||||
"/department-detail2",
|
||||
"/department-detail3" ,
|
||||
"/department-detail4" ,
|
||||
"/department-detail5" ,
|
||||
"/department-detail6" ,
|
||||
"/department-detail7",
|
||||
"/department-detail8",
|
||||
"/department-detail9"
|
||||
"/department-detail3",
|
||||
"/department-detail4",
|
||||
"/department-detail5",
|
||||
"/department-detail6",
|
||||
"/department-detail7",
|
||||
"/department-detail8",
|
||||
"/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;
|
||||
|
||||
@ -106,7 +105,7 @@ function Layout({ theme, toggleTheme }) {
|
||||
|
||||
<div style={{ paddingTop: navbarHeight }}>
|
||||
<RouterView theme={theme} toggleTheme={toggleTheme} />
|
||||
|
||||
|
||||
{location.pathname === "/" && <Footer />}
|
||||
</div>
|
||||
</>
|
||||
@ -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'));
|
||||
|
||||
const canvas = document.querySelector('.background-canvas');
|
||||
console.log(
|
||||
"HTML has dark class:",
|
||||
document.documentElement.classList.contains("dark"),
|
||||
);
|
||||
|
||||
const canvas = document.querySelector(".background-canvas");
|
||||
if (canvas) {
|
||||
console.log("Canvas found:", canvas);
|
||||
console.log("Canvas dimensions:", canvas.width, "x", canvas.height);
|
||||
@ -131,35 +133,37 @@ const App = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const savedTheme = localStorage.getItem("theme");
|
||||
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
|
||||
if (savedTheme === "dark" || (!savedTheme && prefersDark)) {
|
||||
const prefersDark = window.matchMedia(
|
||||
"(prefers-color-scheme: dark)",
|
||||
).matches;
|
||||
|
||||
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");
|
||||
}
|
||||
}, []);
|
||||
|
||||
const toggleTheme = () => {
|
||||
const newTheme = theme === "light" ? "dark" : "light";
|
||||
setTheme(newTheme);
|
||||
|
||||
|
||||
if (newTheme === "dark") {
|
||||
document.documentElement.classList.add("dark");
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark");
|
||||
}
|
||||
|
||||
|
||||
localStorage.setItem("theme", newTheme);
|
||||
};
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Layout theme={theme} toggleTheme={toggleTheme} />
|
||||
</BrowserRouter>
|
||||
<BrowserRouter>
|
||||
<Layout theme={theme} toggleTheme={toggleTheme} />
|
||||
</BrowserRouter>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
export default App;
|
||||
|
||||
@ -1,121 +1,125 @@
|
||||
html {
|
||||
overflow-x: hidden !important;
|
||||
height: 100% !important;
|
||||
overflow-x: hidden !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
min-height: 100% !important;
|
||||
position: relative !important;
|
||||
overflow-x: hidden !important;
|
||||
overflow-y: auto !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
min-height: 100% !important;
|
||||
position: relative !important;
|
||||
overflow-x: hidden !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
.background-canvas {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
z-index: -1 !important;
|
||||
pointer-events: none !important;
|
||||
overflow: hidden !important;
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100vw !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 {
|
||||
width: 0px !important;
|
||||
height: 0px !important;
|
||||
background: transparent !important;
|
||||
width: 0px !important;
|
||||
height: 0px !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: transparent !important;
|
||||
border-radius: 0px !important;
|
||||
background: transparent !important;
|
||||
border-radius: 0px !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: transparent !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
* {
|
||||
scrollbar-width: none !important;
|
||||
scrollbar-color: transparent transparent !important;
|
||||
scrollbar-width: none !important;
|
||||
scrollbar-color: transparent transparent !important;
|
||||
}
|
||||
|
||||
* {
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar !important;
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar !important;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
main {
|
||||
position: relative !important;
|
||||
z-index: 10 !important;
|
||||
min-height: 100vh !important;
|
||||
width: 100% !important;
|
||||
/* padding: 20px !important; */
|
||||
position: relative !important;
|
||||
z-index: 10 !important;
|
||||
min-height: 100vh !important;
|
||||
width: 100% !important;
|
||||
/* padding: 20px !important; */
|
||||
}
|
||||
|
||||
nav.fixed {
|
||||
z-index: 50 !important;
|
||||
background: transparent !important;
|
||||
z-index: 50 !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.background-canvas {
|
||||
opacity: 0.8 !important;
|
||||
}
|
||||
body {
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
overscroll-behavior-y: contain !important;
|
||||
}
|
||||
* {
|
||||
-webkit-tap-highlight-color: transparent !important;
|
||||
}
|
||||
.background-canvas {
|
||||
opacity: 0.8 !important;
|
||||
}
|
||||
body {
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
overscroll-behavior-y: contain !important;
|
||||
}
|
||||
* {
|
||||
-webkit-tap-highlight-color: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
.content-container {
|
||||
position: relative !important;
|
||||
z-index: 10 !important;
|
||||
height: 100% !important;
|
||||
overflow-y: auto !important;
|
||||
overflow-x: hidden !important;
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
position: relative !important;
|
||||
z-index: 10 !important;
|
||||
height: 100% !important;
|
||||
overflow-y: auto !important;
|
||||
overflow-x: hidden !important;
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
}
|
||||
|
||||
.scroll-container::-webkit-scrollbar {
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.scroll-container:hover::-webkit-scrollbar {
|
||||
opacity: 1;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@supports (-webkit-touch-callout: none) {
|
||||
body {
|
||||
height: -webkit-fill-available !important;
|
||||
}
|
||||
.background-canvas {
|
||||
height: -webkit-fill-available !important;
|
||||
}
|
||||
body {
|
||||
height: -webkit-fill-available !important;
|
||||
}
|
||||
.background-canvas {
|
||||
height: -webkit-fill-available !important;
|
||||
}
|
||||
}
|
||||
|
||||
.fade-on-scroll {
|
||||
opacity: 1;
|
||||
transition: opacity 0.3s ease;
|
||||
opacity: 1;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.fade-on-scroll.hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
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([]);
|
||||
const cameraRef = useRef(null);
|
||||
const keysRef = useRef(new Array(127).fill(0));
|
||||
const worldRef = useRef({ width: 0, height: 0 });
|
||||
const themeRef = useRef(theme);
|
||||
const themeRef = useRef(theme);
|
||||
|
||||
class Camera {
|
||||
constructor(position, zoom) {
|
||||
@ -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;
|
||||
@ -61,62 +68,94 @@ const BackgroundCanvas = ({ theme = 'light' }) => {
|
||||
|
||||
const drawJoints = (ctx, joints, camera, view, theme) => {
|
||||
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;
|
||||
ctx.fillRect(0, 0, view.width, view.height);
|
||||
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
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) {
|
||||
ctx.beginPath();
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
const moveCamera = (camera, keys) => {
|
||||
if (keys[37]) camera.acceleration.x -= camera.speed;
|
||||
if (keys[38]) camera.acceleration.y -= camera.speed;
|
||||
if (keys[39]) camera.acceleration.x += camera.speed;
|
||||
if (keys[40]) camera.acceleration.y += camera.speed;
|
||||
if (keys[37]) camera.acceleration.x -= camera.speed;
|
||||
if (keys[38]) camera.acceleration.y -= camera.speed;
|
||||
if (keys[39]) camera.acceleration.x += camera.speed;
|
||||
if (keys[40]) camera.acceleration.y += camera.speed;
|
||||
if (keys[188]) camera.acceleration.z += 0.003;
|
||||
if (keys[190]) camera.acceleration.z -= 0.003;
|
||||
if (keys[190]) camera.acceleration.z -= 0.003;
|
||||
|
||||
camera.position.x += camera.acceleration.x;
|
||||
camera.position.y += camera.acceleration.y;
|
||||
@ -127,49 +166,53 @@ const BackgroundCanvas = ({ theme = 'light' }) => {
|
||||
camera.acceleration.z *= 0.9;
|
||||
};
|
||||
|
||||
const initCanvas = () => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
const initCanvas = () => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
|
||||
const ctx = canvas.getContext('2d');
|
||||
const view = {
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
const ctx = canvas.getContext("2d");
|
||||
const view = {
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
};
|
||||
|
||||
canvas.width = view.width;
|
||||
canvas.height = view.height;
|
||||
|
||||
worldRef.current = {
|
||||
width: view.width * 2,
|
||||
height: view.height * 2,
|
||||
};
|
||||
|
||||
cameraRef.current = new Camera(
|
||||
{
|
||||
x: worldRef.current.width / 2,
|
||||
y: worldRef.current.height / 2,
|
||||
},
|
||||
1,
|
||||
);
|
||||
|
||||
const isMobile = window.innerWidth < 768;
|
||||
const numberOfJoints = isMobile ? 150 : 600;
|
||||
jointsRef.current = generateJoints(
|
||||
numberOfJoints,
|
||||
worldRef.current.width,
|
||||
worldRef.current.height,
|
||||
);
|
||||
|
||||
if (isMobile) {
|
||||
jointsRef.current.forEach((joint) => {
|
||||
joint.bone_length = 120;
|
||||
joint.speed = 0.4;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
canvas.width = view.width;
|
||||
canvas.height = view.height;
|
||||
|
||||
worldRef.current = {
|
||||
width: view.width * 2,
|
||||
height: view.height * 2,
|
||||
};
|
||||
|
||||
cameraRef.current = new Camera(
|
||||
{
|
||||
x: worldRef.current.width / 2,
|
||||
y: worldRef.current.height / 2,
|
||||
},
|
||||
1
|
||||
);
|
||||
|
||||
const isMobile = window.innerWidth < 768;
|
||||
const numberOfJoints = isMobile ? 80 : 300;
|
||||
jointsRef.current = generateJoints(numberOfJoints, worldRef.current.width, worldRef.current.height);
|
||||
|
||||
if (isMobile) {
|
||||
jointsRef.current.forEach(joint => {
|
||||
joint.bone_length = 120;
|
||||
joint.speed = 0.4;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const animate = () => {
|
||||
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,
|
||||
@ -177,8 +220,14 @@ 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(() => {
|
||||
@ -232,15 +281,11 @@ const initCanvas = () => {
|
||||
cancelAnimationFrame(animationRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="background-canvas"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<canvas ref={canvasRef} className="background-canvas" aria-hidden="true" />
|
||||
);
|
||||
};
|
||||
|
||||
export default BackgroundCanvas;
|
||||
export default BackgroundCanvas;
|
||||
|
||||
@ -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%;
|
||||
@ -18,12 +18,15 @@ const StyledWrapper = styled.div`
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
@ -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>
|
||||
@ -454,14 +560,19 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
|
||||
offset={-110}
|
||||
onSetActive={() => setActiveSection(item.key)}
|
||||
onClick={() => {
|
||||
setActiveSection(item.key);
|
||||
if (item.key === "home") scroll.scrollToTop({ duration: 600 });
|
||||
setActiveSection(item.key);
|
||||
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>
|
||||
);
|
||||
@ -475,4 +586,4 @@ const Navbar = ({ toggleTheme, currentTheme }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Navbar;
|
||||
export default Navbar;
|
||||
|
||||
@ -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",
|
||||
@ -91,10 +93,10 @@ export default function EngineeringHeroFlowbite() {
|
||||
width <= 400
|
||||
? baseSize * 0.78
|
||||
: width <= 640
|
||||
? baseSize * 0.88
|
||||
: width <= 1024
|
||||
? baseSize * 0.96
|
||||
: baseSize;
|
||||
? baseSize * 0.88
|
||||
: width <= 1024
|
||||
? baseSize * 0.96
|
||||
: baseSize;
|
||||
const headingMultiplier = width <= 640 ? 2.6 : 3.2;
|
||||
const subtitleMultiplier = width <= 640 ? 0.95 : 1.1;
|
||||
const mainText = (config.main_title || defaultConfig.main_title)
|
||||
@ -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}
|
||||
|
||||
@ -1,40 +1,47 @@
|
||||
@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;
|
||||
--text-color: #313131;
|
||||
--border-color: #d1c9be;
|
||||
}
|
||||
.dark {
|
||||
overflow-y: scroll !important;
|
||||
--primary: #041c40;
|
||||
--secondary: #e06923;
|
||||
--tertiary: #313131;
|
||||
--bg-color: #313131;
|
||||
--text-color: #F5EEE6;
|
||||
--border-color: #4a4a4a;
|
||||
}
|
||||
body {
|
||||
overflow-y: scroll !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
overflow-x: hidden;
|
||||
font-family: 'Cairo', system-ui, -apple-system, sans-serif;
|
||||
color: var(--text-color);
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
html {
|
||||
overflow-y: scroll !important;
|
||||
scroll-behavior: smooth;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
:root {
|
||||
overflow-y: scroll !important;
|
||||
--primary: #041c40;
|
||||
--secondary: #e06923;
|
||||
--tertiary: #313131;
|
||||
--bg-color: #e3e8ec;
|
||||
--text-color: #313131;
|
||||
--border-color: #d1c9be;
|
||||
}
|
||||
.dark {
|
||||
overflow-y: scroll !important;
|
||||
--primary: #041c40;
|
||||
--secondary: #e06923;
|
||||
--tertiary: #313131;
|
||||
--bg-color: #313131;
|
||||
--text-color: #f5eee6;
|
||||
--border-color: #4a4a4a;
|
||||
}
|
||||
body {
|
||||
overflow-y: scroll !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
overflow-x: hidden;
|
||||
font-family:
|
||||
"Cairo",
|
||||
system-ui,
|
||||
-apple-system,
|
||||
sans-serif;
|
||||
color: var(--text-color);
|
||||
background-color: var(--bg-color);
|
||||
transition:
|
||||
background-color 0.3s ease,
|
||||
color 0.3s ease;
|
||||
}
|
||||
html {
|
||||
overflow-y: scroll !important;
|
||||
scroll-behavior: smooth;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
20
src/main.jsx
20
src/main.jsx
@ -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>,
|
||||
);
|
||||
|
||||
@ -1,25 +1,22 @@
|
||||
module.exports = {
|
||||
darkMode: 'class',
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#041c40',
|
||||
secondary: '#e06923',
|
||||
'dark-bg': '#313131',
|
||||
'light-bg': '#F5EEE6',
|
||||
},
|
||||
backdropBlur: {
|
||||
'xs': '2px',
|
||||
'sm': '4px',
|
||||
'md': '8px',
|
||||
'lg': '12px',
|
||||
'xl': '20px',
|
||||
},
|
||||
},
|
||||
darkMode: "class",
|
||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: "#041c40",
|
||||
secondary: "#e06923",
|
||||
"dark-bg": "#313131",
|
||||
"light-bg": "#E3E8EC",
|
||||
},
|
||||
backdropBlur: {
|
||||
xs: "2px",
|
||||
sm: "4px",
|
||||
md: "8px",
|
||||
lg: "12px",
|
||||
xl: "20px",
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user