add: generalized css classes and added a dark mode

This commit is contained in:
Lukian 2025-04-27 00:29:26 +02:00
parent 9806fc3b3c
commit 4ca8a21477
28 changed files with 101 additions and 297 deletions

View file

@ -8,7 +8,7 @@ export default function TopBar({ user }: { user: User | undefined }) {
const [burgerMenuOpen, setBurgerMenuOpen] = useState(false) const [burgerMenuOpen, setBurgerMenuOpen] = useState(false)
return ( return (
<div className="topbar"> <div className="forum-section topbar">
<div className="topbar-left"> <div className="topbar-left">
<Link to="/">Home</Link> <Link to="/">Home</Link>
<Link to="/channels">Channels</Link> <Link to="/channels">Channels</Link>

View file

@ -3,6 +3,26 @@ html {
min-height: 100vh; min-height: 100vh;
} }
.forum-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.forum-section {
width: 97%;
padding: 10px;
display: flex;
flex-direction: column;
align-items: start;
gap: 10px;
border: 1px solid #270722;
background-color: #fff6fd;
}
.cat { .cat {
width: 100px; width: 100px;
} }
@ -18,3 +38,28 @@ html {
.fish { .fish {
width: 300px; width: 300px;
} }
@media (prefers-color-scheme: dark) {
html {
background: linear-gradient(#121212, #1e1b29);
}
.forum-section {
border: 1px solid #a678af;
background-color: #1b1b23;
color: #e4d9ec;
}
a {
color: #b88edc;
text-decoration: underline;
}
a:hover {
color: #d4b4f0;
}
a:visited {
color: #a678af;
}
}

View file

@ -26,9 +26,9 @@ export default function NotFoundPage() {
}, []); }, []);
return ( return (
<div className="not-found-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="not-found-content"> <div className="forum-section">
<h2>404 - Page Not Found</h2> <h2>404 - Page Not Found</h2>
<p>Sorry, the page you are looking for does not exist.</p> <p>Sorry, the page you are looking for does not exist.</p>
<Link to="/">Go back to the homepage</Link> <Link to="/">Go back to the homepage</Link>

View file

@ -150,9 +150,9 @@ export default function ChannelPage({socket}: {socket: WebSocket}) {
if (noChannel) { if (noChannel) {
return ( return (
<div className="channel-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="channel"> <div className="forum-section">
<h2>Channel Not Found</h2> <h2>Channel Not Found</h2>
<p>Sorry, the channel you are looking for does not exist.</p> <p>Sorry, the channel you are looking for does not exist.</p>
<Link to="/">Go back to the homepage</Link> <Link to="/">Go back to the homepage</Link>
@ -163,9 +163,9 @@ export default function ChannelPage({socket}: {socket: WebSocket}) {
if (!channel) { if (!channel) {
return ( return (
<div className="channel-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="channel"> <div className="forum-section">
<p>Loading...</p> <p>Loading...</p>
</div> </div>
</div> </div>
@ -173,9 +173,9 @@ export default function ChannelPage({socket}: {socket: WebSocket}) {
} }
return ( return (
<div className="channel-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="channel"> <div className="forum-section">
<h2>Channel {channel.name}</h2> <h2>Channel {channel.name}</h2>
<p>{channel.description}</p> <p>{channel.description}</p>
<p>Owner: <Link to={`/u/${channel.owner_username}`}>{channel.owner_username}</Link></p> <p>Owner: <Link to={`/u/${channel.owner_username}`}>{channel.owner_username}</Link></p>

View file

@ -4,8 +4,6 @@ import { Channels, User } from "../types"
import axios from "axios" import axios from "axios"
import TopBar from "../components/TopBar" import TopBar from "../components/TopBar"
import "../styles/ChannelsPage.css"
export default function ChannelsPage({socket}: {socket: WebSocket}) { export default function ChannelsPage({socket}: {socket: WebSocket}) {
const [channels, setChannels] = useState<Channels>(); const [channels, setChannels] = useState<Channels>();
const [search, setSearch] = useState<string>(""); const [search, setSearch] = useState<string>("");
@ -64,9 +62,9 @@ export default function ChannelsPage({socket}: {socket: WebSocket}) {
if (!channels) { if (!channels) {
return ( return (
<div className="channels-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="channels-page-channels"> <div className="forum-section">
<h2>Channels</h2> <h2>Channels</h2>
<p>Loading...</p> <p>Loading...</p>
</div> </div>
@ -75,9 +73,9 @@ export default function ChannelsPage({socket}: {socket: WebSocket}) {
} }
return ( return (
<div className="channels-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="channels-page-channels"> <div className="forum-section">
<h2>Channels</h2> <h2>Channels</h2>
<Link to="/create-channel">Create channel</Link> <Link to="/create-channel">Create channel</Link>
<input <input

View file

@ -4,8 +4,6 @@ import { User } from "../types";
import axios from "axios"; import axios from "axios";
import TopBar from "../components/TopBar"; import TopBar from "../components/TopBar";
import "../styles/CreateChannel.css";
export default function CreateChannel() { export default function CreateChannel() {
const navigate = useNavigate(); const navigate = useNavigate();
const [name, setName] = useState(""); const [name, setName] = useState("");
@ -39,9 +37,9 @@ export default function CreateChannel() {
} }
return ( return (
<div className="create-channel-page"> <div className="forum-page">
<TopBar user={user}/> <TopBar user={user}/>
<div className="create-channel"> <div className="forum-section">
<h1>Create Channel</h1> <h1>Create Channel</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<p> <p>

View file

@ -4,8 +4,6 @@ import { User } from "../types";
import axios from "axios"; import axios from "axios";
import TopBar from "../components/TopBar"; import TopBar from "../components/TopBar";
import "../styles/CreateEmoji.css";
export default function CreateEmoji() { export default function CreateEmoji() {
const navigate = useNavigate(); const navigate = useNavigate();
const [name, setName] = useState(""); const [name, setName] = useState("");
@ -50,9 +48,9 @@ export default function CreateEmoji() {
} }
return ( return (
<div className="create-emoji-page"> <div className="forum-page">
<TopBar user={user}/> <TopBar user={user}/>
<div className="create-emoji"> <div className="forum-section">
<h1>Create Emoji</h1> <h1>Create Emoji</h1>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<p> <p>

View file

@ -4,8 +4,6 @@ import { Link } from "react-router-dom"
import axios from "axios" import axios from "axios"
import TopBar from "../components/TopBar" import TopBar from "../components/TopBar"
import "../styles/EditProfile.css"
export default function EditProfile() { export default function EditProfile() {
const [token, setToken] = useState<string>(""); const [token, setToken] = useState<string>("");
const [user, setUser] = useState<User>(); const [user, setUser] = useState<User>();
@ -92,9 +90,9 @@ export default function EditProfile() {
if (!user) { if (!user) {
return ( return (
<div className="edit-profile-page"> <div className="forum-page">
<TopBar user={user}/> <TopBar user={user}/>
<div className="edit-login"> <div className="forum-section">
<p>Please log in to edit your profile</p> <p>Please log in to edit your profile</p>
<Link to="/login">Login</Link> <Link to="/login">Login</Link>
</div> </div>
@ -103,9 +101,9 @@ export default function EditProfile() {
} }
return ( return (
<div className="edit-profile-page"> <div className="forum-page">
<TopBar user={user}/> <TopBar user={user}/>
<div className="edit-pfp"> <div className="forum-section">
<h2>Edit Profile Picture</h2> <h2>Edit Profile Picture</h2>
<form> <form>
<input type="file" name="pfp" id="pfp" /> <input type="file" name="pfp" id="pfp" />
@ -113,14 +111,14 @@ export default function EditProfile() {
<button onClick={deletePfp}>Delete</button> <button onClick={deletePfp}>Delete</button>
</form> </form>
</div> </div>
<div className="edit-username"> <div className="forum-section">
<h2>Edit Username</h2> <h2>Edit Username</h2>
<form> <form>
<input type="text" name="username" id="username" placeholder={user?.username} /> <input type="text" name="username" id="username" placeholder={user?.username} />
<button onClick={editUsername}>Save</button> <button onClick={editUsername}>Save</button>
</form> </form>
</div> </div>
<div className="edit-password"> <div className="forum-section">
<h2>Edit Password</h2> <h2>Edit Password</h2>
<form> <form>
<input type="password" name="old-password" id="old-password" placeholder="Old password" /> <input type="password" name="old-password" id="old-password" placeholder="Old password" />

View file

@ -4,8 +4,6 @@ import { Emojis, User } from "../types"
import axios from "axios" import axios from "axios"
import TopBar from "../components/TopBar" import TopBar from "../components/TopBar"
import "../styles/EmojisPage.css"
export default function EmojisPage({socket}: {socket: WebSocket}) { export default function EmojisPage({socket}: {socket: WebSocket}) {
const [emojis, setEmojis] = useState<Emojis>(); const [emojis, setEmojis] = useState<Emojis>();
const [search, setSearch] = useState<string>(""); const [search, setSearch] = useState<string>("");
@ -67,9 +65,9 @@ export default function EmojisPage({socket}: {socket: WebSocket}) {
if (!emojis) { if (!emojis) {
return ( return (
<div className="emojis-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="emojis-page-emojis"> <div className="forum-section">
<h2>Emojis</h2> <h2>Emojis</h2>
<p>Loading...</p> <p>Loading...</p>
</div> </div>
@ -78,10 +76,10 @@ export default function EmojisPage({socket}: {socket: WebSocket}) {
} }
return ( return (
<div className="emojis-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="emojis-page-emojis"> <div className="forum-section">
<h2>Channels</h2> <h2>Emojis</h2>
<Link to="/create-emoji">Create emoji</Link> <Link to="/create-emoji">Create emoji</Link>
<input <input
type="text" type="text"

View file

@ -146,7 +146,7 @@ export default function Home({socket}: {socket: WebSocket}) {
return ( return (
<div className="home"> <div className="home">
<TopBar user={user} /> <TopBar user={user} />
<div className="home-header"> <div className="forum-section home-header">
<div className="home-header-text"> <div className="home-header-text">
<h2>Welcome to Tanuki's forum !</h2> <h2>Welcome to Tanuki's forum !</h2>
<p> <p>
@ -156,7 +156,7 @@ export default function Home({socket}: {socket: WebSocket}) {
<img src="osaka_arch.png" alt="osaka" className="osaka"/> <img src="osaka_arch.png" alt="osaka" className="osaka"/>
</div> </div>
<div className="main-content"> <div className="main-content">
<div className="home-messages"> <div className="forum-section messages">
<h2>Last messages</h2> <h2>Last messages</h2>
<div className="messages-list"> <div className="messages-list">
{messages?.map((message) => ( {messages?.map((message) => (
@ -170,7 +170,7 @@ export default function Home({socket}: {socket: WebSocket}) {
))} ))}
</div> </div>
</div> </div>
<div className="channels"> <div className="forum-section channels">
<h2>Channels</h2> <h2>Channels</h2>
<div className="channels-content"> <div className="channels-content">
<Link to={'/channels'}>All channels</Link> <Link to={'/channels'}>All channels</Link>

View file

@ -3,8 +3,6 @@ import { useState } from "react";
import { useNavigate, Link } from "react-router-dom"; import { useNavigate, Link } from "react-router-dom";
import TopBar from "../components/TopBar"; import TopBar from "../components/TopBar";
import "../styles/Login.css";
export default function Login() { export default function Login() {
const [username, setUsername] = useState(""); const [username, setUsername] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
@ -24,9 +22,9 @@ export default function Login() {
} }
return ( return (
<div className="login-page"> <div className="forum-page">
<TopBar user={undefined}/> <TopBar user={undefined}/>
<div className="login"> <div className="forum-section">
<h2>Login</h2> <h2>Login</h2>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<input <input

View file

@ -3,8 +3,6 @@ import { useState } from "react";
import { useNavigate, Link } from "react-router-dom"; import { useNavigate, Link } from "react-router-dom";
import TopBar from "../components/TopBar"; import TopBar from "../components/TopBar";
import "../styles/Register.css";
export default function Register () { export default function Register () {
const [username, setUsername] = useState(""); const [username, setUsername] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
@ -31,9 +29,9 @@ export default function Register () {
} }
return ( return (
<div className="register-page"> <div className="forum-page">
<TopBar user={undefined}/> <TopBar user={undefined}/>
<div className="register"> <div className="forum-section">
<h2>Register</h2> <h2>Register</h2>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<p> <p>

View file

@ -97,9 +97,9 @@ export default function UserPage({socket}: {socket: WebSocket}) {
if (noUser) { if (noUser) {
return ( return (
<div className="user-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="user"> <div className="forum-section">
<h2>User Not Found</h2> <h2>User Not Found</h2>
<p>Sorry, the user you are looking for does not exist.</p> <p>Sorry, the user you are looking for does not exist.</p>
<Link to="/">Go back to the homepage</Link> <Link to="/">Go back to the homepage</Link>
@ -110,9 +110,9 @@ export default function UserPage({socket}: {socket: WebSocket}) {
if (!pageUser) { if (!pageUser) {
return ( return (
<div className="user-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="user"> <div className="forum-section">
<h2>Loading...</h2> <h2>Loading...</h2>
</div> </div>
</div> </div>
@ -120,9 +120,9 @@ export default function UserPage({socket}: {socket: WebSocket}) {
} }
return ( return (
<div className="user-page"> <div className="forum-page">
<TopBar user={user} /> <TopBar user={user} />
<div className="user"> <div className="forum-section">
<div className="user-top"> <div className="user-top">
<img src={`/api/users/${pageUser.username}/pfp`} alt="pfp" className="user-page-pfp" /> <img src={`/api/users/${pageUser.username}/pfp`} alt="pfp" className="user-page-pfp" />
<h2>{pageUser.username}</h2> <h2>{pageUser.username}</h2>
@ -142,7 +142,7 @@ export default function UserPage({socket}: {socket: WebSocket}) {
</div> </div>
)} )}
</div> </div>
<div className="user-messages"> <div className="forum-section">
<h2>Last messages</h2> <h2>Last messages</h2>
<div className="messages-list"> <div className="messages-list">
{messages?.map((message) => ( {messages?.map((message) => (

View file

@ -4,8 +4,6 @@ import { User, Users } from "../types"
import axios from "axios" import axios from "axios"
import TopBar from "../components/TopBar" import TopBar from "../components/TopBar"
import "../styles/UsersPage.css"
export default function UsersPage({socket}: {socket: WebSocket}) { export default function UsersPage({socket}: {socket: WebSocket}) {
const [users, setUsers] = useState<Users>(); const [users, setUsers] = useState<Users>();
const [search, setSearch] = useState<string>(""); const [search, setSearch] = useState<string>("");
@ -64,9 +62,9 @@ export default function UsersPage({socket}: {socket: WebSocket}) {
if (!users) { if (!users) {
return ( return (
<div className="users-page"> <div className="forum-page">
<TopBar user={thisUser} /> <TopBar user={thisUser} />
<div className="users-page-users"> <div className="forum-section">
<h2>Users</h2> <h2>Users</h2>
<p>Loading...</p> <p>Loading...</p>
</div> </div>
@ -75,9 +73,9 @@ export default function UsersPage({socket}: {socket: WebSocket}) {
} }
return ( return (
<div className="users-page"> <div className="forum-page">
<TopBar user={thisUser} /> <TopBar user={thisUser} />
<div className="users-page-users"> <div className="forum-section">
<h2>Users</h2> <h2>Users</h2>
<input <input
type="text" type="text"

View file

@ -6,10 +6,3 @@
width: 100%; width: 100%;
gap: 20px; gap: 20px;
} }
.not-found-content {
width: 97%;
border: 1px solid #270722;
padding: 10px;
background-color: #fff6fd;
}

View file

@ -1,19 +1,3 @@
.channel-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.channel {
width: 97%;
border: 1px solid #270722;
padding: 10px;
background-color: #fff6fd;
}
.message-form { .message-form {
margin: 16px 0; margin: 16px 0;
position: relative; position: relative;

View file

@ -1,19 +0,0 @@
.channels-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.channels-page-channels {
width: 97%;
border: 1px solid #270722;
padding: 10px;
background-color: #fff6fd;
display: flex;
flex-direction: column;
align-items: start;
gap: 10px;
}

View file

@ -1,15 +0,0 @@
.create-channel-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.create-channel {
width: 97%;
border: 1px solid #270722;
padding: 10px;
background-color: #fff6fd;
}

View file

@ -1,15 +0,0 @@
.create-emoji-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.create-emoji {
width: 97%;
border: 1px solid #270722;
padding: 10px;
background-color: #fff6fd;
}

View file

@ -1,44 +0,0 @@
.edit-profile-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.edit-login {
width: 97%;
border: 1px solid #270722;
padding: 10px;
display: flex;
flex-direction: column;
background-color: #fff6fd;
}
.edit-pfp {
width: 97%;
border: 1px solid #270722;
padding: 10px;
display: flex;
flex-direction: column;
background-color: #fff6fd;
}
.edit-username {
width: 97%;
border: 1px solid #270722;
padding: 10px;
display: flex;
flex-direction: column;
background-color: #fff6fd;
}
.edit-password {
width: 97%;
border: 1px solid #270722;
padding: 10px;
display: flex;
flex-direction: column;
background-color: #fff6fd;
}

View file

@ -1,24 +0,0 @@
.emojis-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.emojis-page-emojis {
width: 97%;
border: 1px solid #270722;
padding: 10px;
background-color: #fff6fd;
display: flex;
flex-direction: column;
align-items: start;
gap: 10px;
}
.emoji {
max-width: 50px;
max-height: 50px;
}

View file

@ -17,22 +17,13 @@
} }
.home-header { .home-header {
width: 97%;
border: 1px solid #270722;
display: flex;
justify-content: space-between; justify-content: space-between;
align-items: top; flex-direction: row;
padding: 10px;
background-color: #fff6fd;
} }
.home-messages { .messages {
width: 60%; width: 60%;
border: 1px solid #270722; min-height: 100%;
padding: 10px;
background-color: #fff6fd;
display: flex;
flex-direction: column;
align-items: center; align-items: center;
} }
@ -47,12 +38,7 @@
.channels { .channels {
width: 34%; width: 34%;
border: 1px solid #270722;
min-height: 100%; min-height: 100%;
padding: 10px;
display: flex;
flex-direction: column;
background-color: #fff6fd;
align-items: center; align-items: center;
} }

View file

@ -1,15 +0,0 @@
.login-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.login {
width: 97%;
border: 1px solid #270722;
padding: 10px;
background-color: #fff6fd;
}

View file

@ -36,3 +36,9 @@
max-width: 1em; max-width: 1em;
max-height: 1em; max-height: 1em;
} }
@media (prefers-color-scheme: dark) {
.message {
border: 1px solid #a678af;
}
}

View file

@ -1,15 +0,0 @@
.register-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.register {
width: 97%;
border: 1px solid #270722;
padding: 10px;
background-color: #fff6fd;
}

View file

@ -1,11 +1,7 @@
.topbar { .topbar {
width: 97%;
display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
border: 1px solid #270722; flex-direction: row;
padding: 10px;
background-color: #fff6fd;
} }
.topbar-left { .topbar-left {

View file

@ -1,20 +1,5 @@
.user-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.user { .user {
width: 97%;
border: 1px solid #270722;
padding: 10px;
display: flex;
flex-direction: column;
align-items: start; align-items: start;
background-color: #fff6fd;
} }
.user-top { .user-top {
@ -29,15 +14,6 @@
border-radius: 50%; border-radius: 50%;
} }
.user-messages {
width: 97%;
border: 1px solid #270722;
padding: 10px;
display: flex;
flex-direction: column;
background-color: #fff6fd;
}
.messages-list { .messages-list {
width: 100%; width: 100%;
display: flex; display: flex;

View file

@ -1,19 +0,0 @@
.users-page {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
width: 100%;
gap: 20px;
}
.users-page-users {
width: 97%;
border: 1px solid #270722;
padding: 10px;
background-color: #fff6fd;
display: flex;
flex-direction: column;
align-items: start;
gap: 10px;
}