diff --git a/apps/keycloak/themes/mancala/login/resources/css/mancala.css b/apps/keycloak/themes/mancala/login/resources/css/mancala.css index 86d0b7d..eabc7d0 100644 --- a/apps/keycloak/themes/mancala/login/resources/css/mancala.css +++ b/apps/keycloak/themes/mancala/login/resources/css/mancala.css @@ -1,108 +1,111 @@ /* - * Mancala look for keycloak.v2's login pages. Loaded after keycloak.v2's styles.css. - * Colors come from LightTheme and DarkTheme in packages/core/src/theme; text colors are darker (or lighter) than - * the game's where the game's own would not be readable on the board color. - * keycloak.v2 adds pf-v5-theme-dark to when the system prefers a dark color scheme. + * The web app's look for keycloak.v2's login pages (docs/specs/theme-polish). Loaded after keycloak.v2's styles.css. + * js/theme.js puts the player's theme on as t-ceviz, t-gece or t-yesim; their colors are copied from + * apps/frontend/src/styles/app.css, keep them in step. The dark themes also get pf-v5-theme-dark. */ -:root { - --mancala-bg: #bbbbbb; - --mancala-bar: #7b7b7b; - --mancala-bar-text: #ebebeb; - --mancala-board: #9b9b9b; - --mancala-pit: #c4c4c4; - --mancala-pit-readonly: #b0b0b0; - --mancala-pit-edge: #4d4d4d; - --mancala-pit-shadow: rgba(0, 0, 0, 0.22); - --mancala-stone: #5b5b5b; - --mancala-stone-hover: #474747; - --mancala-stone-text: #f2f2f2; - --mancala-ink: #262626; - --mancala-ink-soft: #333333; - --mancala-ink-strong: #000000; - --mancala-hover: rgba(0, 0, 0, 0.08); - --mancala-divider: #6b6b6b; - --mancala-danger: #6b0900; - --mancala-board-image: url("../img/board.svg"); - --mancala-bar-height: 57px; - --mancala-font: serif; +@import url("https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,600;12..96,700;12..96,800&display=swap"); - --pf-v5-global--FontFamily--text: var(--mancala-font); - --pf-v5-global--FontFamily--heading: var(--mancala-font); - --pf-v5-global--Color--100: var(--mancala-ink); - --pf-v5-global--Color--200: var(--mancala-ink-soft); - --pf-v5-global--link--Color: var(--mancala-ink); - --pf-v5-global--link--Color--hover: var(--mancala-ink-strong); - --pf-v5-global--danger-color--100: var(--mancala-danger); +.t-ceviz { + --bg: #1f1712; --surface: #2a2019; --surface2: #382a20; --line: rgba(246, 234, 216, .10); + --ink: #f6ead8; --muted: #c4ad93; --accent: #f2b84b; --onAccent: #2a1a0a; + --accentSoft: rgba(242, 184, 75, .45); --live: #ff8a73; --miniBg: #5b3d28; + color-scheme: dark; } -:root.pf-v5-theme-dark { - --mancala-bg: #414141; - --mancala-bar: #313131; - --mancala-bar-text: #aaaaaa; - --mancala-board: #313131; - --mancala-pit: #606060; - --mancala-pit-readonly: #4b4b4b; - --mancala-pit-edge: #8a8a8a; - --mancala-pit-shadow: rgba(0, 0, 0, 0.45); - --mancala-stone: #aaaaaa; - --mancala-stone-hover: #bdbdbd; - --mancala-stone-text: #1e1e1e; - --mancala-ink: #e0e0e0; - --mancala-ink-soft: #bbbbbb; - --mancala-ink-strong: #ffffff; - --mancala-hover: rgba(255, 255, 255, 0.08); - --mancala-divider: #555555; - --mancala-danger: #ff8a80; - --mancala-board-image: url("../img/board-dark.svg"); +.t-gece { + --bg: #0c1220; --surface: #141c30; --surface2: #1d2744; --line: rgba(238, 241, 248, .09); + --ink: #eef1f8; --muted: #9aa6c2; --accent: #e2b36a; --onAccent: #241707; + --accentSoft: rgba(226, 179, 106, .45); --live: #ff8a7a; --miniBg: #1d2a4d; + color-scheme: dark; +} + +.t-yesim { + --bg: #e9ebe3; --surface: #f7f8f3; --surface2: #dde0d3; --line: rgba(29, 39, 33, .12); + --ink: #1d2721; --muted: #4f5d55; --accent: #2a7650; --onAccent: #ffffff; + --accentSoft: rgba(42, 118, 80, .4); --live: #b43a26; --miniBg: #d3d6c8; + color-scheme: light; +} + +:root:is(.t-ceviz, .t-gece, .t-yesim) { + --font: 'Bricolage Grotesque', system-ui, sans-serif; + --bar-height: 69px; + + --pf-v5-global--FontFamily--text: var(--font); + --pf-v5-global--FontFamily--heading: var(--font); + --pf-v5-global--Color--100: var(--ink); + --pf-v5-global--Color--200: var(--muted); + --pf-v5-global--BackgroundColor--100: var(--surface); + --pf-v5-global--BackgroundColor--200: var(--bg); + --pf-v5-global--BorderColor--100: var(--line); + --pf-v5-global--link--Color: var(--ink); + --pf-v5-global--link--Color--hover: var(--accent); + --pf-v5-global--primary-color--100: var(--accent); + --pf-v5-global--danger-color--100: var(--live); + --pf-v5-global--danger-color--200: var(--live); } .login-pf body { - background: var(--mancala-bg); - font-family: var(--mancala-font); + background: var(--bg); + color: var(--ink); + font-family: var(--font); } -/* Header: the game's app bar with its logo and title */ +/* Header: the app's header with its logo and name */ #kc-header { position: fixed; inset: 0 0 auto 0; z-index: 10; - height: var(--mancala-bar-height); + height: var(--bar-height); margin: 0; - padding: 0 4vw; + padding: 0 32px; + box-sizing: border-box; display: flex; align-items: center; - background: var(--mancala-bar); + background: var(--bg); + border-bottom: 1px solid var(--line); } +/* The realm's name is replaced by the app's, which is "Köçürme" in Turkish. */ #kc-header-wrapper { display: flex; align-items: center; gap: 10px; margin: 0; padding: 0; - font-family: var(--mancala-font); - font-size: 2em; - font-weight: bold; - line-height: 1; + font-size: 0; letter-spacing: normal; text-transform: none; - text-align: start; - color: var(--mancala-bar-text) !important; + color: var(--ink) !important; } #kc-header-wrapper::before { content: ""; flex: none; - width: 30px; - height: 30px; - background: url("../img/logo.svg") center / contain no-repeat; + width: 34px; + height: 34px; + background: var(--accent); + -webkit-mask: url("../img/logo-mask.svg") center / contain no-repeat; + mask: url("../img/logo-mask.svg") center / contain no-repeat; +} + +#kc-header-wrapper::after { + content: "Mancala"; + font-family: var(--font); + font-size: 24px; + font-weight: 800; + letter-spacing: -.02em; + line-height: 1; +} + +:lang(tr) #kc-header-wrapper::after { + content: "Köçürme"; } .pf-v5-c-login { min-height: 100vh; - padding-block-start: calc(var(--mancala-bar-height) + 2rem); + padding-block-start: calc(var(--bar-height) + 2rem); padding-block-end: 2rem; } @@ -112,24 +115,42 @@ grid-template-columns: minmax(0, 30rem); } -/* Card: the board, with a small board at the start of a game on top */ +/* Card: the app's card, with a board at the start of a game on top */ .pf-v5-c-login__main { - --pf-v5-c-login__main--BackgroundColor: var(--mancala-board); - --pf-v5-c-login__main--BoxShadow: 0 8px 24px rgba(0, 0, 0, 0.18); - --pf-v5-c-login__main-footer-band--BorderTopColor: var(--mancala-divider); + --pf-v5-c-login__main--BackgroundColor: var(--surface); + --pf-v5-c-login__main--BoxShadow: 0 20px 50px rgba(0, 0, 0, .25); + --pf-v5-c-login__main-footer-band--BorderTopColor: var(--line); + --pf-v5-c-login__main-footer-band--BackgroundColor: transparent; + position: relative; padding-block-start: 2rem; - border-radius: 24px; - color: var(--mancala-ink); + border-radius: 28px; + color: var(--ink); +} + +.pf-v5-c-login__main::before, +.pf-v5-c-login__main::after { + content: ""; + display: block; + width: min(calc(100% - 4rem), 280px); + aspect-ratio: 328 / 92; + margin: 0 auto; } .pf-v5-c-login__main::before { - content: ""; - display: block; - width: min(calc(100% - 4rem), 260px); - aspect-ratio: 312 / 76; - margin: 0 auto; - background: var(--mancala-board-image) center / contain no-repeat; + background: var(--miniBg); + -webkit-mask: url("../img/board-mask.svg") center / contain no-repeat; + mask: url("../img/board-mask.svg") center / contain no-repeat; +} + +.pf-v5-c-login__main::after { + position: absolute; + top: 2rem; + left: 50%; + transform: translateX(-50%); + background: var(--accent); + -webkit-mask: url("../img/stones-mask.svg") center / contain no-repeat; + mask: url("../img/stones-mask.svg") center / contain no-repeat; } .pf-v5-c-login__main-header { @@ -138,43 +159,56 @@ } #kc-page-title { - color: var(--mancala-ink); - font-family: var(--mancala-font); - font-size: 1.5rem; - font-weight: bold; + color: var(--ink); + font-family: var(--font); + font-size: 1.6rem; + font-weight: 800; + letter-spacing: -.02em; } .pf-v5-c-login__main hr { - border-color: var(--mancala-divider); + border-color: var(--line); } .pf-v5-c-login__main a:not(.pf-v5-c-button) { - color: var(--mancala-ink); + color: var(--ink); + font-weight: 700; text-decoration: underline; + text-decoration-color: var(--accentSoft); + text-underline-offset: 3px; } .pf-v5-c-login__main a:not(.pf-v5-c-button):hover { - color: var(--mancala-ink-strong); + color: var(--accent); + text-decoration-color: currentColor; } -/* Inputs: pits */ +.pf-v5-c-form__label, +.pf-v5-c-form__label-text { + color: var(--ink); + font-weight: 700; +} + +.pf-v5-c-login__main .pf-v5-c-helper-text, +.pf-v5-c-login__main .pf-v5-c-check__label, +.pf-v5-c-login__main-footer-band { + color: var(--muted); +} + +/* Inputs */ .pf-v5-c-form-control { - --pf-v5-c-form-control--BackgroundColor: var(--mancala-pit); - --pf-v5-c-form-control--Color: var(--mancala-ink); - --pf-v5-c-form-control--m-placeholder--Color: var(--mancala-ink-soft); - --pf-v5-c-form-control--m-readonly--BackgroundColor: var(--mancala-pit-readonly); - --pf-v5-c-form-control__toggle-icon--Color: var(--mancala-ink); + --pf-v5-c-form-control--BackgroundColor: var(--surface2); + --pf-v5-c-form-control--Color: var(--ink); + --pf-v5-c-form-control--m-placeholder--Color: var(--muted); + --pf-v5-c-form-control--m-readonly--BackgroundColor: var(--bg); + --pf-v5-c-form-control__toggle-icon--Color: var(--ink); --pf-v5-c-form-control--PaddingLeft: 1rem; --pf-v5-c-form-control--PaddingRight: 1rem; - border: 1px solid var(--mancala-pit-edge); - border-radius: 999px; - box-shadow: inset 0 2px 5px var(--mancala-pit-shadow); - font-family: var(--mancala-font); -} - -.pf-v5-c-form-control:has(textarea) { - border-radius: 16px; + min-height: 46px; + border: 1.5px solid var(--line); + border-radius: 14px; + font-family: var(--font); } .pf-v5-c-form-control::before, @@ -184,6 +218,7 @@ .pf-v5-c-form-control > :is(input, select, textarea) { font-family: inherit; + color: var(--ink); background-color: transparent; border-radius: inherit; } @@ -192,103 +227,194 @@ padding-inline-start: 1rem; } +.pf-v5-c-form-control > select option { + background: var(--surface); + color: var(--ink); +} + .pf-v5-c-form-control > :is(input, select, textarea):focus { outline: none; } .pf-v5-c-form-control:hover { - border-color: var(--mancala-ink); + border-color: var(--muted); } .pf-v5-c-form-control:focus-within { - border-color: var(--mancala-ink); - outline: 2px solid var(--mancala-ink); - outline-offset: 2px; + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accentSoft); } .pf-v5-c-form-control.pf-m-error { - border-color: var(--mancala-danger); - box-shadow: inset 0 2px 5px var(--mancala-pit-shadow), 0 0 0 1px var(--mancala-danger); + border-color: var(--live); +} + +.pf-v5-c-form-control.pf-m-error .pf-v5-c-form-control__icon.pf-m-status { + color: var(--live); } .pf-v5-c-login__main .pf-v5-c-helper-text__item.pf-m-error, .pf-v5-c-login__main .pf-v5-c-helper-text__item.pf-m-error .pf-v5-c-helper-text__item-text, .pf-v5-c-login__main .pf-v5-c-helper-text__item-text.pf-m-error { - color: var(--mancala-danger); + color: var(--live); + font-weight: 700; } -/* Password field and its show button form one pill */ +/* The language select in the card's header */ -.pf-v5-c-input-group > .pf-v5-c-input-group__item:first-child:not(:last-child) .pf-v5-c-form-control { - border-start-end-radius: 0; - border-end-end-radius: 0; +.pf-v5-c-login__main-header-utilities .pf-v5-c-form-control { + min-height: 40px; + border-radius: 20px; } -.pf-v5-c-input-group > .pf-v5-c-input-group__item:last-child:not(:first-child) .pf-v5-c-button { - border-radius: 0 999px 999px 0; +/* Password field and its show button form one field: the group has the border */ + +.pf-v5-c-input-group { + border: 1.5px solid var(--line); + border-radius: 14px; + background: var(--surface2); + overflow: hidden; } -/* Buttons: pill shaped like the game's */ +.pf-v5-c-input-group:hover { + border-color: var(--muted); +} + +.pf-v5-c-input-group:focus-within { + border-color: var(--accent); + box-shadow: 0 0 0 3px var(--accentSoft); +} + +.pf-v5-c-input-group .pf-v5-c-form-control, +.pf-v5-c-input-group .pf-v5-c-form-control:focus-within { + border: none; + border-radius: 0; + box-shadow: none; +} + +.pf-v5-c-input-group .pf-v5-c-button.pf-m-control { + --pf-v5-c-button--BorderRadius: 0; + --pf-v5-c-button--after--BorderRadius: 0; + border-radius: 0; +} + +.pf-v5-c-input-group .pf-v5-c-button.pf-m-control::after { + border: none; +} + +/* Buttons: the app's pills */ .pf-v5-c-button { - --pf-v5-c-button--BorderRadius: 999px; - --pf-v5-c-button--after--BorderRadius: 999px; + --pf-v5-c-button--BorderRadius: 23px; + --pf-v5-c-button--after--BorderRadius: 23px; + --pf-v5-c-button--FontWeight: 700; - --pf-v5-c-button--m-primary--BackgroundColor: var(--mancala-stone); - --pf-v5-c-button--m-primary--hover--BackgroundColor: var(--mancala-stone-hover); - --pf-v5-c-button--m-primary--focus--BackgroundColor: var(--mancala-stone-hover); - --pf-v5-c-button--m-primary--active--BackgroundColor: var(--mancala-stone-hover); - --pf-v5-c-button--m-primary--Color: var(--mancala-stone-text); - --pf-v5-c-button--m-primary--hover--Color: var(--mancala-stone-text); - --pf-v5-c-button--m-primary--focus--Color: var(--mancala-stone-text); - --pf-v5-c-button--m-primary--active--Color: var(--mancala-stone-text); + --pf-v5-c-button--m-primary--BackgroundColor: var(--accent); + --pf-v5-c-button--m-primary--hover--BackgroundColor: var(--accent); + --pf-v5-c-button--m-primary--focus--BackgroundColor: var(--accent); + --pf-v5-c-button--m-primary--active--BackgroundColor: var(--accent); + --pf-v5-c-button--m-primary--Color: var(--onAccent); + --pf-v5-c-button--m-primary--hover--Color: var(--onAccent); + --pf-v5-c-button--m-primary--focus--Color: var(--onAccent); + --pf-v5-c-button--m-primary--active--Color: var(--onAccent); - --pf-v5-c-button--m-secondary--Color: var(--mancala-ink); - --pf-v5-c-button--m-secondary--hover--Color: var(--mancala-ink); - --pf-v5-c-button--m-secondary--focus--Color: var(--mancala-ink); - --pf-v5-c-button--m-secondary--active--Color: var(--mancala-ink); - --pf-v5-c-button--m-secondary--after--BorderColor: var(--mancala-ink); - --pf-v5-c-button--m-secondary--hover--after--BorderColor: var(--mancala-ink); - --pf-v5-c-button--m-secondary--focus--after--BorderColor: var(--mancala-ink); - --pf-v5-c-button--m-secondary--active--after--BorderColor: var(--mancala-ink); - --pf-v5-c-button--m-secondary--hover--BackgroundColor: var(--mancala-hover); - --pf-v5-c-button--m-secondary--focus--BackgroundColor: var(--mancala-hover); - --pf-v5-c-button--m-secondary--active--BackgroundColor: var(--mancala-hover); + --pf-v5-c-button--m-secondary--BackgroundColor: transparent; + --pf-v5-c-button--m-secondary--Color: var(--ink); + --pf-v5-c-button--m-secondary--hover--Color: var(--ink); + --pf-v5-c-button--m-secondary--focus--Color: var(--ink); + --pf-v5-c-button--m-secondary--active--Color: var(--ink); + --pf-v5-c-button--m-secondary--after--BorderColor: var(--line); + --pf-v5-c-button--m-secondary--hover--after--BorderColor: var(--muted); + --pf-v5-c-button--m-secondary--focus--after--BorderColor: var(--muted); + --pf-v5-c-button--m-secondary--active--after--BorderColor: var(--muted); + --pf-v5-c-button--m-secondary--hover--BackgroundColor: transparent; + --pf-v5-c-button--m-secondary--focus--BackgroundColor: transparent; + --pf-v5-c-button--m-secondary--active--BackgroundColor: transparent; - --pf-v5-c-button--m-link--Color: var(--mancala-ink); - --pf-v5-c-button--m-link--hover--Color: var(--mancala-ink-strong); - --pf-v5-c-button--m-link--focus--Color: var(--mancala-ink-strong); - --pf-v5-c-button--m-link--active--Color: var(--mancala-ink-strong); + --pf-v5-c-button--m-link--Color: var(--ink); + --pf-v5-c-button--m-link--hover--Color: var(--accent); + --pf-v5-c-button--m-link--focus--Color: var(--accent); + --pf-v5-c-button--m-link--active--Color: var(--accent); - --pf-v5-c-button--m-control--BackgroundColor: var(--mancala-pit); - --pf-v5-c-button--m-control--hover--BackgroundColor: var(--mancala-pit); - --pf-v5-c-button--m-control--focus--BackgroundColor: var(--mancala-pit); - --pf-v5-c-button--m-control--active--BackgroundColor: var(--mancala-pit); - --pf-v5-c-button--m-control--Color: var(--mancala-ink); - --pf-v5-c-button--m-control--hover--Color: var(--mancala-ink-strong); - --pf-v5-c-button--m-control--focus--Color: var(--mancala-ink-strong); - --pf-v5-c-button--m-control--active--Color: var(--mancala-ink-strong); - font-family: var(--mancala-font); + --pf-v5-c-button--m-control--BackgroundColor: var(--surface2); + --pf-v5-c-button--m-control--hover--BackgroundColor: var(--surface2); + --pf-v5-c-button--m-control--focus--BackgroundColor: var(--surface2); + --pf-v5-c-button--m-control--active--BackgroundColor: var(--surface2); + --pf-v5-c-button--m-control--Color: var(--ink); + --pf-v5-c-button--m-control--hover--Color: var(--ink); + --pf-v5-c-button--m-control--focus--Color: var(--ink); + --pf-v5-c-button--m-control--active--Color: var(--ink); + --pf-v5-c-button--m-control--after--BorderColor: var(--line); + --pf-v5-c-button--m-control--hover--after--BorderColor: var(--muted); + font-family: var(--font); } .pf-v5-c-button.pf-m-primary { - font-weight: bold; + min-height: 46px; + font-size: 15px; } -.pf-v5-c-button.pf-m-control::after { - border: 1px solid var(--mancala-pit-edge); - border-radius: inherit; +.pf-v5-c-button.pf-m-primary:hover { + filter: brightness(1.06); } -.pf-v5-c-button.pf-m-control:hover::after { - border-color: var(--mancala-ink); +/* Secondary buttons are the app's ghost buttons: a thin line, a stronger one on hover */ +.pf-v5-c-button.pf-m-secondary::after { + border: 1.5px solid var(--line); +} + +.pf-v5-c-button.pf-m-secondary:hover::after { + border-color: var(--muted); } .pf-v5-c-button:focus-visible { - outline: 2px solid var(--mancala-ink); - outline-offset: 2px; + outline: 3px solid var(--accent); + outline-offset: 3px; } .pf-v5-c-check__input { - accent-color: var(--mancala-stone); + accent-color: var(--accent); +} + +/* Messages: info, success, warning and errors above the form */ + +.pf-v5-c-alert { + --pf-v5-c-alert--BackgroundColor: var(--surface2); + --pf-v5-c-alert--BoxShadow: none; + --pf-v5-c-alert--BorderTopWidth: 0; + --pf-v5-c-alert__title--Color: var(--ink); + --pf-v5-c-alert__icon--Color: var(--accent); + --pf-v5-c-alert--m-danger__icon--Color: var(--live); + --pf-v5-c-alert--m-danger__title--Color: var(--ink); + --pf-v5-c-alert--m-warning__title--Color: var(--ink); + --pf-v5-c-alert--m-success__title--Color: var(--ink); + --pf-v5-c-alert--m-info__title--Color: var(--ink); + border-radius: 14px; +} + +.pf-v5-c-alert.pf-m-danger { + box-shadow: inset 4px 0 0 var(--live); +} + +@media (max-width: 640px) { + :root:is(.t-ceviz, .t-gece, .t-yesim) { + --bar-height: 61px; + } + + #kc-header { + padding: 0 16px; + } + + #kc-header-wrapper::before { + width: 28px; + height: 28px; + } + + #kc-header-wrapper::after { + font-size: 20px; + } + + .pf-v5-c-login__main { + border-radius: 24px; + } } diff --git a/apps/keycloak/themes/mancala/login/resources/img/board-dark.svg b/apps/keycloak/themes/mancala/login/resources/img/board-dark.svg deleted file mode 100644 index c1edcbd..0000000 --- a/apps/keycloak/themes/mancala/login/resources/img/board-dark.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/keycloak/themes/mancala/login/resources/img/board-mask.svg b/apps/keycloak/themes/mancala/login/resources/img/board-mask.svg new file mode 100644 index 0000000..f2c7ee1 --- /dev/null +++ b/apps/keycloak/themes/mancala/login/resources/img/board-mask.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/keycloak/themes/mancala/login/resources/img/board.svg b/apps/keycloak/themes/mancala/login/resources/img/board.svg deleted file mode 100644 index 2fad955..0000000 --- a/apps/keycloak/themes/mancala/login/resources/img/board.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/keycloak/themes/mancala/login/resources/img/logo-mask.svg b/apps/keycloak/themes/mancala/login/resources/img/logo-mask.svg new file mode 100644 index 0000000..d704c49 --- /dev/null +++ b/apps/keycloak/themes/mancala/login/resources/img/logo-mask.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/apps/keycloak/themes/mancala/login/resources/img/logo.svg b/apps/keycloak/themes/mancala/login/resources/img/logo.svg deleted file mode 100644 index cf65dfd..0000000 --- a/apps/keycloak/themes/mancala/login/resources/img/logo.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - diff --git a/apps/keycloak/themes/mancala/login/resources/img/stones-mask.svg b/apps/keycloak/themes/mancala/login/resources/img/stones-mask.svg new file mode 100644 index 0000000..2ba2360 --- /dev/null +++ b/apps/keycloak/themes/mancala/login/resources/img/stones-mask.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/keycloak/themes/mancala/login/resources/js/theme.js b/apps/keycloak/themes/mancala/login/resources/js/theme.js new file mode 100644 index 0000000..813a140 --- /dev/null +++ b/apps/keycloak/themes/mancala/login/resources/js/theme.js @@ -0,0 +1,13 @@ +// Puts the web app's theme on the page: the one the player chose, which the web app keeps in the mancala_theme +// cookie, or else Ceviz for a dark system color scheme and Yeşim for a light one. Runs in , before the page +// is drawn. The dark themes also get PatternFly's dark mode. +(function () { + var DARK_THEMES = { ceviz: true, gece: true }; + var THEMES = { ceviz: true, gece: true, yesim: true }; + var match = document.cookie.match(/(?:^|;\s*)mancala_theme=([a-z]+)/); + var theme = match && THEMES[match[1]] ? match[1] + : window.matchMedia("(prefers-color-scheme: dark)").matches ? "ceviz" : "yesim"; + var classList = document.documentElement.classList; + classList.add("t-" + theme); + if (DARK_THEMES[theme]) classList.add("pf-v5-theme-dark"); +})(); diff --git a/apps/keycloak/themes/mancala/login/theme.properties b/apps/keycloak/themes/mancala/login/theme.properties index ec25cc5..8fe0280 100644 --- a/apps/keycloak/themes/mancala/login/theme.properties +++ b/apps/keycloak/themes/mancala/login/theme.properties @@ -1,6 +1,9 @@ -# Login pages in the look of the game. Keeps keycloak.v2's templates and only adds a stylesheet, -# so Keycloak upgrades do not need template changes. +# Login pages in the look of the web app, in its three themes (docs/specs/theme-polish). Keeps keycloak.v2's +# templates and only adds a stylesheet and a script, so Keycloak upgrades do not need template changes. parent=keycloak.v2 import=common/keycloak styles=css/styles.css css/mancala.css +# Picks the theme before the page is drawn; it also sets PatternFly's dark mode, so Keycloak's own is off. +scripts=js/theme.js +darkMode=false diff --git a/docs/specs/theme-polish/tasks.md b/docs/specs/theme-polish/tasks.md index 5ae6e72..c92a562 100644 --- a/docs/specs/theme-polish/tasks.md +++ b/docs/specs/theme-polish/tasks.md @@ -5,6 +5,6 @@ Work through the tasks in order; each ends with its checks passing and a commit. - [x] 1. **Spec**: requirements, design and tasks. - [x] 2. **Web app messages**: Notyf at the top centre in the theme's colors. - [x] 3. **Theme cookie**: the web app saves the chosen theme for the login pages. -- [ ] 4. **Login theme**: the script, the three themes' styles, logo and board masks; checked in Chrome in all three +- [x] 4. **Login theme**: the script, the three themes' styles, logo and board masks; checked in Chrome in all three themes, at desktop and phone width, with and without the cookie. - [ ] 5. **Docs**: `AGENTS.md` (specs list, the cookie), `apps/keycloak/README.md`, `TODO.md`.