Spaces:
Running
Running
Komalpreet Kaur commited on
feat: add dark mode toggle to welcome/auth page
Browse files
frontend/src/App.jsx
CHANGED
|
@@ -218,7 +218,7 @@ function App() {
|
|
| 218 |
setActivePage('console');
|
| 219 |
};
|
| 220 |
|
| 221 |
-
if (!username) return <AuthScreen onAuth={setUsername} />;
|
| 222 |
|
| 223 |
const stats = [
|
| 224 |
{ label: 'Working Memory', value: vitals?.working || '0', icon: 'psychology' },
|
|
|
|
| 218 |
setActivePage('console');
|
| 219 |
};
|
| 220 |
|
| 221 |
+
if (!username) return <AuthScreen onAuth={setUsername} darkMode={darkMode} setDarkMode={setDarkMode} />;
|
| 222 |
|
| 223 |
const stats = [
|
| 224 |
{ label: 'Working Memory', value: vitals?.working || '0', icon: 'psychology' },
|
frontend/src/components/AuthScreen.css
CHANGED
|
@@ -426,3 +426,167 @@
|
|
| 426 |
flex-shrink: 0;
|
| 427 |
}
|
| 428 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
flex-shrink: 0;
|
| 427 |
}
|
| 428 |
}
|
| 429 |
+
|
| 430 |
+
|
| 431 |
+
/* βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 432 |
+
Dark Mode Toggle Button (Top-Right)
|
| 433 |
+
βββββββββββββββββββββββββββββββββββββββββββββββ */
|
| 434 |
+
|
| 435 |
+
.landing-theme-toggle {
|
| 436 |
+
position: absolute;
|
| 437 |
+
top: 24px;
|
| 438 |
+
right: 24px;
|
| 439 |
+
z-index: 100;
|
| 440 |
+
width: 44px;
|
| 441 |
+
height: 44px;
|
| 442 |
+
border-radius: 14px;
|
| 443 |
+
border: 1px solid rgba(0, 0, 0, 0.06);
|
| 444 |
+
background: rgba(255, 255, 255, 0.5);
|
| 445 |
+
backdrop-filter: blur(20px);
|
| 446 |
+
-webkit-backdrop-filter: blur(20px);
|
| 447 |
+
display: flex;
|
| 448 |
+
align-items: center;
|
| 449 |
+
justify-content: center;
|
| 450 |
+
cursor: pointer;
|
| 451 |
+
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
| 452 |
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
|
| 453 |
+
}
|
| 454 |
+
|
| 455 |
+
.landing-theme-toggle .material-icons {
|
| 456 |
+
font-size: 20px;
|
| 457 |
+
color: #64748b;
|
| 458 |
+
transition: color 0.3s;
|
| 459 |
+
}
|
| 460 |
+
|
| 461 |
+
.landing-theme-toggle:hover {
|
| 462 |
+
transform: translateY(-2px);
|
| 463 |
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
|
| 464 |
+
border-color: rgba(255, 107, 53, 0.3);
|
| 465 |
+
}
|
| 466 |
+
|
| 467 |
+
.landing-theme-toggle:hover .material-icons {
|
| 468 |
+
color: #ff6b35;
|
| 469 |
+
}
|
| 470 |
+
|
| 471 |
+
.landing-theme-toggle:active {
|
| 472 |
+
transform: translateY(0);
|
| 473 |
+
}
|
| 474 |
+
|
| 475 |
+
|
| 476 |
+
/* βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 477 |
+
Dark Theme Overrides (.landing.dark)
|
| 478 |
+
βββββββββββββββββββββββββββββββββββββββββββββββ */
|
| 479 |
+
|
| 480 |
+
.landing.dark {
|
| 481 |
+
background: #0c0e14;
|
| 482 |
+
}
|
| 483 |
+
|
| 484 |
+
/* Background orbs β deeper, richer glows */
|
| 485 |
+
.landing.dark .orb-1 {
|
| 486 |
+
background: rgba(255, 107, 53, 0.08);
|
| 487 |
+
}
|
| 488 |
+
.landing.dark .orb-2 {
|
| 489 |
+
background: rgba(255, 139, 84, 0.06);
|
| 490 |
+
}
|
| 491 |
+
.landing.dark .orb-3 {
|
| 492 |
+
background: rgba(255, 107, 53, 0.04);
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
.landing.dark .bg-grid {
|
| 496 |
+
background-image: radial-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px);
|
| 497 |
+
}
|
| 498 |
+
|
| 499 |
+
/* Glass panel β dark frosted glass */
|
| 500 |
+
.landing.dark .splash-content,
|
| 501 |
+
.landing.dark .name-content {
|
| 502 |
+
background: rgba(20, 22, 32, 0.6);
|
| 503 |
+
border-color: rgba(255, 255, 255, 0.06);
|
| 504 |
+
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.3), inset 0 0 20px rgba(255, 255, 255, 0.02);
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
/* Typography */
|
| 508 |
+
.landing.dark .hero-title {
|
| 509 |
+
color: #f1f5f9;
|
| 510 |
+
}
|
| 511 |
+
|
| 512 |
+
.landing.dark .hero-desc {
|
| 513 |
+
color: #94a3b8;
|
| 514 |
+
}
|
| 515 |
+
|
| 516 |
+
.landing.dark .name-heading {
|
| 517 |
+
color: #f1f5f9;
|
| 518 |
+
}
|
| 519 |
+
|
| 520 |
+
.landing.dark .name-sub {
|
| 521 |
+
color: #94a3b8;
|
| 522 |
+
}
|
| 523 |
+
|
| 524 |
+
/* Feature badges */
|
| 525 |
+
.landing.dark .splash-feature {
|
| 526 |
+
background: rgba(255, 255, 255, 0.04);
|
| 527 |
+
border-color: rgba(255, 255, 255, 0.08);
|
| 528 |
+
color: #cbd5e1;
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
/* Hint text */
|
| 532 |
+
.landing.dark .splash-hint {
|
| 533 |
+
color: #475569;
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
/* Name input */
|
| 537 |
+
.landing.dark .name-input {
|
| 538 |
+
background: rgba(255, 255, 255, 0.05) !important;
|
| 539 |
+
border-color: rgba(255, 255, 255, 0.08) !important;
|
| 540 |
+
color: #f1f5f9 !important;
|
| 541 |
+
}
|
| 542 |
+
|
| 543 |
+
.landing.dark .name-input::placeholder {
|
| 544 |
+
color: #475569 !important;
|
| 545 |
+
}
|
| 546 |
+
|
| 547 |
+
.landing.dark .name-input:focus {
|
| 548 |
+
background: rgba(255, 255, 255, 0.08) !important;
|
| 549 |
+
border-color: #ff6b35 !important;
|
| 550 |
+
box-shadow: 0 0 20px rgba(255, 107, 53, 0.15) !important;
|
| 551 |
+
}
|
| 552 |
+
|
| 553 |
+
/* Back link */
|
| 554 |
+
.landing.dark .back-link {
|
| 555 |
+
color: #94a3b8;
|
| 556 |
+
}
|
| 557 |
+
|
| 558 |
+
.landing.dark .back-link:hover {
|
| 559 |
+
color: #ff6b35;
|
| 560 |
+
}
|
| 561 |
+
|
| 562 |
+
/* Footer */
|
| 563 |
+
.landing.dark .landing-footer {
|
| 564 |
+
color: #475569;
|
| 565 |
+
}
|
| 566 |
+
|
| 567 |
+
/* Theme toggle in dark mode */
|
| 568 |
+
.landing.dark .landing-theme-toggle {
|
| 569 |
+
background: rgba(255, 255, 255, 0.05);
|
| 570 |
+
border-color: rgba(255, 255, 255, 0.08);
|
| 571 |
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
|
| 572 |
+
}
|
| 573 |
+
|
| 574 |
+
.landing.dark .landing-theme-toggle .material-icons {
|
| 575 |
+
color: #94a3b8;
|
| 576 |
+
}
|
| 577 |
+
|
| 578 |
+
.landing.dark .landing-theme-toggle:hover {
|
| 579 |
+
background: rgba(255, 255, 255, 0.08);
|
| 580 |
+
border-color: rgba(255, 107, 53, 0.3);
|
| 581 |
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
| 582 |
+
}
|
| 583 |
+
|
| 584 |
+
/* Pulse ring in dark mode */
|
| 585 |
+
.landing.dark .hero-pulse-ring {
|
| 586 |
+
border-color: rgba(255, 107, 53, 0.15);
|
| 587 |
+
}
|
| 588 |
+
|
| 589 |
+
/* Error text stays visible */
|
| 590 |
+
.landing.dark .auth-error {
|
| 591 |
+
color: #f87171;
|
| 592 |
+
}
|
frontend/src/components/AuthScreen.jsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
import { useState, useEffect, useRef } from 'react';
|
| 2 |
import './AuthScreen.css';
|
| 3 |
|
| 4 |
-
function AuthScreen({ onAuth }) {
|
| 5 |
const [stage, setStage] = useState('splash'); // 'splash' | 'enter'
|
| 6 |
const [username, setUsername] = useState('');
|
| 7 |
const [error, setError] = useState('');
|
|
@@ -57,7 +57,16 @@ function AuthScreen({ onAuth }) {
|
|
| 57 |
};
|
| 58 |
|
| 59 |
return (
|
| 60 |
-
<div className={`landing ${transitioning ? 'transitioning' : ''}`}>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
{/* Animated background */}
|
| 63 |
<div className="landing-bg">
|
|
|
|
| 1 |
import { useState, useEffect, useRef } from 'react';
|
| 2 |
import './AuthScreen.css';
|
| 3 |
|
| 4 |
+
function AuthScreen({ onAuth, darkMode, setDarkMode }) {
|
| 5 |
const [stage, setStage] = useState('splash'); // 'splash' | 'enter'
|
| 6 |
const [username, setUsername] = useState('');
|
| 7 |
const [error, setError] = useState('');
|
|
|
|
| 57 |
};
|
| 58 |
|
| 59 |
return (
|
| 60 |
+
<div className={`landing ${transitioning ? 'transitioning' : ''} ${darkMode ? 'dark' : ''}`}>
|
| 61 |
+
|
| 62 |
+
{/* Dark Mode Toggle */}
|
| 63 |
+
<button
|
| 64 |
+
className="landing-theme-toggle"
|
| 65 |
+
onClick={() => setDarkMode(!darkMode)}
|
| 66 |
+
title={darkMode ? 'Switch to Light Mode' : 'Switch to Dark Mode'}
|
| 67 |
+
>
|
| 68 |
+
<span className="material-icons">{darkMode ? 'light_mode' : 'dark_mode'}</span>
|
| 69 |
+
</button>
|
| 70 |
|
| 71 |
{/* Animated background */}
|
| 72 |
<div className="landing-bg">
|