Add Keycloak login theme source files #174

Merged
ldraney merged 2 commits from keycloak-landscaping-theme into main 2026-06-08 04:13:10 +00:00
Owner

Summary

  • Add keycloak-theme/landscaping/login/ with theme.properties and login.css
  • CSS mirrors application.css design tokens (colors, fonts, spacing, radius, plant icon)
  • Source lives alongside the app for co-evolution; deployed to Keycloak via pal-e-platform ConfigMap

Changes

  • keycloak-theme/landscaping/login/theme.properties -- extends base keycloak theme
  • keycloak-theme/landscaping/login/resources/css/login.css -- CSS overrides matching app design system

Test Plan

  • Theme verified live on Keycloak login page
  • Plant icon, blue accent button, form fields match the app's design
  • Hides default Keycloak branding and "Sign in to your account" header
  • Screenshot verified via Playwright

Review Checklist

  • Passed automated review-fix loop
  • No secrets committed
  • No unnecessary file changes
  • Commit messages are descriptive
  • Feature flag needed? No -- static CSS files, no runtime code

Closes #173

  • landscaping-assistant -- project this affects
  • Cross-repo: ldraney/pal-e-platform #415 (ConfigMap), ldraney/pal-e-services #109 (realm config)
## Summary - Add `keycloak-theme/landscaping/login/` with theme.properties and login.css - CSS mirrors application.css design tokens (colors, fonts, spacing, radius, plant icon) - Source lives alongside the app for co-evolution; deployed to Keycloak via pal-e-platform ConfigMap ## Changes - `keycloak-theme/landscaping/login/theme.properties` -- extends base keycloak theme - `keycloak-theme/landscaping/login/resources/css/login.css` -- CSS overrides matching app design system ## Test Plan - [x] Theme verified live on Keycloak login page - [x] Plant icon, blue accent button, form fields match the app's design - [x] Hides default Keycloak branding and "Sign in to your account" header - [x] Screenshot verified via Playwright ## Review Checklist - [ ] Passed automated review-fix loop - [x] No secrets committed - [x] No unnecessary file changes - [x] Commit messages are descriptive - [x] Feature flag needed? No -- static CSS files, no runtime code ## Related Notes Closes #173 - `landscaping-assistant` -- project this affects - Cross-repo: `ldraney/pal-e-platform #415` (ConfigMap), `ldraney/pal-e-services #109` (realm config)
Add Keycloak login theme source files
Some checks are pending
ci/woodpecker/push/woodpecker Pipeline was successful
CI / scan_ruby (pull_request) Waiting to run
CI / scan_js (pull_request) Waiting to run
CI / lint (pull_request) Waiting to run
ci/woodpecker/pr/woodpecker Pipeline was successful
155af509ca
Theme CSS mirrors application.css design tokens (colors, fonts, spacing).
Deployed to Keycloak via pal-e-platform ConfigMap; source lives here
alongside the app for co-evolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

PR #174 Review

DOMAIN REVIEW

Tech stack: Static CSS (Keycloak login theme overriding PatternFly). Two files: theme.properties and login.css. No runtime code, no server logic.

Design token parity with application.css:

Every :root token in login.css was compared against app/assets/stylesheets/application.css. All 17 shared tokens match exactly:

Token application.css login.css Match
--color-bg #fafafa #fafafa Yes
--color-surface #ffffff #ffffff Yes
--color-text #1a1a1a #1a1a1a Yes
--color-muted #57606a #57606a Yes
--color-border #d0d7de #d0d7de Yes
--color-accent #2563eb #2563eb Yes
--color-accent-hover #1d4ed8 #1d4ed8 Yes
--color-accent-light #ddf4ff #ddf4ff Yes
--color-success #16a34a #16a34a Yes
--color-success-light #f0fdf4 #f0fdf4 Yes
--color-danger #d1242f #d1242f Yes
--color-danger-light #fef2f2 #fef2f2 Yes
--font-body system-ui, -apple-system, sans-serif same Yes
--max-width 30rem 30rem Yes
--radius 8px 8px Yes
--spacing-* (all 5) identical identical Yes

Two application.css tokens intentionally omitted from login.css (correct -- neither is used on login pages):

  • --color-success-hover: #15803d
  • --color-info-light: #f0f9ff

Hardcoded hex outside :root -- audit passed:

  • rgba(0, 0, 0, 0.06) / rgba(0, 0, 0, 0.1) in box-shadow: standard CSS shadow pattern, not a design token. Same pattern used throughout application.css.
  • rgba(37, 99, 235, 0.25) / rgba(37, 99, 235, 0.35) in button box-shadow: these are the accent color (#2563eb = rgb(37, 99, 235)) at alpha, exactly matching the .login-btn / .login-btn:hover shadows in application.css (lines 1713-1718). CSS variables cannot be used inside rgba() without color-mix() which has narrower support. Acceptable.
  • stroke='%232563eb' in SVG data URI: URL-encoded #2563eb. CSS custom properties cannot resolve inside data URIs. This is the only viable pattern. Acceptable.
  • color: white on submit button text: matches application.css line 89 (.btn-accent { color: white; }). Acceptable.

No rogue hardcoded colors found.

SVG data URI security review:
The SVG is a simple plant icon with four <path> elements, no <script>, no <foreignObject>, no event handlers, no external references. It uses only stroke, fill='none', stroke-width, stroke-linecap, stroke-linejoin. This is safe.

!important usage:
Every !important targets a Keycloak/PatternFly selector that would otherwise win specificity (PatternFly uses high-specificity selectors and its own !important declarations). This is the standard pattern for Keycloak theme overrides. The usage is disciplined -- !important appears only on declarations that override PatternFly defaults, not on internal relationships between theme rules.

theme.properties:

  • parent=keycloak -- correctly extends the base theme
  • import=common/keycloak -- imports shared Keycloak resources
  • styles=css/login.css -- path matches the file location

Component parity with app login page:
The CSS mirrors the app's login component structure: centered card, 5rem plant icon, 1.75rem/700 title, same form field styling (0.9rem/700 labels, 1px border, 8px radius, 3px accent focus ring), same submit button (1.2rem/700, accent background, matching box-shadows), same alert color scheme (danger-light/success-light/accent-light backgrounds).

Mobile responsive:
The @media (max-width: 480px) breakpoint removes card border and shadow, reduces padding -- appropriate for the login form on small screens.

BLOCKERS

None.

This is a static CSS file with no runtime code, no user input processing, no secrets, and no server-side logic. The BLOCKER criteria (test coverage, input validation, secrets, auth duplication) do not apply to static theme assets. The CSS is purely presentational.

NITS

  1. DRY opportunity (non-blocking): The :root token block is duplicated between application.css and login.css. If these ever drift, the login page will look different from the app. Consider a comment in both files referencing the other as the source of truth, or a future build step to extract shared tokens. The current approach (copy with a header comment noting the mirror) is pragmatic for now since Keycloak themes cannot import Rails asset pipeline CSS.

  2. #kc-page-title styled twice (non-blocking): #kc-page-title is hidden via display: none !important on line 54, then styled with font properties on lines 133-142. The styling block is dead code since the element is hidden. This is harmless but could confuse a future maintainer -- a comment noting the title section styles .kc-page-title (class) for themes that show it would clarify intent.

SOP COMPLIANCE

  • Branch named after issue: keycloak-landscaping-theme -- does not follow {issue-number}-{kebab-case} convention (should be 173-keycloak-landscaping-theme). Non-blocking for static CSS assets.
  • PR body follows template: Summary, Changes, Test Plan, Review Checklist, Related -- all present
  • Related references cross-repo context (pal-e-platform #415, pal-e-services #109)
  • Closes #173 referenced
  • No secrets committed
  • No unnecessary file changes (2 files, both theme-related)
  • Commit messages descriptive

PROCESS OBSERVATIONS

  • Change failure risk: Low. Static CSS with no runtime behavior. Worst case is a visual regression on the Keycloak login page, which was already verified via Playwright screenshot per the test plan.
  • Deployment dependency: This PR alone does not deploy the theme. It requires the pal-e-platform ConfigMap (referenced as #415) to mount the files into Keycloak. The PR correctly documents this cross-repo dependency.
  • Token drift risk: The duplicated :root block creates a maintenance surface. When application.css tokens change, login.css must be updated manually. This is an accepted trade-off documented in the header comment.

VERDICT: APPROVED

## PR #174 Review ### DOMAIN REVIEW **Tech stack:** Static CSS (Keycloak login theme overriding PatternFly). Two files: `theme.properties` and `login.css`. No runtime code, no server logic. **Design token parity with application.css:** Every `:root` token in `login.css` was compared against `app/assets/stylesheets/application.css`. All 17 shared tokens match exactly: | Token | application.css | login.css | Match | |-------|----------------|-----------|-------| | `--color-bg` | `#fafafa` | `#fafafa` | Yes | | `--color-surface` | `#ffffff` | `#ffffff` | Yes | | `--color-text` | `#1a1a1a` | `#1a1a1a` | Yes | | `--color-muted` | `#57606a` | `#57606a` | Yes | | `--color-border` | `#d0d7de` | `#d0d7de` | Yes | | `--color-accent` | `#2563eb` | `#2563eb` | Yes | | `--color-accent-hover` | `#1d4ed8` | `#1d4ed8` | Yes | | `--color-accent-light` | `#ddf4ff` | `#ddf4ff` | Yes | | `--color-success` | `#16a34a` | `#16a34a` | Yes | | `--color-success-light` | `#f0fdf4` | `#f0fdf4` | Yes | | `--color-danger` | `#d1242f` | `#d1242f` | Yes | | `--color-danger-light` | `#fef2f2` | `#fef2f2` | Yes | | `--font-body` | `system-ui, -apple-system, sans-serif` | same | Yes | | `--max-width` | `30rem` | `30rem` | Yes | | `--radius` | `8px` | `8px` | Yes | | `--spacing-*` (all 5) | identical | identical | Yes | Two application.css tokens intentionally omitted from login.css (correct -- neither is used on login pages): - `--color-success-hover: #15803d` - `--color-info-light: #f0f9ff` **Hardcoded hex outside :root -- audit passed:** - `rgba(0, 0, 0, 0.06)` / `rgba(0, 0, 0, 0.1)` in box-shadow: standard CSS shadow pattern, not a design token. Same pattern used throughout application.css. - `rgba(37, 99, 235, 0.25)` / `rgba(37, 99, 235, 0.35)` in button box-shadow: these are the accent color (`#2563eb` = `rgb(37, 99, 235)`) at alpha, exactly matching the `.login-btn` / `.login-btn:hover` shadows in application.css (lines 1713-1718). CSS variables cannot be used inside `rgba()` without `color-mix()` which has narrower support. Acceptable. - `stroke='%232563eb'` in SVG data URI: URL-encoded `#2563eb`. CSS custom properties cannot resolve inside data URIs. This is the only viable pattern. Acceptable. - `color: white` on submit button text: matches `application.css` line 89 (`.btn-accent { color: white; }`). Acceptable. No rogue hardcoded colors found. **SVG data URI security review:** The SVG is a simple plant icon with four `<path>` elements, no `<script>`, no `<foreignObject>`, no event handlers, no external references. It uses only `stroke`, `fill='none'`, `stroke-width`, `stroke-linecap`, `stroke-linejoin`. This is safe. **!important usage:** Every `!important` targets a Keycloak/PatternFly selector that would otherwise win specificity (PatternFly uses high-specificity selectors and its own `!important` declarations). This is the standard pattern for Keycloak theme overrides. The usage is disciplined -- `!important` appears only on declarations that override PatternFly defaults, not on internal relationships between theme rules. **theme.properties:** - `parent=keycloak` -- correctly extends the base theme - `import=common/keycloak` -- imports shared Keycloak resources - `styles=css/login.css` -- path matches the file location **Component parity with app login page:** The CSS mirrors the app's login component structure: centered card, 5rem plant icon, 1.75rem/700 title, same form field styling (0.9rem/700 labels, 1px border, 8px radius, 3px accent focus ring), same submit button (1.2rem/700, accent background, matching box-shadows), same alert color scheme (danger-light/success-light/accent-light backgrounds). **Mobile responsive:** The `@media (max-width: 480px)` breakpoint removes card border and shadow, reduces padding -- appropriate for the login form on small screens. ### BLOCKERS None. This is a static CSS file with no runtime code, no user input processing, no secrets, and no server-side logic. The BLOCKER criteria (test coverage, input validation, secrets, auth duplication) do not apply to static theme assets. The CSS is purely presentational. ### NITS 1. **DRY opportunity (non-blocking):** The `:root` token block is duplicated between `application.css` and `login.css`. If these ever drift, the login page will look different from the app. Consider a comment in both files referencing the other as the source of truth, or a future build step to extract shared tokens. The current approach (copy with a header comment noting the mirror) is pragmatic for now since Keycloak themes cannot import Rails asset pipeline CSS. 2. **`#kc-page-title` styled twice (non-blocking):** `#kc-page-title` is hidden via `display: none !important` on line 54, then styled with font properties on lines 133-142. The styling block is dead code since the element is hidden. This is harmless but could confuse a future maintainer -- a comment noting the title section styles `.kc-page-title` (class) for themes that show it would clarify intent. ### SOP COMPLIANCE - [x] Branch named after issue: `keycloak-landscaping-theme` -- does not follow `{issue-number}-{kebab-case}` convention (should be `173-keycloak-landscaping-theme`). Non-blocking for static CSS assets. - [x] PR body follows template: Summary, Changes, Test Plan, Review Checklist, Related -- all present - [x] Related references cross-repo context (`pal-e-platform #415`, `pal-e-services #109`) - [x] Closes #173 referenced - [x] No secrets committed - [x] No unnecessary file changes (2 files, both theme-related) - [x] Commit messages descriptive ### PROCESS OBSERVATIONS - **Change failure risk:** Low. Static CSS with no runtime behavior. Worst case is a visual regression on the Keycloak login page, which was already verified via Playwright screenshot per the test plan. - **Deployment dependency:** This PR alone does not deploy the theme. It requires the pal-e-platform ConfigMap (referenced as `#415`) to mount the files into Keycloak. The PR correctly documents this cross-repo dependency. - **Token drift risk:** The duplicated `:root` block creates a maintenance surface. When application.css tokens change, login.css must be updated manually. This is an accepted trade-off documented in the header comment. ### VERDICT: APPROVED
Remove dead styling on hidden #kc-page-title
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
CI / scan_ruby (pull_request) Has been cancelled
CI / scan_js (pull_request) Has been cancelled
CI / lint (pull_request) Has been cancelled
c8a80e259c
The element is display:none — styling it is unreachable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ldraney deleted branch keycloak-landscaping-theme 2026-06-08 04:13:10 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/landscaping-assistant!174
No description provided.