mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-03-04 02:20:19 +01:00
Enhance rainbow mode animations
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useCallback, useRef, useEffect } from 'react';
|
||||
import { usePreferences } from '../contexts/PreferencesContext';
|
||||
import type { ThemeMode } from '../constants/theme';
|
||||
import rainbowStyles from '../styles/rainbow.module.css';
|
||||
|
||||
interface RainbowThemeHook {
|
||||
themeMode: ThemeMode;
|
||||
@@ -21,15 +22,56 @@ export function useRainbowTheme(): RainbowThemeHook {
|
||||
const toggleCount = useRef(0);
|
||||
const lastToggleTime = useRef(Date.now());
|
||||
const isToggleDisabled = useRef(false);
|
||||
const rainbowIntervalRef = useRef<number | null>(null);
|
||||
|
||||
// Apply rainbow class to body whenever theme changes
|
||||
useEffect(() => {
|
||||
const root = document.documentElement;
|
||||
|
||||
const clearRainbowInterval = () => {
|
||||
if (rainbowIntervalRef.current !== null) {
|
||||
window.clearInterval(rainbowIntervalRef.current);
|
||||
rainbowIntervalRef.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
const resetRainbowVariables = () => {
|
||||
root.style.removeProperty('--rainbow-hue');
|
||||
root.style.removeProperty('--rainbow-angle');
|
||||
root.style.removeProperty('--rainbow-sparkle-opacity');
|
||||
root.style.removeProperty('--rainbow-glow-strength');
|
||||
};
|
||||
|
||||
if (themeMode === 'rainbow') {
|
||||
document.body.classList.add('rainbow-mode-active');
|
||||
showRainbowNotification();
|
||||
|
||||
const applyRainbowVariables = () => {
|
||||
const hue = Math.floor(Math.random() * 360);
|
||||
const angle = Math.floor(Math.random() * 360);
|
||||
const sparkle = (Math.random() * 0.4 + 0.4).toFixed(2);
|
||||
const glow = (Math.random() * 0.3 + 0.35).toFixed(2);
|
||||
|
||||
root.style.setProperty('--rainbow-hue', hue.toString());
|
||||
root.style.setProperty('--rainbow-angle', `${angle}deg`);
|
||||
root.style.setProperty('--rainbow-sparkle-opacity', sparkle);
|
||||
root.style.setProperty('--rainbow-glow-strength', glow);
|
||||
};
|
||||
|
||||
applyRainbowVariables();
|
||||
clearRainbowInterval();
|
||||
rainbowIntervalRef.current = window.setInterval(applyRainbowVariables, 1400);
|
||||
} else {
|
||||
document.body.classList.remove('rainbow-mode-active');
|
||||
clearRainbowInterval();
|
||||
resetRainbowVariables();
|
||||
}
|
||||
|
||||
return () => {
|
||||
clearRainbowInterval();
|
||||
resetRainbowVariables();
|
||||
document.body.classList.remove('rainbow-mode-active');
|
||||
};
|
||||
}, [themeMode]);
|
||||
|
||||
const showRainbowNotification = () => {
|
||||
@@ -42,26 +84,8 @@ export function useRainbowTheme(): RainbowThemeHook {
|
||||
// Create and show rainbow notification
|
||||
const notification = document.createElement('div');
|
||||
notification.id = 'rainbow-notification';
|
||||
notification.className = rainbowStyles.rainbowNotification;
|
||||
notification.innerHTML = '🌈 RAINBOW MODE ACTIVATED! 🌈<br><small>Button disabled for 3 seconds, then click to exit</small>';
|
||||
notification.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: linear-gradient(45deg, #ff0000, #ff8800, #ffff00, #88ff00, #00ff88, #00ffff, #0088ff, #8800ff);
|
||||
background-size: 300% 300%;
|
||||
animation: rainbowBackground 1s ease infinite;
|
||||
color: white;
|
||||
padding: 15px 20px;
|
||||
border-radius: 25px;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
z-index: 1000;
|
||||
border: 2px solid white;
|
||||
box-shadow: 0 0 20px rgba(255, 255, 255, 0.8);
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.3s ease;
|
||||
`;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
@@ -88,20 +112,31 @@ export function useRainbowTheme(): RainbowThemeHook {
|
||||
// Create and show exit notification
|
||||
const notification = document.createElement('div');
|
||||
notification.id = 'rainbow-exit-notification';
|
||||
notification.innerHTML = '🌙 Rainbow mode deactivated';
|
||||
|
||||
const rootStyles = getComputedStyle(document.documentElement);
|
||||
const hueValue = rootStyles.getPropertyValue('--rainbow-hue').trim();
|
||||
const baseHue = Number.isNaN(Number.parseFloat(hueValue))
|
||||
? 0
|
||||
: Number.parseFloat(hueValue);
|
||||
const exitHue = (baseHue + 200) % 360;
|
||||
const accentHue = (exitHue + 45) % 360;
|
||||
|
||||
notification.innerHTML = '🌙 Rainbow mode deactivated — back to reality';
|
||||
notification.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: linear-gradient(45deg, #333, #666);
|
||||
background: linear-gradient(135deg, hsla(${exitHue}deg, 85%, 40%, 0.85), hsla(${accentHue}deg, 90%, 45%, 0.9));
|
||||
background-size: 220% 220%;
|
||||
animation: rainbowBackground 1.8s ease infinite;
|
||||
color: white;
|
||||
padding: 15px 20px;
|
||||
border-radius: 25px;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
z-index: 1000;
|
||||
border: 2px solid #999;
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
|
||||
border: 2px solid hsla(${accentHue}deg, 95%, 75%, 0.9);
|
||||
box-shadow: 0 0 25px hsla(${accentHue}deg, 100%, 65%, 0.45);
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.3s ease;
|
||||
|
||||
@@ -1,8 +1,27 @@
|
||||
/* Rainbow Mode Styles - Easter Egg! */
|
||||
:global(:root) {
|
||||
--rainbow-hue: 0;
|
||||
--rainbow-angle: -45deg;
|
||||
--rainbow-sparkle-opacity: 0.45;
|
||||
--rainbow-glow-strength: 0.4;
|
||||
}
|
||||
|
||||
@keyframes rainbowBackground {
|
||||
0% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
100% { background-position: 0% 50%; }
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
25% {
|
||||
background-position: 50% 0%;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
75% {
|
||||
background-position: 50% 100%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rainbowBorder {
|
||||
@@ -32,16 +51,102 @@
|
||||
50% { transform: scale(1.05); }
|
||||
}
|
||||
|
||||
@keyframes rainbowAurora {
|
||||
0% {
|
||||
transform: rotate(0deg) scale(1);
|
||||
opacity: calc(var(--rainbow-glow-strength) * 0.9);
|
||||
}
|
||||
50% {
|
||||
transform: rotate(180deg) scale(1.05);
|
||||
opacity: calc(var(--rainbow-glow-strength) * 1.15);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg) scale(1);
|
||||
opacity: calc(var(--rainbow-glow-strength) * 0.9);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rainbowSparkle {
|
||||
0% {
|
||||
background-position: 0% 0%, 50% 50%, 100% 100%;
|
||||
opacity: calc(var(--rainbow-sparkle-opacity) * 0.6);
|
||||
}
|
||||
50% {
|
||||
background-position: 50% 50%, 100% 0%, 0% 100%;
|
||||
opacity: calc(var(--rainbow-sparkle-opacity) * 1.1);
|
||||
}
|
||||
100% {
|
||||
background-position: 100% 100%, 0% 0%, 50% 50%;
|
||||
opacity: calc(var(--rainbow-sparkle-opacity) * 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Main rainbow theme class */
|
||||
.rainbowMode {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
isolation: isolate;
|
||||
background: linear-gradient(
|
||||
-45deg,
|
||||
#ff0000, #ff8800, #ffff00, #88ff00, #00ff88, #00ffff, #0088ff, #8800ff, #ff0088, #ff0000
|
||||
var(--rainbow-angle),
|
||||
#ff0000,
|
||||
#ff8800,
|
||||
#ffff00,
|
||||
#88ff00,
|
||||
#00ff88,
|
||||
#00ffff,
|
||||
#0088ff,
|
||||
#8800ff,
|
||||
#ff0088,
|
||||
#ff0000
|
||||
) !important;
|
||||
background-size: 400% 400% !important;
|
||||
background-size: 500% 500% !important;
|
||||
animation: rainbowBackground 3s ease infinite !important;
|
||||
color: white !important;
|
||||
overflow-x: hidden;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
box-shadow: inset 0 0 45px rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
.rainbowMode::before,
|
||||
.rainbowMode::after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: -40vh;
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
transition: opacity 1s ease;
|
||||
}
|
||||
|
||||
.rainbowMode::before {
|
||||
background: conic-gradient(
|
||||
from calc(var(--rainbow-angle) + 90deg),
|
||||
rgba(255, 0, 0, 0.5),
|
||||
rgba(255, 154, 0, 0.5),
|
||||
rgba(208, 222, 33, 0.5),
|
||||
rgba(79, 220, 74, 0.5),
|
||||
rgba(63, 218, 216, 0.5),
|
||||
rgba(47, 201, 226, 0.5),
|
||||
rgba(28, 127, 238, 0.5),
|
||||
rgba(95, 21, 242, 0.5),
|
||||
rgba(186, 12, 248, 0.5),
|
||||
rgba(251, 7, 217, 0.5),
|
||||
rgba(255, 0, 0, 0.5)
|
||||
);
|
||||
mix-blend-mode: screen;
|
||||
filter: blur(80px);
|
||||
animation: rainbowAurora 14s linear infinite;
|
||||
opacity: var(--rainbow-glow-strength);
|
||||
}
|
||||
|
||||
.rainbowMode::after {
|
||||
background-image:
|
||||
radial-gradient(circle at 10% 20%, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0) 45%),
|
||||
radial-gradient(circle at 80% 30%, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0) 40%),
|
||||
radial-gradient(circle at 30% 75%, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0) 35%);
|
||||
background-size: 250px 250px, 320px 320px, 280px 280px;
|
||||
mix-blend-mode: screen;
|
||||
animation: rainbowSparkle 9s ease-in-out infinite;
|
||||
opacity: var(--rainbow-sparkle-opacity);
|
||||
}
|
||||
|
||||
/* Rainbow components */
|
||||
@@ -55,7 +160,13 @@
|
||||
color: white !important;
|
||||
border: 2px solid !important;
|
||||
border-radius: 15px !important;
|
||||
box-shadow: 0 0 20px rgba(255, 255, 255, 0.3) !important;
|
||||
box-shadow: 0 0 25px rgba(255, 255, 255, 0.35) !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
transition: transform 0.4s ease, filter 0.8s ease;
|
||||
}
|
||||
|
||||
.rainbowCard:hover {
|
||||
transform: translateY(-6px) scale(1.02);
|
||||
}
|
||||
|
||||
.rainbowButton {
|
||||
@@ -70,12 +181,15 @@
|
||||
border-radius: 8px !important;
|
||||
transition: all 0.3s ease !important;
|
||||
font-weight: bold !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25) !important;
|
||||
}
|
||||
|
||||
.rainbowButton:hover {
|
||||
transform: scale(1.05) !important;
|
||||
animation: rainbowBackground 1s ease infinite, rainbowBorder 0.5s linear infinite, rainbowPulse 0.5s ease infinite !important;
|
||||
box-shadow: 0 0 25px rgba(255, 255, 255, 0.6) !important;
|
||||
filter: saturate(140%) hue-rotate(calc((var(--rainbow-hue) + 40) * 1deg));
|
||||
}
|
||||
|
||||
.rainbowInput {
|
||||
@@ -88,6 +202,9 @@
|
||||
border: 2px solid !important;
|
||||
color: white !important;
|
||||
border-radius: 8px !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
box-shadow: inset 0 0 12px rgba(255, 255, 255, 0.25) !important;
|
||||
transition: filter 0.6s ease;
|
||||
}
|
||||
|
||||
.rainbowInput::placeholder {
|
||||
@@ -98,6 +215,7 @@
|
||||
animation: rainbowText 3s linear infinite !important;
|
||||
font-weight: bold !important;
|
||||
text-shadow: 0 0 10px currentColor !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
}
|
||||
|
||||
.rainbowSegmentedControl {
|
||||
@@ -110,6 +228,8 @@
|
||||
border: 2px solid !important;
|
||||
border-radius: 12px !important;
|
||||
padding: 4px !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
box-shadow: 0 0 18px rgba(255, 255, 255, 0.35) !important;
|
||||
}
|
||||
|
||||
.rainbowPaper {
|
||||
@@ -122,6 +242,7 @@
|
||||
border: 2px solid !important;
|
||||
color: white !important;
|
||||
border-radius: 12px !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
}
|
||||
|
||||
/* Easter egg notification */
|
||||
@@ -129,7 +250,12 @@
|
||||
position: fixed !important;
|
||||
top: 20px !important;
|
||||
right: 20px !important;
|
||||
background: linear-gradient(45deg,#ffff00, #88ff00, #00ff88, #00ffff) !important;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
hsla(calc(var(--rainbow-hue) * 1deg), 100%, 65%, 0.95),
|
||||
hsla(calc((var(--rainbow-hue) + 60) * 1deg), 100%, 70%, 0.95),
|
||||
hsla(calc((var(--rainbow-hue) + 120) * 1deg), 100%, 72%, 0.95)
|
||||
) !important;
|
||||
background-size: 300% 300% !important;
|
||||
animation: rainbowBackground 1s ease infinite, rainbowBorder 0.5s linear infinite !important;
|
||||
color: white !important;
|
||||
@@ -142,22 +268,24 @@
|
||||
box-shadow: 0 0 20px rgba(255, 255, 255, 0.8) !important;
|
||||
user-select: none !important;
|
||||
pointer-events: none !important;
|
||||
transition: opacity 0.4s ease !important;
|
||||
}
|
||||
|
||||
/* Specific component overrides */
|
||||
.rainbowMode [data-mantine-color-scheme] {
|
||||
background: linear-gradient(
|
||||
-45deg,
|
||||
var(--rainbow-angle),
|
||||
#ff0000, #ff8800, #ffff00, #88ff00, #00ff88, #00ffff, #0088ff, #8800ff, #ff0088, #ff0000
|
||||
) !important;
|
||||
background-size: 400% 400% !important;
|
||||
animation: rainbowBackground 3s ease infinite !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
}
|
||||
|
||||
/* Make all buttons rainbow in rainbow mode */
|
||||
.rainbowMode button {
|
||||
background: linear-gradient(
|
||||
45deg,
|
||||
calc(var(--rainbow-angle) + 45deg),
|
||||
#ffff00, #88ff00, #00ff88, #00ffff
|
||||
) !important;
|
||||
background-size: 100% 100% !important;
|
||||
@@ -166,6 +294,8 @@
|
||||
animation: rainbowBackground 2s ease infinite, rainbowBorder 1.5s linear infinite !important;
|
||||
color: white !important;
|
||||
font-weight: bold !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25) !important;
|
||||
}
|
||||
|
||||
/* Make all inputs rainbow in rainbow mode */
|
||||
@@ -173,7 +303,7 @@
|
||||
.rainbowMode select,
|
||||
.rainbowMode textarea {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
calc(var(--rainbow-angle) + 90deg),
|
||||
#ffff00, #88ff00, #00ff88, #00ffff
|
||||
) !important;
|
||||
background-size: 100% 100% !important;
|
||||
@@ -181,6 +311,8 @@
|
||||
border: 2px solid !important;
|
||||
animation: rainbowBackground 2.5s ease infinite, rainbowBorder 1.5s linear infinite !important;
|
||||
color: white !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
box-shadow: inset 0 0 12px rgba(255, 255, 255, 0.25) !important;
|
||||
}
|
||||
|
||||
/* Rainbow text class */
|
||||
@@ -188,6 +320,7 @@
|
||||
animation: rainbowText 3s linear infinite !important;
|
||||
font-weight: bold !important;
|
||||
text-shadow: 0 0 10px currentColor !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
}
|
||||
|
||||
/* Make all text rainbow */
|
||||
@@ -199,4 +332,5 @@
|
||||
.rainbowMode h6 {
|
||||
animation: rainbowText 3s linear infinite !important;
|
||||
font-weight: bold !important;
|
||||
filter: hue-rotate(calc(var(--rainbow-hue) * 1deg));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user