mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-04 02:00:38 +00:00
use tailwind for frontpage
This commit is contained in:
+25
-44
@@ -1,4 +1,4 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { LitElement, html } from 'lit';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { Lobby } from "../core/Schemas";
|
||||
import { Difficulty, GameMapType, GameType } from '../core/game/Game';
|
||||
@@ -11,37 +11,9 @@ export class PublicLobby extends LitElement {
|
||||
private lobbiesInterval: number | null = null;
|
||||
private currLobby: Lobby = null;
|
||||
|
||||
static styles = css`
|
||||
.lobby-button {
|
||||
width: 100%;
|
||||
max-width: 25rem;
|
||||
margin: 0 auto;
|
||||
padding: 0.75rem;
|
||||
background: linear-gradient(to right, #2563eb, #3b82f6);
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
border-radius: 0.5rem;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.lobby-button:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.lobby-button.highlighted {
|
||||
background: linear-gradient(to right, #16a34a, #22c55e);
|
||||
}
|
||||
.lobby-name {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.lobby-info {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
color: rgb(219 234 254);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
`;
|
||||
createRenderRoot() {
|
||||
return this;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
@@ -83,19 +55,28 @@ export class PublicLobby extends LitElement {
|
||||
const lobby = this.lobbies[0];
|
||||
const timeRemaining = Math.max(0, Math.floor(lobby.msUntilStart / 1000));
|
||||
|
||||
// return html`
|
||||
// <div class="bg-blue-500 p-4 rounded-lg text-white hover:bg-blue-600">
|
||||
// Test Tailwind
|
||||
// </div>
|
||||
// `;
|
||||
|
||||
return html`
|
||||
<button
|
||||
@click=${() => this.lobbyClicked(lobby)}
|
||||
class="lobby-button ${this.isLobbyHighlighted ? 'highlighted' : ''}"
|
||||
>
|
||||
<div class="lobby-name">Next Public Game</div>
|
||||
<div class="lobby-info">
|
||||
<div>Starts in: ${timeRemaining}s</div>
|
||||
<div>Players: ${lobby.numClients}</div>
|
||||
<div>ID: ${lobby.id}</div>
|
||||
</div>
|
||||
</button>
|
||||
`;
|
||||
<button
|
||||
@click=${() => this.lobbyClicked(lobby)}
|
||||
class="w-full max-w-3xl mx-auto py-3 px-4 md:py-6 md:px-8 ${this.isLobbyHighlighted
|
||||
? 'bg-gradient-to-r from-green-600 to-green-500'
|
||||
: 'bg-gradient-to-r from-blue-600 to-blue-500'
|
||||
} text-white font-medium rounded-xl transition-opacity duration-200 hover:opacity-90"
|
||||
>
|
||||
<div class="text-xl md:text-2xl font-semibold mb-4">Next Game</div>
|
||||
<div class="flex justify-center gap-8 text-blue-100 text-m md:text-lg">
|
||||
<div>Starts in: ${timeRemaining}s</div>
|
||||
<div>Players: ${lobby.numClients}</div>
|
||||
<div>ID: ${lobby.id}</div>
|
||||
</div>
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
|
||||
private lobbyClicked(lobby: Lobby) {
|
||||
|
||||
+10
-35
@@ -1,4 +1,4 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { LitElement, html } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { MAX_USERNAME_LENGTH, validateUsername } from '../core/validations/username';
|
||||
@@ -9,37 +9,14 @@ const usernameKey: string = 'username';
|
||||
export class UsernameInput extends LitElement {
|
||||
@state() private username: string = '';
|
||||
@property({ type: String }) validationError: string = '';
|
||||
private _isValid: boolean = true;
|
||||
|
||||
private _isValid: boolean = true
|
||||
// Remove static styles since we're using Tailwind
|
||||
|
||||
static styles = css`
|
||||
input {
|
||||
width: 15rem;
|
||||
padding: .5rem;
|
||||
background-color: white;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.375rem;
|
||||
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
color: #111827;
|
||||
text-align: center;
|
||||
}
|
||||
input:focus {
|
||||
outline: none;
|
||||
ring: 2px;
|
||||
ring-color: #3b82f6;
|
||||
border-color: #3b82f6;
|
||||
}
|
||||
.error {
|
||||
color: #dc2626;
|
||||
background-color: #fff;
|
||||
padding: 4px;
|
||||
font-size: 0.875rem;
|
||||
border: 1px solid #dc2626;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
`;
|
||||
createRenderRoot() {
|
||||
// Disable shadow DOM to allow Tailwind classes to work
|
||||
return this;
|
||||
}
|
||||
|
||||
public getCurrentUsername(): string {
|
||||
return this.username;
|
||||
@@ -60,9 +37,10 @@ export class UsernameInput extends LitElement {
|
||||
@change=${this.handleChange}
|
||||
placeholder="Enter your username"
|
||||
maxlength="${MAX_USERNAME_LENGTH}"
|
||||
class="w-72 px-4 py-2 bg-white border border-gray-300 rounded-xl shadow-sm text-2xl text-gray-900 text-center focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
>
|
||||
${this.validationError
|
||||
? html`<div class="error">${this.validationError}</div>`
|
||||
? html`<div class="mt-2 px-3 py-1 text-lg text-red-600 bg-white border border-red-600 rounded">${this.validationError}</div>`
|
||||
: null}
|
||||
`;
|
||||
}
|
||||
@@ -70,8 +48,6 @@ export class UsernameInput extends LitElement {
|
||||
private handleChange(e: Event) {
|
||||
const input = e.target as HTMLInputElement;
|
||||
this.username = input.value.trim();
|
||||
|
||||
|
||||
const result = validateUsername(this.username)
|
||||
this._isValid = result.isValid
|
||||
if (result.isValid) {
|
||||
@@ -119,7 +95,6 @@ export class UsernameInput extends LitElement {
|
||||
}
|
||||
|
||||
public isValid(): boolean {
|
||||
return true
|
||||
return this._isValid
|
||||
return this._isValid;
|
||||
}
|
||||
}
|
||||
@@ -172,6 +172,11 @@ export class Leaderboard extends LitElement implements Layer {
|
||||
private _hidden = true;
|
||||
|
||||
render() {
|
||||
// return html`
|
||||
// <div class="bg-blue-500 p-4 rounded-lg text-white hover:bg-blue-600">
|
||||
// Test Tailwind
|
||||
// </div>
|
||||
// `;
|
||||
return html`
|
||||
<div class="leaderboard ${this._hidden ? 'hidden' : ''}">
|
||||
<table>
|
||||
|
||||
+45
-47
@@ -1,21 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>OpenFront (ALPHA)</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script
|
||||
async
|
||||
src="https://www.googletagmanager.com/gtag/js?id=AW-16702609763"
|
||||
></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
gtag("js", new Date());
|
||||
<html lang="en" class="h-full">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -28,49 +12,64 @@
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'AW-16702609763');
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="content">
|
||||
<h1><img src="../../resources/images/OpenFrontLogo.svg" alt="OpenFront.io"></h1>
|
||||
<h3 class="version">(v0.14.0)</h3>
|
||||
<body
|
||||
class="h-full overflow-hidden select-none font-sans min-h-screen bg-opacity-0 bg-cover bg-center bg-fixed transition-opacity duration-300 ease-in-out invisible opacity-0">
|
||||
<!-- Main container with responsive padding -->
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-4 sm:py-6 lg:py-8">
|
||||
<!-- Logo section with responsive scaling -->
|
||||
<img src="../../resources/images/OpenFrontLogo.svg" alt="OpenFront.io"
|
||||
class="h-auto w-1/2 lg:w-1/4 mx-auto transform sm:scale-125 md:scale-150 lg:scale-175">
|
||||
|
||||
<username-input></username-input>
|
||||
<!-- Version text scales with screen size -->
|
||||
<h3 class="font-sans text-center text-black pb-4 text-sm sm:text-base lg:text-lg">(v0.14.0)</h3>
|
||||
|
||||
<div class="lobby-section">
|
||||
<div class="p-2 flex items-center justify-center min-h-full w-full">
|
||||
<username-input></username-input>
|
||||
</div>
|
||||
|
||||
<!-- Public lobby section with responsive spacing -->
|
||||
<div class="w-full pb-4 p-2 flex items-center justify-center min-h-full">
|
||||
<public-lobby></public-lobby>
|
||||
</div>
|
||||
|
||||
<div class="button-container">
|
||||
<button id="single-player" class="primary-button">Single Player</button>
|
||||
<div style="display: flex; flex-direction: column; gap: 1rem; flex: 1;">
|
||||
<button id="host-lobby-button" class="secondary-button">Create Lobby</button>
|
||||
<button id="join-private-lobby-button" class="secondary-button">Join Lobby</button>
|
||||
<!-- Button container with responsive width and spacing -->
|
||||
<div
|
||||
class="flex flex-col sm:flex-row gap-4 sm:gap-6 lg:gap-8 max-w-sm sm:max-w-md lg:max-w-lg xl:max-w-xl mx-auto">
|
||||
<!-- Single Player button -->
|
||||
<button id="single-player" class="bg-blue-600 hover:bg-blue-700 text-white p-3 sm:p-4 lg:p-5
|
||||
font-bold text-lg sm:text-xl lg:text-2xl rounded-lg
|
||||
flex-1 border-none cursor-pointer transition-colors duration-300">
|
||||
Single Player
|
||||
</button>
|
||||
|
||||
<!-- Secondary buttons container -->
|
||||
<div class="flex flex-col gap-3 sm:gap-4 lg:gap-5 flex-1">
|
||||
<button id="host-lobby-button" class="bg-blue-100 hover:bg-blue-200 text-blue-900
|
||||
p-3 sm:p-4 lg:p-5 font-medium
|
||||
text-sm sm:text-base lg:text-lg rounded-md w-full
|
||||
border-none cursor-pointer transition-colors duration-300">
|
||||
Create Lobby
|
||||
</button>
|
||||
<button id="join-private-lobby-button" class="bg-blue-100 hover:bg-blue-200 text-blue-900
|
||||
p-3 sm:p-4 lg:p-5 font-medium
|
||||
text-sm sm:text-base lg:text-lg rounded-md w-full
|
||||
border-none cursor-pointer transition-colors duration-300">
|
||||
Join Lobby
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <a href="https://youtu.be/jvHEvbko3uw?si=znspkP84P76B1w5I" class="link-button green" target="_blank" rel="noopener noreferrer">
|
||||
How to Play
|
||||
</a>
|
||||
|
||||
<a href="https://discord.gg/k22YrnAzGp" class="link-button purple" target="_blank" rel="noopener noreferrer">
|
||||
Join the Discord!
|
||||
</a> -->
|
||||
|
||||
</div>
|
||||
|
||||
<div id="customMenu">
|
||||
<!-- Game components with appropriate spacing -->
|
||||
<div id="customMenu" class="mt-4 sm:mt-6 lg:mt-8">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<div id="app"></div>
|
||||
<div id="radialMenu" class="radial-menu"></div>
|
||||
|
||||
<!-- Game modals and overlays -->
|
||||
<single-player-modal></single-player-modal>
|
||||
<host-lobby-modal></host-lobby-modal>
|
||||
<join-private-lobby-modal></join-private-lobby-modal>
|
||||
@@ -83,13 +82,12 @@
|
||||
<player-info-overlay></player-info-overlay>
|
||||
<win-modal></win-modal>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script>
|
||||
window.addEventListener('DOMContentLoaded', (event) => {
|
||||
document.body.style.visibility = 'visible';
|
||||
document.body.style.opacity = 1;
|
||||
document.body.classList.remove('invisible', 'opacity-0');
|
||||
});
|
||||
</script>
|
||||
|
||||
<script defer src='https://static.cloudflareinsights.com/beacon.min.js'
|
||||
data-cf-beacon='{"token": "03d93e6fefb349c28ee69b408fa25a13"}'></script>
|
||||
</body>
|
||||
|
||||
@@ -1,256 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
html,
|
||||
body {
|
||||
touch-action: manipulation;
|
||||
-ms-touch-action: manipulation;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
* {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Overpass';
|
||||
src: url('/resources/fonts/overpass.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Overpass', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 100vh;
|
||||
background-color: #15151500;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
background-blend-mode: overlay;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
body {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
background: rgba(45, 45, 51, 0.173);
|
||||
backdrop-filter: blur(6px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
h1 {
|
||||
font-family: Arial, serif;
|
||||
text-align: center;
|
||||
color: #2e2e2e;
|
||||
font-size: 3em;
|
||||
margin: 1em 0 10px;
|
||||
}
|
||||
|
||||
h1 img {
|
||||
height: auto;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
transform: scale(2);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-family: Arial, serif;
|
||||
text-align: center;
|
||||
color: #2e2e2e;
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-family: Arial, serif;
|
||||
text-align: center;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
|
||||
.version {
|
||||
font-family: Arial, serif;
|
||||
text-align: center;
|
||||
color: #000000;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Username input */
|
||||
#username-container {
|
||||
margin-bottom: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#username {
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
border: 2px solid #007bff;
|
||||
border-radius: 5px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
margin: 1em auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.button-container {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
max-width: 20rem;
|
||||
max-height: 10rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.primary-button {
|
||||
background-color: #2563eb;
|
||||
color: white;
|
||||
padding: 1rem 1rem;
|
||||
font-weight: bold;
|
||||
font-size: 1.25rem;
|
||||
border-radius: 0.5rem;
|
||||
flex: 1;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.secondary-button {
|
||||
background-color: #dbeafe;
|
||||
color: #1e40af;
|
||||
padding: 1rem;
|
||||
font-weight: 500;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 0.375rem;
|
||||
width: 100%;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.link-button {
|
||||
display: block;
|
||||
max-width: 400px;
|
||||
margin: 1rem auto;
|
||||
padding: 0.5rem 1rem;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
border-radius: 0.375rem;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.link-button.green {
|
||||
background-color: #059669;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.link-button.purple {
|
||||
background-color: #4f46e5;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Discord */
|
||||
.discord-link {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: #5865F2;
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.discord-link:hover {
|
||||
background-color: #4752C4;
|
||||
}
|
||||
|
||||
.discord-logo {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
/* Media Queries */
|
||||
@media (min-width: 768px) {
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
|
||||
h3 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.lobby-section {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
#username {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.lobby-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.lobby-button {
|
||||
width: 50rem;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.lobby-name {
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.lobby-timer,
|
||||
.player-count {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.discord-link {
|
||||
top: 50px;
|
||||
right: 50px;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.discord-logo {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user