Theme files are cached under a path that only changes with Keycloak's version, for 30 days, so returning players kept the grey stylesheet. It is renamed to login.css, and theme files are now cached for an hour.
3.8 KiB
3.8 KiB
Theme polish: design
See requirements.md; requirement ids (R1.1, …) are referenced below.
Decisions
| Decision | Reason |
|---|---|
The web app writes the theme's id to a mancala_theme cookie; a small script in the login theme reads it and puts the theme's class on <html> |
Keycloak's pages are on another origin (localhost:8080, auth.playmancala.app), so they cannot read the app's localStorage. Cookies are shared: host-only cookies across the ports of localhost, and a cookie for playmancala.app with its subdomains (R1.2). |
The script runs in <head>, before the page is drawn |
No flash of another theme. |
Without the cookie, the script picks Ceviz or Yeşim from prefers-color-scheme (R1.3) |
The app's default theme is Ceviz (dark); Yeşim is its only light theme. |
darkMode=false in the theme; the script adds PatternFly's pf-v5-theme-dark itself for the dark themes |
Keycloak's own dark mode follows the system and would fight the chosen theme. |
The theme stays a stylesheet on top of keycloak.v2, now with the three themes' tokens copied from apps/frontend/src/styles/app.css |
Templates stay Keycloak's, so upgrades need no template changes. |
| The logo and the small board on the card are masks filled with the theme's colors | One image each for all three themes. |
| The app's name comes from CSS by the page's language | The realm's display name is one string; the header shows "Köçürme" for Turkish and "Mancala" otherwise, like the web app. |
| Notyf stays for messages, configured for the top centre and restyled with the theme's variables (R2) | It is used from plain functions (Util.checkConnectionAndMaybeAlert), not only components; a React toast would need a context everywhere. |
Login theme (apps/keycloak/themes/mancala/login)
theme.properties:darkMode=false,scripts=js/theme.js, stylescss/styles.css css/login.css.js/theme.js: readsmancala_theme(ceviz,gece,yesim), falls back to the color scheme, addst-<id>and, for Ceviz and Gece,pf-v5-theme-darkto<html>.css/login.css: the Bricolage Grotesque font; the tokens of.t-ceviz,.t-gece,.t-yesim; PatternFly's variables mapped to them; the header like the app's (logo, name), the card on--surface, inputs on--surface2, primary buttons in--accent, secondary ones outlined, links in--ink, errors in--live.img/logo-mask.svg,img/board-mask.svg: alpha masks.
Web app
Header (R3)
AppHeader: logo, the page's actions (children), how to play,SettingsMenu,AccountMenu. The signed-in user comes from anAuthUserContextthatMancalaAppprovides, so pages need not pass it down.SettingsMenu(new) replacesThemeSwatches: a@szhsin/react-menumenu like the account menu, with a "Theme" header and one checkbox item per theme (swatch, name). Checked items in every menu (the theme, the last bot level) show a check at their end instead of the library's mark in front.- Icon buttons in the header use
.ibtn(round, no outline, a surface on hover and while open); the account button showsgetInitialsin an accent circle. - Home: the header's actions get
hide-m; a.qa.show-mrow at the top of the page holds New Game and the bot menu (BotLevelMenuwith a full button) below 640 px.
Messages and the theme cookie
theme/themes.ts:saveThemeCookie(theme), called withapplyThemeClassat start and on every theme change. The cookie lasts a year,SameSite=Lax,Secureon https, and on a real domain is set for the last two labels of the host (playmancala.app).util/Notyf.ts:position: { x: "center", y: "top" }, a shorter duration, no icons, dismissible by click.styles/app.css: Notyf's container below the header; the toast in--inkon--bg(an inverted chip, readable on every theme), the app's font, rounded.