Skip to content

Commit 2a564fc

Browse files
committed
feat: Add TailwindCSS
1 parent e92c1b2 commit 2a564fc

12 files changed

Lines changed: 827 additions & 27 deletions

File tree

package-lock.json

Lines changed: 754 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
"notify-unpushed": "sh ./scripts/notify-unpushed.sh",
1111
"prettify": "prettier -w",
1212
"prepare": "sh ./scripts/setup.sh",
13-
"start": "npm run webpack-server & ts-node --swc src/index.ts",
13+
"servers": "npm run webpack-server & npm run tailwind-server",
14+
"start": "npm run servers & ts-node --swc src/index.ts",
15+
"tailwind-server": "npx @tailwindcss/cli -i ./src/web/styles/tailwind.css -o ./src/web/react/compiled/styles.css --watch",
1416
"test": "npm run lint && npm run tsc",
1517
"tsc": "tsc",
1618
"webpack-server": "webpack -c src/web/webpack/webpack.config.ts --watch"
@@ -20,6 +22,7 @@
2022
"license": "ISC",
2123
"dependencies": {
2224
"@swc/core": "^1.7.40",
25+
"@tailwindcss/cli": "^4.0.8",
2326
"axios": "^1.6.0",
2427
"chokidar": "^3.5.3",
2528
"discord.js": "^14.11.0",
@@ -30,6 +33,7 @@
3033
"ps-client": "^4.4.0",
3134
"react": "^18.2.0",
3235
"react-dom": "^18.2.0",
36+
"tailwindcss": "^4.0.8",
3337
"ts-loader": "^9.5.2",
3438
"ts-node": "^10.9.2",
3539
"tsconfig-paths": "^4.2.0",

src/web/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import connection from '@/database';
55
import { log } from '@/utils/logger';
66
import loadAPI from '@/web/loaders/api';
77
import loadBundles from '@/web/loaders/bundles';
8+
import loadStatic from '@/web/loaders/static';
89
import loadUI from '@/web/loaders/ui';
910

1011
const app = express();
@@ -14,6 +15,7 @@ app.use(json());
1415

1516
if (process.env.USE_WEB) {
1617
connection
18+
.then(() => loadStatic(app))
1719
.then(() => loadAPI(app))
1820
.then(() => loadUI(app))
1921
.then(() => loadBundles(app))

src/web/loaders/static.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { fsPath } from '@/utils/fsPath';
2+
3+
import type { Application } from 'express';
4+
5+
export default async function init(app: Application): Promise<void> {
6+
app.get('/styles.css', (req, res) => res.sendFile(fsPath('web', 'react', 'compiled', 'styles.css')));
7+
app.get('/favicon.ico', (req, res) => res.sendFile(fsPath('web', 'assets', 'favicon.ico')));
8+
}

src/web/react/compiled/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
*.js
2+
*.css

src/web/react/components/board.tsx

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,35 +26,30 @@ export function Table<T>({
2626
const rowLabels = getLabels(board.length, rowLabel);
2727
const colLabels = getLabels(board[0].length, colLabel);
2828
return (
29-
<table
30-
style={{
31-
borderCollapse: 'collapse',
32-
margin: 20,
33-
}}
34-
>
29+
<table className="border-collapse m-5">
3530
<tbody>
3631
<tr>
3732
<th />
3833
{colLabels.map(label => (
39-
<th style={{ color: 'gray', height: 20 }}>{label}</th>
34+
<th className="text-secondary h-5">{label}</th>
4035
))}
4136
<th />
4237
</tr>
4338

4439
{board.map((row, i) => (
4540
<tr>
46-
<th style={{ color: 'gray', width: 20 }}>{rowLabels[i]}</th>
41+
<th className="text-secondary w-5">{rowLabels[i]}</th>
4742
{row.map((cell, j) => (
4843
<Cell cell={cell} i={i} j={j} />
4944
))}
50-
<th style={{ color: 'gray', width: 20 }}>{rowLabels[i]}</th>
45+
<th className="text-secondary w-5">{rowLabels[i]}</th>
5146
</tr>
5247
))}
5348

5449
<tr>
5550
<th />
5651
{colLabels.map(label => (
57-
<th style={{ color: 'gray', height: 20 }}>{label}</th>
52+
<th className="text-secondary h-5">{label}</th>
5853
))}
5954
<th />
6055
</tr>

src/web/react/components/othello/index.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@ type OthelloLog = { action: 'play' | 'skip'; time: string; turn: 'W' | 'B'; ctx:
1414
type Board = (null | 'W' | 'B')[][];
1515
type GameState = { board: Board; sinceLast: number | null; at: Date; score: { W: number; B: number } };
1616

17-
const roundStyles = { height: 24, width: 24, display: 'inline-block', borderRadius: 100, marginLeft: 3, marginTop: 3 };
18-
1917
const Cell: CellRenderer<'W' | 'B' | null> = ({ cell }) => (
20-
<td style={{ height: 30, width: 30, background: 'green', borderCollapse: 'collapse', border: '1px solid black' }}>
21-
{cell ? <span style={{ ...roundStyles, background: cell === 'W' ? 'white' : 'black' }} /> : null}
18+
<td className="h-8 w-8 bg-green-600 border-collapse border border-primary leading-0">
19+
{cell ? <span className={`${cell === 'W' ? 'bg-white' : 'bg-black'} h-7 w-7 inline-block rounded-full m-0.5`} /> : null}
2220
</td>
2321
);
2422
const Board = memo(({ state }: { state: GameState }) => (
2523
<>
2624
<Table<'W' | 'B' | null> board={state.board} rowLabel="1-9" colLabel="A-Z" Cell={Cell} />
27-
{state.sinceLast
28-
? `Played after ${state.sinceLast / 1000}s.`
29-
: `Game started on ${state.at.toDateString()} at ${state.at.toLocaleTimeString()}.`}
25+
<span className="text-secondary">
26+
{state.sinceLast
27+
? `Played after ${state.sinceLast / 1000}s.`
28+
: `Game started on ${state.at.toDateString()} at ${state.at.toLocaleTimeString()}.`}
29+
</span>
3030
</>
3131
));
3232

@@ -83,17 +83,17 @@ const BoardWrapper = memo(({ states, game }: { states: GameState[]; game: GameMo
8383
);
8484

8585
return (
86-
<div style={{ display: 'flex', flexDirection: 'column', maxWidth: 800, alignItems: 'center' }}>
86+
<div className="flex flex-col items-center max-w-3xl m-10">
8787
<h1>
88-
{game.players.B.name} (Black) vs {game.players.W.name} (White) <small style={{ color: 'dimgray' }}>in {game.room}</small>
88+
{game.players.B.name} (Black) vs {game.players.W.name} (White) <small className="text-secondary">in {game.room}</small>
8989
</h1>
90-
<h2>{subHeading}</h2>
90+
<h2 className="text-secondary">{subHeading}</h2>
9191
<br />
92-
<h2 style={currentTurn === 0 ? { color: 'dimgray' } : {}}>{currentTurn === 0 ? 'Game start' : `Turn #${currentTurn}`}</h2>
92+
<h2 className={currentTurn === 0 ? 'text-secondary' : ''}>{currentTurn === 0 ? 'Game start' : `Turn #${currentTurn}`}</h2>
9393
{controls}
9494
<Board state={state} />
9595
{controls}
96-
<b style={{ margin: 10 }}>
96+
<b className="m-3">
9797
Score: {state.score.B} (Black) - {state.score.W} (White)
9898
</b>
9999
</div>

src/web/styles/base.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@layer base {
2+
h1 {
3+
@apply text-2xl;
4+
}
5+
h2 {
6+
@apply text-xl;
7+
}
8+
9+
button {
10+
@apply bg-purple-700 border-purple-900 border px-2 py-1 m-2 rounded-xl font-bold;
11+
&:hover {
12+
@apply bg-purple-800;
13+
}
14+
}
15+
}

src/web/styles/classes.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.bg-primary {
2+
@apply bg-zinc-50 dark:bg-zinc-900;
3+
}
4+
5+
.text-primary {
6+
@apply text-zinc-900 dark:text-white;
7+
}
8+
9+
.text-secondary {
10+
@apply text-zinc-700 dark:text-zinc-300;
11+
}
12+
13+
.border-primary {
14+
@apply border-zinc-800 dark:border-zinc-200;
15+
}

src/web/styles/tailwind.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@import 'tailwindcss';
2+
3+
@import './base.css';
4+
@import './classes.css';
5+
6+
@source './components';
7+
@source './templates';

0 commit comments

Comments
 (0)