diff --git a/src/html/components/games-link.tsx b/src/html/components/games-link.tsx index 9e4cd4b0..e71341d2 100644 --- a/src/html/components/games-link.tsx +++ b/src/html/components/games-link.tsx @@ -1,3 +1,4 @@ +import { requestContext } from '@fastify/request-context' import { collections } from '../../database/collections' import { GameState } from '../../database/models/game.model' import { GameLiveIndicator } from './game-live-indicator' @@ -8,8 +9,14 @@ export async function GamesLink() { $in: [GameState.created, GameState.configuring, GameState.launching, GameState.started], }, }) + const url = requestContext.get('url') return ( - 0 && 'accent']} id="navbar-games-link"> + 0 && 'accent']} + id="navbar-games-link" + aria-current={url === '/games' ? 'page' : undefined} + > {gamesLiveCount > 0 ? : <>} Games diff --git a/src/html/components/navigation-bar.tsx b/src/html/components/navigation-bar.tsx index 1ff8cbbe..27f08424 100644 --- a/src/html/components/navigation-bar.tsx +++ b/src/html/components/navigation-bar.tsx @@ -1,3 +1,4 @@ +import { requestContext } from '@fastify/request-context' import type { User } from '../../auth/types/user' import { GamesLink } from './games-link' import { IconBrandDiscord, IconChartPie, IconCrown, IconHeart } from './icons' @@ -71,8 +72,9 @@ function Menu(props: Html.PropsWithChildren<{ user?: User | undefined }>) { } function MenuItem({ href, children }: Html.PropsWithChildren<{ href: string }>) { + const url = requestContext.get('url') return ( - + {children} ) diff --git a/src/html/index.ts b/src/html/index.ts index eb6bdb8b..f700cf30 100644 --- a/src/html/index.ts +++ b/src/html/index.ts @@ -2,12 +2,15 @@ import fp from 'fastify-plugin' import { z } from 'zod' import type { ZodTypeProvider } from 'fastify-type-provider-zod' import mime from 'mime' +import { resolve } from 'node:path' export const csses = new Map() export default fp( async app => { - await app.register((await import('./middleware/htmx')).default) + await app.register((await import('@fastify/autoload')).default, { + dir: resolve(import.meta.dirname, 'middleware'), + }) app.withTypeProvider().get( '/css/:fileName', diff --git a/src/messages/index.ts b/src/html/middleware/flash-messages.ts similarity index 100% rename from src/messages/index.ts rename to src/html/middleware/flash-messages.ts diff --git a/src/html/middleware/path.ts b/src/html/middleware/path.ts new file mode 100644 index 00000000..a54e9802 --- /dev/null +++ b/src/html/middleware/path.ts @@ -0,0 +1,15 @@ +import fp from 'fastify-plugin' + +declare module '@fastify/request-context' { + interface RequestContextData { + // Current request url (e.g. /games/1234) + url: string | undefined + } +} + +// eslint-disable-next-line @typescript-eslint/require-await +export default fp(async app => { + app.addHook('preHandler', async request => { + request.requestContext.set('url', request.url) + }) +}) diff --git a/src/html/styles/navigation-bar.css b/src/html/styles/navigation-bar.css index 73ac69a4..b18f1242 100644 --- a/src/html/styles/navigation-bar.css +++ b/src/html/styles/navigation-bar.css @@ -30,7 +30,7 @@ padding: 4px 10px; } - &.active { + &[aria-current='page'] { background-color: theme(colors.abru.dark.20); } diff --git a/src/main.ts b/src/main.ts index 20d7110a..66116dd8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -36,7 +36,6 @@ await app.register(await import('@fastify/static'), { await app.register((await import('@kitajs/fastify-html-plugin')).default) await app.register((await import('./html')).default) -await app.register((await import('./messages')).default) await app.register((await import('./websocket')).default) await app.register((await import('./auth')).default) await app.register((await import('./queue')).default)