Compare commits

...

2 Commits

Author SHA1 Message Date
29b1c69d78 Make website more colorful
All checks were successful
Publish Docker image / Push Docker image to Docker Hub (push) Successful in 1m19s
2025-02-28 20:52:17 +01:00
34ef0c7940 Extract colors 2025-02-28 18:51:56 +01:00
11 changed files with 844 additions and 138 deletions

View File

@ -1,19 +1,63 @@
import Game from "./pages/Game";
import {useContext} from "react";
import {useContext, useEffect, useState} from "react";
import {StateContext} from "@/common/contexts/StateContext";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faMusic} from "@fortawesome/free-solid-svg-icons";
import {faDrum, faGuitar, faHeadphones, faMusic} from "@fortawesome/free-solid-svg-icons";
import Home from "@/pages/Home";
const App = () => {
const {currentState} = useContext(StateContext);
const [cursorPos, setCursorPos] = useState({ x: 0, y: 0 });
const musicNotes = [
{ id: 1, top: "8%", left: "20%", icon: faMusic, scale: 1.2 },
{ id: 2, top: "75%", left: "85%", icon: faGuitar, scale: 1 },
{ id: 3, top: "65%", left: "12%", icon: faHeadphones, scale: 1.1 },
{ id: 4, top: "20%", left: "70%", icon: faDrum, scale: 0.9 }
];
useEffect(() => {
const handleMouseMove = (e) => {
if (!handleMouseMove.ticking) {
handleMouseMove.ticking = true;
requestAnimationFrame(() => {
setCursorPos({ x: e.clientX, y: e.clientY });
handleMouseMove.ticking = false;
});
}
};
handleMouseMove.ticking = false;
window.addEventListener('mousemove', handleMouseMove);
return () => window.removeEventListener('mousemove', handleMouseMove);
}, []);
return (
<>
<div className="background-elements">
<FontAwesomeIcon icon={faMusic} className="music-note note-1" />
<FontAwesomeIcon icon={faMusic} className="music-note note-2" />
<FontAwesomeIcon icon={faMusic} className="music-note note-3" />
<div className="glow-point point-1" style={{
transform: `translate(${(cursorPos.x / window.innerWidth - 0.5) * -20}px, ${(cursorPos.y / window.innerHeight - 0.5) * -20}px)`
}}></div>
<div className="glow-point point-2" style={{
transform: `translate(${(cursorPos.x / window.innerWidth - 0.5) * 15}px, ${(cursorPos.y / window.innerHeight - 0.5) * 15}px)`
}}></div>
<div className="glow-point point-3" style={{
transform: `translate(${(cursorPos.x / window.innerWidth - 0.5) * -10}px, ${(cursorPos.y / window.innerHeight - 0.5) * -10}px)`
}}></div>
{musicNotes.map((note) => (
<div key={`note-${note.id}`} className={`music-note note-${note.id}`}
style={{
top: note.top,
left: note.left,
fontSize: `${note.scale * 60}pt`,
transform: `translate(${(cursorPos.x / window.innerWidth - 0.5) * -5 * note.scale}px, ${(cursorPos.y / window.innerHeight - 0.5) * -5 * note.scale}px)`
}}
>
<FontAwesomeIcon icon={note.icon} />
</div>
))}
</div>
{currentState === "Home" && <Home />}
{currentState === "Game" && <Game />}

View File

@ -1,6 +1,15 @@
$background: rgba(255, 255, 255, 0.14)
$border: rgba(255, 255, 255, 0.35)
$white: #ECECEC
$green: #26EE5E
$black: #000
$dark-gray: #1e1e1e
$light-gray: #aaa
$red: #ff0000
$green: #26EE5E
$pink: #ff6bb3
$blue: #4d9dff
$purple: #9c6bff
$cyan: #6bffea
$yellow: #ffde6b
$mint-green: #85ffbd

View File

@ -10,10 +10,70 @@ body
color: #E0E0E0
font-family: 'Bangers', sans-serif
height: 100vh
background: linear-gradient(135deg, #0f2027, #203a43, #2c5364)
width: 100vw
background-size: 300% 300%
animation: shifting-background 30s ease infinite
background: linear-gradient(45deg, #4d3ae7 0%, #b84bc3 50%, #ff6a88 100%) fixed
user-select: none
overflow: hidden
position: relative
&:before
content: ""
position: fixed
top: 0
left: 0
right: 0
bottom: 0
background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z' fill='%23ffffff' fill-opacity='0.05' fill-rule='evenodd'/%3E%3C/svg%3E")
.background-overlay
position: fixed
top: 0
left: 0
width: 100vw
height: 100vh
z-index: 0
pointer-events: none
.rotating-gradient
position: absolute
top: 50%
left: 50%
width: 250vh
height: 250vh
transform: translate(-50%, -50%)
background: conic-gradient(from 0deg, rgba(255, 102, 196, 0.2), rgba(102, 204, 255, 0.2), rgba(255, 209, 128, 0.2), rgba(133, 255, 189, 0.2), rgba(255, 102, 196, 0.2))
border-radius: 50%
animation: rotate-background 180s linear infinite
will-change: transform
transform-origin: center center
opacity: 0.7
filter: blur(40px)
&:after
content: ""
position: fixed
top: 0
left: 0
right: 0
bottom: 0
background: radial-gradient(circle at center, transparent 0%, rgba(0, 0, 0, 0.1) 60%, rgba(0, 0, 0, 0.4) 100%)
z-index: 1
pointer-events: none
::-webkit-scrollbar
width: 8px
background-color: rgba(0, 0, 0, 0.2)
border-radius: 4px
::-webkit-scrollbar-thumb
background-color: rgba(255, 255, 255, 0.15)
border-radius: 4px
border: 1px solid rgba(255, 255, 255, 0.05)
&:hover
background-color: rgba(255, 255, 255, 0.25)
.glassy
background: $background
@ -21,40 +81,150 @@ body
border: 2px solid $border
border-radius: 0.8rem
::-webkit-scrollbar
width: 10px
.background-elements
position: absolute
position: fixed
top: 0
left: 0
width: 100%
height: 100%
width: 100vw
height: 100vh
overflow: hidden
z-index: 0
z-index: 2
pointer-events: none
.glow-point
position: absolute
width: 250px
height: 250px
border-radius: 50%
filter: blur(100px)
opacity: 0.4
will-change: transform
transform: translateZ(0)
&.point-1
top: 20%
left: 10%
background-color: rgba(255, 102, 196, 0.8)
animation: float-glow 15s infinite alternate ease-in-out
&.point-2
top: 70%
left: 80%
background-color: rgba(102, 204, 255, 0.8)
animation: float-glow 18s infinite alternate-reverse ease-in-out
&.point-3
top: 80%
left: 20%
background-color: rgba(133, 255, 189, 0.8)
animation: float-glow 12s infinite alternate ease-in-out 2s
.music-note
position: absolute
font-size: 24pt
color: rgba(255, 255, 255, 0.5)
animation: float-notes 5s infinite ease-in-out
font-size: 60pt
opacity: 0.7
will-change: transform, opacity, filter
filter: drop-shadow(0 0 15px rgba(255, 255, 255, 0.7))
transform: translateZ(0)
backface-visibility: hidden
@for $i from 1 through 5
&.note-#{$i}
animation-name: float-note-#{$i}, pulse-note
animation-duration: #{10 + ($i * 1)}s, 5s
animation-timing-function: ease-in-out, ease-in-out
animation-iteration-count: infinite, infinite
animation-direction: alternate, alternate
animation-delay: #{$i * 0.7}s, #{$i * 0.4}s
@if $i % 4 == 0
color: rgba(255, 102, 196, 0.8)
@else if $i % 4 == 1
color: rgba(102, 204, 255, 0.8)
@else if $i % 4 == 2
color: rgba(255, 209, 128, 0.8)
@else
color: rgba(133, 255, 189, 0.8)
&.note-1
top: 20%
left: 30%
.card-element
background: rgba(255, 255, 255, 0.07)
backdrop-filter: blur(10px)
border: 1px solid rgba(255, 255, 255, 0.2)
border-radius: 20px
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1), 0 0 20px rgba(255, 255, 255, 0.1)
overflow: hidden
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)
animation: card-float 6s infinite ease-in-out alternate
&.note-2
top: 60%
left: 80%
&:hover
transform: translateY(-10px) scale(1.02)
box-shadow: 0 15px 50px rgba(0, 0, 0, 0.2), 0 0 40px rgba(255, 255, 255, 0.2)
border: 1px solid rgba(255, 255, 255, 0.4)
&.note-3
top: 90%
left: 50%
@keyframes float-notes
@keyframes shifting-background
0%
background-position: 0% 0%
50%
background-position: 100% 100%
100%
background-position: 0% 0%
@keyframes rotate-background
0%
transform: translate(-50%, -50%) rotate(0deg)
100%
transform: translate(-50%, -50%) rotate(360deg)
@keyframes float-glow
0%, 100%
transform: translate(0, 0) scale(1)
filter: blur(100px)
50%
transform: translate(30px, -20px) scale(1.2)
filter: blur(80px)
@keyframes card-float
0%, 100%
transform: translateY(0)
50%
transform: translateY(-10px)
100%
transform: translateY(0)
transform: translateY(-8px)
@keyframes float-note-1
0%, 100%
transform: translateY(0) rotate(0deg)
50%
transform: translateY(-40px) rotate(10deg)
@keyframes float-note-2
0%, 100%
transform: translateY(0) rotate(0deg)
50%
transform: translateY(-30px) rotate(-8deg)
@keyframes float-note-3
0%, 100%
transform: translateY(0) rotate(0deg)
50%
transform: translateY(-50px) rotate(15deg)
@keyframes float-note-4
0%, 100%
transform: translateY(0) rotate(0deg)
33%
transform: translateY(-25px) rotate(-5deg)
66%
transform: translateY(-40px) rotate(5deg)
@keyframes float-note-5
0%, 100%
transform: translateY(0) rotate(0deg)
50%
transform: translateY(-35px) rotate(-12deg)
@keyframes pulse-note
0%, 100%
filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.5))
opacity: 0.6
50%
filter: drop-shadow(0 0 20px rgba(255, 255, 255, 0.7))
opacity: 0.9

View File

@ -7,10 +7,11 @@ import {faMessage} from "@fortawesome/free-solid-svg-icons";
export const Game = () => {
const {setCurrentState} = useContext(StateContext);
const [messages, setMessages] = useState([{sender: "Marco", text: "Hallo!"},]);
const [messages, setMessages] = useState([{sender: "Marco", text: "Hallo!"}]);
const [inputValue, setInputValue] = useState("");
const messageEndRef = useRef(null);
useEffect(() => {
messageEndRef.current?.scrollIntoView({behavior: "smooth"});
}, [messages]);
@ -24,13 +25,15 @@ export const Game = () => {
return (
<div className="game-page">
<div className="background-overlay">
<div className="rotating-gradient"></div>
</div>
<div className="main-content">
<div className="song-display">
<h2>ToneGuessr</h2>
<div className="song-card">
<img
src="https://mir-s3-cdn-cf.behance.net/project_modules/1400/fe529a64193929.5aca8500ba9ab.jpg"
alt="Song"/>
<img src="https://mir-s3-cdn-cf.behance.net/project_modules/1400/fe529a64193929.5aca8500ba9ab.jpg" alt="Song"/>
<div className="song-info">
<div className="song-names">Black Steam</div>
<div className="song-description">von Carrot Quest GmbH</div>
@ -52,7 +55,8 @@ export const Game = () => {
<div ref={messageEndRef}></div>
</div>
<div className="chat-input">
<input type="text" value={inputValue} onChange={(e) => setInputValue(e.target.value)}
<input type="text" value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()}
placeholder="Gib eine Nachricht ein..."
/>

View File

@ -32,7 +32,7 @@ export const MusicSlider = () => {
useEffect(() => {
const handleMouseMove = (e) => dragging && handleFrequencyChange(e);
const handleMouseUpGlobal = () => dragging && handleMouseUp();
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUpGlobal);
@ -83,25 +83,22 @@ export const MusicSlider = () => {
return (
<div className="otamatone-container">
<div className="otamatone" onMouseDown={handleMouseDown}>
<div className="otamatone-face">
<div className="otamatone-mouth" style={{
height: `${10 + (frequency / 2000) * 40}px`,
width: `${10 + (frequency / 2000) * 40}px`
}}></div>
<div className="otamatone-eyes">
<div className="eye left-eye"></div>
<div className="eye right-eye"></div>
</div>
</div>
<div className="otamatone-neck" ref={sliderRef}>
<div className="frequency-indicator" style={{left: `${(frequency - 20) / 1980 * 100}%`}}></div>
<div className="note-marker" style={{left: '10%', pointerEvents: 'none'}}></div>
<div className="note-marker" style={{left: '50%', pointerEvents: 'none'}}></div>
<div className="note-marker" style={{left: '90%', pointerEvents: 'none'}}></div>
</div>
<div className="otamatone-face">
<div
className="otamatone-mouth"
style={{
height: `${10 + (frequency / 2000) * 40}px`,
width: `${10 + (frequency / 2000) * 40}px`
}}
></div>
<div className="otamatone-eyes">
<div className="eye left-eye"></div>
<div className="eye right-eye"></div>
</div>
</div>
</div>
</div>
)

View File

@ -1,3 +1,5 @@
@import "@/common/styles/colors"
.otamatone-container
display: flex
justify-content: center
@ -6,77 +8,169 @@
left: 0
right: 0
bottom: 0
padding: 20px
background-color: rgba(30, 30, 30, 0.5)
backdrop-filter: blur(10px)
border-radius: 20px
margin: 20px
z-index: 1
padding: 20px 30px 30px 30px
background: rgba(20, 20, 30, 0.75)
backdrop-filter: blur(15px)
border-radius: 30px 30px 0 0
margin: 0
z-index: 10
box-shadow: 0 -5px 30px rgba(0, 0, 0, 0.3), 0 -2px 10px rgba(255, 255, 255, 0.1)
border-top: 1px solid rgba(255, 255, 255, 0.3)
border-left: 1px solid rgba(255, 255, 255, 0.2)
border-right: 1px solid rgba(255, 255, 255, 0.2)
transition: transform 0.3s ease
width: 100%
.otamatone
display: flex
flex-direction: row
align-items: center
cursor: pointer
padding: 10px
padding: 15px
width: 100%
max-width: 1200px
margin: 0 auto
.otamatone-neck
flex: 1
height: 20px
background: linear-gradient(135deg, #000, #444)
border-radius: 10px
height: 40px
background: linear-gradient(135deg, #2c2c3a, #444455)
border-radius: 20px
position: relative
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5), inset 0 -2px 10px rgba(255, 255, 255, 0.15)
margin: 0 20px
&:before
content: ""
position: absolute
left: 0
right: 0
top: 0
height: 50%
border-radius: 20px 20px 0 0
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), transparent)
pointer-events: none
&:after
content: ""
position: absolute
left: 5%
right: 5%
top: 50%
height: 1px
background: rgba(255, 255, 255, 0.2)
pointer-events: none
.frequency-indicator
position: absolute
top: -10px
width: 20px
height: 20px
background-color: #ff0000
top: -20px
width: 40px
height: 40px
background: linear-gradient(135deg, $pink, darken($pink, 15%))
border-radius: 50%
transform: translateX(-50%)
box-shadow: 0 0 20px rgba(255, 107, 179, 0.7)
border: 2px solid rgba(255, 255, 255, 0.8)
z-index: 1
transition: transform 0.1s ease
cursor: grab
&:hover
transform: translateX(-50%) scale(1.1)
&:active
cursor: grabbing
transform: translateX(-50%) scale(0.95)
.note-marker
position: absolute
top: -30px
font-size: 24pt
color: #fff
top: -50px
font-size: 32pt
color: $white
text-shadow: 0 0 15px rgba(255, 255, 255, 0.7)
font-weight: bold
.otamatone-face
width: 100px
height: 100px
background: radial-gradient(circle, #fff, #ddd)
width: 140px
height: 140px
background: radial-gradient(circle at 30% 30%, #fff, #f0f0f0)
border-radius: 50%
display: flex
flex-direction: column
align-items: center
justify-content: center
position: absolute
position: relative
left: 0
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2)
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5), inset 0 -3px 10px rgba(0, 0, 0, 0.2), inset 0 3px 10px rgba(255, 255, 255, 0.8)
border: 1px solid rgba(255, 255, 255, 0.9)
margin-right: 15px
&:before
content: ""
position: absolute
width: 80%
height: 80%
border-radius: 50%
background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.9), transparent)
pointer-events: none
.otamatone-eyes
display: flex
justify-content: space-between
width: 60%
position: absolute
top: 30px
top: 40px
.eye
width: 15px
height: 15px
width: 22px
height: 22px
background-color: #000
border-radius: 50%
position: relative
animation: blink 4s infinite ease-in-out
&:before
content: ""
position: absolute
width: 30%
height: 30%
background-color: #fff
border-radius: 50%
top: 15%
left: 15%
.left-eye
margin-right: 10px
margin-right: 20px
.right-eye
margin-left: 10px
margin-left: 20px
.otamatone-mouth
background-color: #000
border-radius: 50%
position: absolute
bottom: 10px
bottom: 30px
width: 30px
height: 30px
transition: all 0.3s ease
animation: mouth-pulse 5s infinite alternate ease-in-out
@keyframes blink
0%, 90%, 100%
transform: scaleY(1)
95%
transform: scaleY(0.1)
@keyframes mouth-pulse
0%, 100%
transform: scale(1)
50%
transform: scale(1.2)
@keyframes slider-enter
0%
transform: translateY(100%)
opacity: 0
100%
transform: translateY(0)
opacity: 1

View File

@ -1,10 +1,15 @@
@import "@/common/styles/colors"
.game-page
display: flex
flex-direction: column
align-items: center
justify-content: center
height: 100vh
width: 100vw
padding: 20px
position: relative
animation: page-fade-in 1s ease-in-out
.main-content
display: flex
@ -13,7 +18,9 @@
justify-content: center
width: 100%
padding: 20px
z-index: 1
z-index: 2
position: relative
animation: float-up 1.5s ease-out
.song-display
display: flex
@ -22,31 +29,74 @@
justify-content: center
width: 50%
margin-right: 20px
color: #fff
color: $white
text-align: center
h2
font-size: 36pt
color: #fff
margin-bottom: 20px
font-size: 52pt
color: $white
margin-bottom: 25px
position: relative
z-index: 2
background: linear-gradient(135deg, $pink, $blue 45%, $mint-green 65%, $yellow 85%, $pink)
background-size: 300% 100%
animation: title-shimmer 10s infinite alternate ease-in-out, title-float 6s infinite ease-in-out
-webkit-background-clip: text
background-clip: text
-webkit-text-fill-color: transparent
filter: drop-shadow(0 0 15px rgba(255, 255, 255, 0.7))
letter-spacing: 0.1em
font-weight: bold
&:before
content: "ToneGuessr"
position: absolute
z-index: -1
left: 0
top: 0
background: none
-webkit-text-fill-color: transparent
filter: blur(15px) brightness(1.3)
opacity: 0.6
width: 100%
height: 100%
.song-card
display: flex
flex-direction: row
align-items: center
background-color: rgba(255, 255, 255, 0.1)
padding: 20px
background: rgba(255, 255, 255, 0.08)
padding: 25px
border-radius: 20px
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5)
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.2), 0 0 20px rgba(255, 255, 255, 0.1)
backdrop-filter: blur(10px)
border: 1px solid rgba(255, 255, 255, 0.2)
max-width: 500px
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)
will-change: transform, box-shadow
transform: translateZ(0)
backface-visibility: hidden
animation: card-pulse 6s infinite alternate ease-in-out
&:hover
transform: translateY(-10px) scale(1.02)
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3), 0 0 30px rgba(255, 255, 255, 0.15)
border: 1px solid rgba(255, 255, 255, 0.4)
img
width: 100px
height: 100px
border-radius: 10px
margin-right: 20px
width: 120px
height: 120px
border-radius: 15px
margin-right: 25px
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4)
transition: transform 0.3s ease
will-change: transform
transform: translateZ(0)
animation: album-rotate 10s infinite alternate ease-in-out
&:hover
transform: scale(1.1) rotate(5deg)
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5), 0 0 40px rgba(102, 204, 255, 0.3)
.song-info
display: flex
@ -54,76 +104,227 @@
align-items: flex-start
.song-names
font-size: 24pt
color: #fff
font-size: 28pt
color: $white
margin-bottom: 10px
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5)
animation: text-shimmer 5s infinite alternate ease-in-out
.song-description
font-size: 14pt
color: #aaa
font-size: 16pt
color: $border
opacity: 0.8
position: relative
&:after
content: ""
position: absolute
bottom: -5px
left: 0
width: 0%
height: 1px
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.7), transparent)
transition: all 0.4s ease
&:hover:after
width: 100%
.chat-window
width: 50%
height: 400px
background: rgba(255, 255, 255, 0.1)
height: 450px
background: rgba(255, 255, 255, 0.08)
backdrop-filter: blur(10px)
border-radius: 10px
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1)
border-radius: 20px
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.2), 0 0 20px rgba(255, 255, 255, 0.1)
border: 1px solid rgba(255, 255, 255, 0.2)
display: flex
flex-direction: column
overflow: hidden
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)
will-change: box-shadow, border
transform: translateZ(0)
backface-visibility: hidden
animation: card-float 6s infinite ease-in-out alternate 0.5s
&:hover
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3), 0 0 30px rgba(255, 255, 255, 0.15)
border: 1px solid rgba(255, 255, 255, 0.4)
.chat-header
display: flex
align-items: center
padding: 10px
padding: 15px
background: rgba(30, 30, 30, 0.5)
border-bottom: 1px solid rgba(255, 255, 255, 0.2)
svg
font-size: 18pt
color: $white
filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.5))
animation: icon-pulse 3s infinite alternate ease-in-out
.chat-title
margin-left: 10px
font-size: 16pt
color: #fff
margin-left: 15px
font-size: 18pt
color: $white
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5)
.chat-messages
flex: 1
padding: 10px
overflow-y: auto
color: #fff
color: $white
position: relative
&::-webkit-scrollbar
width: 8px
background: rgba(0, 0, 0, 0.2)
border-radius: 4px
&::-webkit-scrollbar-thumb
background: rgba(255, 255, 255, 0.2)
border-radius: 4px
&:hover
background: rgba(255, 255, 255, 0.3)
.message
margin-bottom: 10px
padding: 8px 12px
border-radius: 12px
background: rgba(255, 255, 255, 0.05)
backdrop-filter: blur(5px)
border: 1px solid rgba(255, 255, 255, 0.1)
transition: all 0.3s ease
animation: message-fade-in 0.5s ease-out
&:hover
background: rgba(255, 255, 255, 0.1)
transform: translateY(-2px)
.message-sender
font-weight: bold
color: $yellow
margin-right: 5px
.message-text
margin-left: 10px
margin-left: 5px
.chat-input
display: flex
padding: 10px
padding: 15px
background: rgba(30, 30, 30, 0.5)
border-top: 1px solid rgba(255, 255, 255, 0.2)
input
flex: 1
padding: 10px
padding: 12px 15px
border: none
border-radius: 5px
border-radius: 10px
outline: none
background: rgba(255, 255, 255, 0.2)
color: #fff
background: rgba(0, 0, 0, 0.3)
color: $white
font-family: 'Bangers', sans-serif
letter-spacing: 0.1rem
backdrop-filter: blur(5px)
transition: all 0.3s ease
will-change: box-shadow
&:focus
box-shadow: 0 0 20px rgba(255, 255, 255, 0.3)
background: rgba(0, 0, 0, 0.4)
button
margin-left: 10px
padding: 10px
background-color: #203a43
color: #fff
margin-left: 15px
padding: 12px 20px
background: linear-gradient(135deg, $purple, $blue)
color: $white
border: none
border-radius: 5px
border-radius: 10px
cursor: pointer
font-family: 'Bangers', sans-serif
letter-spacing: 0.1rem
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5)
will-change: transform, background, box-shadow
transform: translateZ(0)
position: relative
overflow: hidden
&:before
content: ""
position: absolute
top: -50%
left: -50%
width: 200%
height: 200%
background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, transparent 70%)
opacity: 0
transition: opacity 0.5s ease
&:hover
background-color: #1e1e1e
transform: translateY(-3px) scale(1.05)
background: linear-gradient(135deg, lighten($purple, 5%), lighten($blue, 5%))
box-shadow: 0 0 20px rgba(102, 204, 255, 0.7)
&:before
opacity: 1
animation: rotate-background 5s linear infinite
@keyframes subtle-text-glow
0%, 100%
text-shadow: 0 0 10px rgba(255, 255, 255, 0.4)
50%
text-shadow: 0 0 15px rgba(255, 255, 255, 0.6), 0 0 25px rgba(255, 255, 255, 0.3)
@keyframes title-glow
0%, 100%
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5), 0 0 30px rgba(102, 204, 255, 0.4)
50%
text-shadow: 0 0 15px rgba(255, 255, 255, 0.7), 0 0 40px rgba(102, 204, 255, 0.6), 0 0 60px rgba(102, 204, 255, 0.3)
@keyframes text-shimmer
0%, 100%
opacity: 0.95
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5)
50%
opacity: 1
text-shadow: 0 0 15px rgba(255, 255, 255, 0.7), 0 0 25px rgba(133, 255, 189, 0.5)
@keyframes album-rotate
0%, 100%
transform: rotate(-2deg)
50%
transform: rotate(2deg)
@keyframes icon-pulse
0%, 100%
filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.5))
transform: scale(1)
50%
filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.8))
transform: scale(1.1)
@keyframes message-fade-in
0%
opacity: 0
transform: translateY(10px)
100%
opacity: 1
transform: translateY(0)
@keyframes title-shimmer
0%
background-position: 0% 50%
50%
background-position: 100% 50%
100%
background-position: 0% 50%
@keyframes title-float
0%, 100%
transform: translateY(0) scale(1) rotate(-1deg)
filter: drop-shadow(0 0 15px rgba(255, 255, 255, 0.7))
50%
transform: translateY(-10px) scale(1.05) rotate(1deg)
filter: drop-shadow(0 0 25px rgba(255, 255, 255, 0.9)) drop-shadow(0 0 50px rgba(102, 204, 255, 0.6))

View File

@ -9,9 +9,18 @@ export const Home = () => {
return (
<div className="home-page">
<div className="background-overlay">
<div className="rotating-gradient"></div>
</div>
<div className="logo-container">
<h1 className="logo">ToneGuessr</h1>
<p className="tagline">Das Frequenzspiel für Marco :3</p>
</div>
<div className="action-area">
<ActionCard title="Raum beitreten" icon={faArrowRightToBracket} onClick={() => {}} />
<ActionCard title="Raum erstellen" icon={faPlusSquare} onClick={() => setCurrentState("Game")} />
<ActionCard title="Join Room" icon={faArrowRightToBracket} onClick={() => {}} />
<ActionCard title="Create Room" icon={faPlusSquare} onClick={() => setCurrentState("Game")} />
</div>
</div>
);

View File

@ -1,11 +1,11 @@
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import "./styles.sass";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
export const ActionCard = ({ title, icon, onClick }) => {
return (
<div className="glassy action-card" onClick={onClick}>
<FontAwesomeIcon icon={icon} />
<h1>{title}</h1>
</div>
);
}
export const ActionCard = ({title, icon, onClick}) => {
return (
<div className="action-card" onClick={onClick}>
<FontAwesomeIcon icon={icon} />
<h1>{title}</h1>
</div>
);
};

View File

@ -1,23 +1,96 @@
@use "@/common/styles/colors" as *
@import "@/common/styles/colors"
.action-card
display: flex
flex-direction: column
padding: 2rem 0
width: 13rem
padding: 2.5rem 1.5rem
width: 15rem
text-align: center
gap: 2rem
transition: all 0.3s ease-in-out
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275)
cursor: pointer
user-select: none
background: rgba(255, 255, 255, 0.07)
backdrop-filter: blur(10px)
border: 1px solid rgba(255, 255, 255, 0.2)
border-radius: 20px
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1), 0 0 20px rgba(255, 255, 255, 0.1)
position: relative
overflow: hidden
transform: translateZ(0)
backface-visibility: hidden
animation: card-pulse 6s infinite alternate ease-in-out
&:nth-child(odd)
animation-delay: 1s
&:before
content: ""
position: absolute
top: -50%
left: -50%
width: 200%
height: 200%
background: radial-gradient(circle, rgba(255, 255, 255, 0.15) 0%, transparent 70%)
opacity: 0
transition: opacity 0.5s ease
svg
font-size: 52pt
font-size: 62pt
color: $white
filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.3))
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275)
transform: translateZ(0)
animation: icon-glow 5s infinite alternate ease-in-out
h1
margin: 0
color: $white
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5)
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275)
transform: translateZ(0)
position: relative
&:after
content: ""
position: absolute
bottom: -5px
left: 25%
width: 0%
height: 2px
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.7), transparent)
transition: all 0.4s ease
&:hover
transform: scale(1.1) translate(0, -0.5rem) rotate(0.5deg)
transform: scale(1.05) translate(0, -0.5rem) rotate(0.5deg)
border: 1px solid rgba(255, 255, 255, 0.5)
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2), 0 0 30px rgba(255, 255, 255, 0.15), 0 0 0 2px rgba(255, 255, 255, 0.3)
&:before
opacity: 1
animation: rotate-background 15s linear infinite
svg
transform: scale(1.2)
filter: drop-shadow(0 0 25px rgba(255, 255, 255, 0.8))
h1
transform: scale(1.05)
&:after
width: 50%
left: 25%
@keyframes card-pulse
0%, 100%
transform: scale(1)
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1), 0 0 20px rgba(255, 255, 255, 0.1)
50%
transform: scale(1.02)
box-shadow: 0 6px 35px rgba(0, 0, 0, 0.15), 0 0 25px rgba(255, 255, 255, 0.15)
@keyframes icon-glow
0%, 100%
filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.3))
50%
filter: drop-shadow(0 0 20px rgba(255, 255, 255, 0.6))

View File

@ -1,15 +1,120 @@
@import "@/common/styles/colors"
.home-page
display: flex
flex-direction: column
align-items: center
justify-content: center
height: 100%
width: 100%
height: 100vh
width: 100vw
position: relative
z-index: 1
animation: page-fade-in 1s ease-in-out
.logo-container
text-align: center
margin-bottom: 2rem
animation: logo-entrance 1.2s cubic-bezier(0.175, 0.885, 0.32, 1.275)
position: relative
.logo
font-size: 80pt
line-height: 1.1
margin: 0
padding: 0 15px
background: linear-gradient(135deg, $pink, $blue 45%, $mint-green 65%, $yellow 85%, $pink)
background-size: 300% 100%
animation: logo-shimmer 10s infinite alternate ease-in-out, logo-glow 5s infinite alternate ease-in-out
-webkit-background-clip: text
background-clip: text
-webkit-text-fill-color: transparent
filter: drop-shadow(0 0 12px rgba(255, 255, 255, 0.6))
position: relative
letter-spacing: 0.1em
font-weight: bold
&:before
content: "ToneGuessr"
position: absolute
z-index: -1
left: 0
top: 0
background: none
-webkit-text-fill-color: transparent
filter: blur(15px) brightness(1.2)
opacity: 0.7
width: 100%
height: 100%
animation: text-pulse 5s infinite alternate ease-in-out
.tagline
font-size: 24pt
margin: 5px 0 0 0
color: rgba(255, 255, 255, 0.9)
text-shadow: 0 0 15px rgba(255, 255, 255, 0.4)
animation: tagline-fade 2s ease-in-out
letter-spacing: 0.1em
.action-area
margin-top: 5rem
margin-top: 2rem
display: flex
gap: 3rem
flex-wrap: wrap
justify-content: center
justify-content: center
position: relative
z-index: 2
animation: float-up 1.5s ease-out
@keyframes logo-entrance
0%
opacity: 0
transform: scale(0.8) translateY(-50px)
100%
opacity: 1
transform: scale(1) translateY(0)
@keyframes logo-glow
0%, 100%
filter: drop-shadow(0 0 12px rgba(255, 255, 255, 0.6))
transform: scale(1) rotate(-1deg)
50%
filter: drop-shadow(0 0 20px rgba(255, 255, 255, 0.9)) drop-shadow(0 0 40px rgba(102, 204, 255, 0.5))
transform: scale(1.05) rotate(1deg)
@keyframes tagline-fade
0%
opacity: 0
transform: translateY(10px)
100%
opacity: 1
transform: translateY(0)
@keyframes page-fade-in
0%
opacity: 0
100%
opacity: 1
@keyframes float-up
0%
opacity: 0
transform: translateY(50px)
100%
opacity: 1
transform: translateY(0)
@keyframes logo-shimmer
0%
background-position: 0% 50%
50%
background-position: 100% 50%
100%
background-position: 0% 50%
@keyframes text-pulse
0%, 100%
opacity: 0.5
filter: blur(15px) brightness(1.2)
50%
opacity: 0.8
filter: blur(20px) brightness(1.5)