Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/web-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@
"@tanstack/react-table": "^8.21.3",
"axios": "^1.13.2",
"framer-motion": "^12.35.0",
"gsap": "^3.15.0",
"lucide-react": "^0.554.0",
"postprocessing": "^6.39.1",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-hot-toast": "^2.6.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^7.9.6",
"recharts": "^2.13.0",
"remark-gfm": "^4.0.1",
"tailwindcss": "^4.1.18"
"tailwindcss": "^4.1.18",
"three": "^0.184.0"
},
"devDependencies": {
"@eslint/js": "^9.39.1",
Expand Down
29 changes: 18 additions & 11 deletions apps/web-dashboard/src/components/AuthShell.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,25 @@ function AuthShell({

<div className="auth-shell__content">
<div className="auth-form-card">
<div className="auth-form-card__brand">
<div className="auth-form-card__brand-mark">U</div>
<span className="auth-form-card__brand-text">urBackend</span>
</div>

<div className="auth-form-card__header">
{onModeClick ? (
<button
type="button"
className="auth-form-card__mode auth-form-card__mode--clickable"
onClick={onModeClick}
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}
>
{modeLabel}
</button>
) : (
<span className="auth-form-card__mode">{modeLabel}</span>
{modeLabel && (
onModeClick ? (
<button
type="button"
className="auth-form-card__mode auth-form-card__mode--clickable"
onClick={onModeClick}
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}
>
{modeLabel}
</button>
) : (
<span className="auth-form-card__mode">{modeLabel}</span>
)
)}
{title ? <h1>{title}</h1> : null}
{subtitle ? <p>{subtitle}</p> : null}
Expand Down
110 changes: 110 additions & 0 deletions apps/web-dashboard/src/components/BorderGlow/BorderGlow.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
.border-glow-card {
--edge-proximity: 0;
--cursor-angle: 45deg;
--edge-sensitivity: 30;
--color-sensitivity: calc(var(--edge-sensitivity) + 20);
--border-radius: 28px;
--glow-padding: 40px;
--cone-spread: 25;

position: relative;
border-radius: var(--border-radius);
isolation: isolate;
transform: translate3d(0, 0, 0.01px);
display: flex;
flex-direction: column;
border: 1px solid rgba(255, 255, 255, 0.08);
background: var(--card-bg, rgba(255, 255, 255, 0.02));
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
overflow: visible;
box-shadow:
rgba(0, 0, 0, 0.1) 0px 1px 2px,
rgba(0, 0, 0, 0.1) 0px 2px 4px,
rgba(0, 0, 0, 0.1) 0px 4px 8px,
rgba(0, 0, 0, 0.1) 0px 8px 16px,
rgba(0, 0, 0, 0.1) 0px 16px 32px,
rgba(0, 0, 0, 0.1) 0px 32px 64px;
}

.border-glow-card::before,
.border-glow-card > .edge-light {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
transition: opacity 0.25s ease-out;
z-index: -1;
}

.border-glow-card:not(:hover):not(.sweep-active)::before,
.border-glow-card:not(:hover):not(.sweep-active) > .edge-light {
opacity: 0;
transition: opacity 0.75s ease-in-out;
}

/* colored mesh-gradient border */
.border-glow-card::before {
border: 1px solid transparent;
background:
linear-gradient(#0c0a0f 0 100%) padding-box,
linear-gradient(rgba(255, 255, 255, 0) 0% 100%) border-box,
var(--gradient-one, radial-gradient(at 80% 55%, hsla(268, 100%, 76%, 1) 0px, transparent 50%)) border-box,
var(--gradient-two, radial-gradient(at 69% 34%, hsla(349, 100%, 74%, 1) 0px, transparent 50%)) border-box,
var(--gradient-three, radial-gradient(at 8% 6%, hsla(136, 100%, 78%, 1) 0px, transparent 50%)) border-box,
var(--gradient-four, radial-gradient(at 41% 38%, hsla(192, 100%, 64%, 1) 0px, transparent 50%)) border-box,
var(--gradient-five, radial-gradient(at 86% 85%, hsla(186, 100%, 74%, 1) 0px, transparent 50%)) border-box,
var(--gradient-six, radial-gradient(at 82% 18%, hsla(52, 100%, 65%, 1) 0px, transparent 50%)) border-box,
var(--gradient-seven, radial-gradient(at 51% 4%, hsla(12, 100%, 72%, 1) 0px, transparent 50%)) border-box,
var(--gradient-base, linear-gradient(#c299ff 0 100%)) border-box;

opacity: calc((var(--edge-proximity) - var(--color-sensitivity)) / (100 - var(--color-sensitivity)));

mask-image:
conic-gradient(
from var(--cursor-angle) at center,
black calc(var(--cone-spread) * 1%),
transparent calc((var(--cone-spread) + 15) * 1%),
transparent calc((100 - var(--cone-spread) - 15) * 1%),
black calc((100 - var(--cone-spread)) * 1%)
);
}

/* outer glow layer */
.border-glow-card > .edge-light {
inset: calc(var(--glow-padding) * -1);
pointer-events: none;
z-index: 1;

mask-image:
conic-gradient(
from var(--cursor-angle) at center, black 2.5%, transparent 10%, transparent 90%, black 97.5%
);

opacity: calc((var(--edge-proximity) - var(--edge-sensitivity)) / (100 - var(--edge-sensitivity)));
mix-blend-mode: plus-lighter;
}

.border-glow-card > .edge-light::before {
content: "";
position: absolute;
inset: var(--glow-padding);
border-radius: inherit;
box-shadow:
0 0 1px 0 var(--glow-color-60, hsl(40deg 80% 80% / 60%)),
0 0 3px 0 var(--glow-color-50, hsl(40deg 80% 80% / 50%)),
0 0 6px 0 var(--glow-color-40, hsl(40deg 80% 80% / 40%)),
0 0 15px 0 var(--glow-color-30, hsl(40deg 80% 80% / 30%)),
0 0 25px 2px var(--glow-color-20, hsl(40deg 80% 80% / 20%)),
0 0 50px 2px var(--glow-color-10, hsl(40deg 80% 80% / 10%));
}

.border-glow-inner {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
width: 100%;
position: relative;
z-index: 1;
}
156 changes: 156 additions & 0 deletions apps/web-dashboard/src/components/BorderGlow/BorderGlow.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import { useRef, useCallback, useEffect } from 'react';
import './BorderGlow.css';

function parseHSL(hslStr) {
const match = hslStr.match(/([\d.]+)\s*([\d.]+)%?\s*([\d.]+)%?/);
if (!match) return { h: 40, s: 80, l: 80 };
return { h: parseFloat(match[1]), s: parseFloat(match[2]), l: parseFloat(match[3]) };
}

function buildGlowVars(glowColor, intensity) {
const { h, s, l } = parseHSL(glowColor);
const base = `${h}deg ${s}% ${l}%`;
const opacities = [100, 60, 50, 40, 30, 20, 10];
const keys = ['', '-60', '-50', '-40', '-30', '-20', '-10'];
const vars = {};
for (let i = 0; i < opacities.length; i++) {
vars[`--glow-color${keys[i]}`] = `hsl(${base} / ${Math.min(opacities[i] * intensity, 100)}%)`;
}
return vars;
}

const GRADIENT_POSITIONS = ['80% 55%', '69% 34%', '8% 6%', '41% 38%', '86% 85%', '82% 18%', '51% 4%'];
const GRADIENT_KEYS = ['--gradient-one', '--gradient-two', '--gradient-three', '--gradient-four', '--gradient-five', '--gradient-six', '--gradient-seven'];
const COLOR_MAP = [0, 1, 2, 0, 1, 2, 1];

function buildGradientVars(colors) {
const vars = {};
for (let i = 0; i < 7; i++) {
const c = colors[Math.min(COLOR_MAP[i], colors.length - 1)];
vars[GRADIENT_KEYS[i]] = `radial-gradient(at ${GRADIENT_POSITIONS[i]}, ${c} 0px, transparent 50%)`;
}
vars['--gradient-base'] = `linear-gradient(${colors[0]} 0 100%)`;
return vars;
}

function easeOutCubic(x) { return 1 - Math.pow(1 - x, 3); }
function easeInCubic(x) { return x * x * x; }

function animateValue({ start = 0, end = 100, duration = 1000, delay = 0, ease = easeOutCubic, onUpdate, onEnd }) {
const t0 = performance.now() + delay;
function tick() {
const elapsed = performance.now() - t0;
const t = Math.min(elapsed / duration, 1);
onUpdate(start + (end - start) * ease(t));
if (t < 1) requestAnimationFrame(tick);
else if (onEnd) onEnd();
}
setTimeout(() => requestAnimationFrame(tick), delay);
}

const BorderGlow = ({
children,
className = '',
edgeSensitivity = 30,
glowColor = '40 80 80',
backgroundColor = 'rgba(255, 255, 255, 0.02)',
borderRadius = 16,
glowRadius = 40,
glowIntensity = 1.0,
coneSpread = 25,
animated = false,
colors = ['#00f5d4', '#00b4ab', '#00ffd8'],
fillOpacity = 0.5,
}) => {
const cardRef = useRef(null);

const getCenterOfElement = useCallback((el) => {
const { width, height } = el.getBoundingClientRect();
return [width / 2, height / 2];
}, []);

const getEdgeProximity = useCallback((el, x, y) => {
const [cx, cy] = getCenterOfElement(el);
const dx = x - cx;
const dy = y - cy;
let kx = Infinity;
let ky = Infinity;
if (dx !== 0) kx = cx / Math.abs(dx);
if (dy !== 0) ky = cy / Math.abs(dy);
return Math.min(Math.max(1 / Math.min(kx, ky), 0), 1);
}, [getCenterOfElement]);

const getCursorAngle = useCallback((el, x, y) => {
const [cx, cy] = getCenterOfElement(el);
const dx = x - cx;
const dy = y - cy;
if (dx === 0 && dy === 0) return 0;
const radians = Math.atan2(dy, dx);
let degrees = radians * (180 / Math.PI) + 90;
if (degrees < 0) degrees += 360;
return degrees;
}, [getCenterOfElement]);

const handlePointerMove = useCallback((e) => {
const card = cardRef.current;
if (!card) return;

const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;

const edge = getEdgeProximity(card, x, y);
const angle = getCursorAngle(card, x, y);

card.style.setProperty('--edge-proximity', `${(edge * 100).toFixed(3)}`);
card.style.setProperty('--cursor-angle', `${angle.toFixed(3)}deg`);
}, [getEdgeProximity, getCursorAngle]);

useEffect(() => {
if (!animated || !cardRef.current) return;
const card = cardRef.current;
const angleStart = 110;
const angleEnd = 465;
card.classList.add('sweep-active');
card.style.setProperty('--cursor-angle', `${angleStart}deg`);

animateValue({ duration: 500, onUpdate: v => card.style.setProperty('--edge-proximity', v) });
animateValue({ ease: easeInCubic, duration: 1500, end: 50, onUpdate: v => {
card.style.setProperty('--cursor-angle', `${(angleEnd - angleStart) * (v / 100) + angleStart}deg`);
}});
animateValue({ ease: easeOutCubic, delay: 1500, duration: 2250, start: 50, end: 100, onUpdate: v => {
card.style.setProperty('--cursor-angle', `${(angleEnd - angleStart) * (v / 100) + angleStart}deg`);
}});
animateValue({ ease: easeInCubic, delay: 2500, duration: 1500, start: 100, end: 0,
onUpdate: v => card.style.setProperty('--edge-proximity', v),
onEnd: () => card.classList.remove('sweep-active'),
});
}, [animated]);

const glowVars = buildGlowVars(glowColor, glowIntensity);

return (
<div
ref={cardRef}
onPointerMove={handlePointerMove}
className={`border-glow-card ${className}`}
style={{
'--card-bg': backgroundColor,
'--edge-sensitivity': edgeSensitivity,
'--border-radius': `${borderRadius}px`,
'--glow-padding': `${glowRadius}px`,
'--cone-spread': coneSpread,
'--fill-opacity': fillOpacity,
...glowVars,
...buildGradientVars(colors),
}}
>
<span className="edge-light" />
<div className="border-glow-inner">
{children}
</div>
</div>
);
};

export default BorderGlow;
17 changes: 17 additions & 0 deletions apps/web-dashboard/src/components/Hyperspeed/Hyperspeed.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#lights {
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
top: 0;
left: 0;
z-index: 0; /* Behind all content in the hero section! */
pointer-events: none; /* Make sure users can click elements over it */
opacity: 0.45; /* Soften the light beams for better foreground text readability */
}

canvas {
width: 100%;
height: 100%;
display: block;
}
Loading
Loading