Skip to content

Let a custom project's theme add stylesheets - #40

Merged
Ekhorn merged 4 commits into
mainfrom
28-migrate-kc-themes-to-vaadin-part-5
Oct 30, 2026
Merged

Ekhorn merged 4 commits into
mainfrom
28-migrate-kc-themes-to-vaadin-part-5

Conversation

@Ekhorn

@Ekhorn Ekhorn commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Description

A child theme with parent=openremote can override a page's .ftl and ship its own resources, but its CSS never loads: styles= in theme.properties becomes a <link> only in a FreeMarker theme, and these pages are a compiled bundle. The one thing a custom project is most likely to want, is their own stylesheet. These changes allow a custom stylesheet to be applied on top of ours.

Changelog

  • An inline script in the generated template reads orStyles from the theme properties Keycloak already sends and writes a <link> per entry into the head, after the bundle's own so the child wins. Paths resolve against the theme's resources, as Keycloak's styles= do, and an absolute URL is passed through.
  • In the head rather than appended from the bundle, so the browser holds the first paint for them exactly as it does for Keycloak's own styles=. Appended, they arrived after the page had been built and painted in this theme's styling, and it visibly flipped; in WebKit the components were built before the child's rules existed at all. index.html therefore places the bundle's own tags itself, with inject: false.
  • orStyles rather than Keycloak's own styles, which is inherited from the fallback theme and is what the pages this theme does not implement are rendered with: reading it would put the fallback theme's stylesheet on these pages, and declaring our own would take it away from theirs.
  • The dev server applies a child theme's orStyles when OR_CHILD_THEME points at its login directory, and keeps the page hidden until they have loaded, as a real page does. yarn start:example runs it with a small example theme in theme/ui/dev-server/example-theme.

Effect on custom projects

A theme mounted under /deployment/keycloak/themes with parent=openremote and orStyles=css/custom.css now has that file loaded on every page this theme implements. With --spi-theme-cache-themes=false --spi-theme-static-max-age=-1 on the container, editing it is a browser refresh.

It can also be worked on without a container: OR_CHILD_THEME=/path/to/custom/project/deployment/keycloak/themes/acme/login yarn start in theme/ui serves it to the dev server, which reloads the page when the stylesheet changes.

That stylesheet is on the critical path, as Keycloak's styles= has always been: a slow one is a slow login page. Two things it cannot hold back, both in the README: a web font with font-display: swap, which is what Google Fonts' URLs ask for, and an entrance animation or transition that runs while the page is hidden for the realm's branding, which wants scoping under html:not(.or-booting).

A realm that sets styles in manager_config.json still wins the brand colour: those are injected after everything else, and the demo configuration carries --or-app-color4 by default. A child theme changes the rest, and the brand colour belongs to the realm.

@Ekhorn
Ekhorn added this pull request to stack #41 October 2, 2026 13:24
@Ekhorn
Ekhorn force-pushed the 28-migrate-kc-themes-to-vaadin-part-5 branch from 0f0d6d7 to b4d92c5 Compare October 2, 2026 14:01
@Ekhorn Ekhorn self-assigned this Oct 2, 2026
@Ekhorn
Ekhorn force-pushed the 28-migrate-kc-themes-to-vaadin-part-5 branch from b4d92c5 to 627c297 Compare October 9, 2026 16:12
@Ekhorn Ekhorn linked an issue Oct 13, 2026 that may be closed by this pull request
13 tasks

@wborn wborn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an initial AI-assisted review.

The addition of orStyles provides a straightforward mechanism for custom projects to extend the compiled OpenRemote Keycloak theme without rebuilding it.

The implementation is small and follows the intended behavior:

  • Stylesheets are read from the theme's properties.
  • Relative paths resolve against Keycloak's theme resources directory.
  • Absolute HTTP(S) URLs are preserved.
  • Stylesheets are appended after the bundle's own styles.
  • Existing Keycloak styles properties remain separate, preserving fallback theme behavior.

The README documents the configuration and explains why orStyles is needed instead of the standard styles property.

No additional code issues were identified in the three changed files.

A real child-theme deployment should still be tested to confirm that Keycloak supplies the expected resources URL and inherited properties, and that the custom stylesheet is actually loaded on an implemented page.

AI found no further issues in the reviewed change. Manual maintainer review is still needed before merge. This PR also remains marked as a draft.

@Ekhorn
Ekhorn force-pushed the 28-migrate-kc-themes-to-vaadin-part-5 branch from 627c297 to 3c6b9d7 Compare October 13, 2026 17:44
@Ekhorn
Ekhorn force-pushed the 28-migrate-kc-themes-to-vaadin-part-5 branch from 3c6b9d7 to cf5a13d Compare October 14, 2026 10:27
@Ekhorn
Ekhorn marked this pull request as ready for review October 14, 2026 11:13
@Ekhorn
Ekhorn requested a review from a team October 14, 2026 15:23
@richturner
richturner force-pushed the 28-migrate-kc-themes-to-vaadin-part-5 branch from cf5a13d to 7bdefb8 Compare October 15, 2026 08:54

@richturner richturner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a useful change, would it be much effort to include a mock example theme just for dev testing purposes?

@richturner richturner self-assigned this Oct 19, 2026
@Ekhorn
Ekhorn requested a review from richturner October 28, 2026 09:02
richturner
richturner previously approved these changes Oct 28, 2026
@Ekhorn
Ekhorn force-pushed the 28-migrate-kc-themes-to-vaadin-part-5 branch from 94522fb to dc20e37 Compare October 28, 2026 11:24
@Ekhorn
Ekhorn requested a review from richturner October 28, 2026 11:25
@Ekhorn
Ekhorn force-pushed the 28-migrate-kc-themes-to-vaadin-part-5 branch from 1a373bc to 40238d4 Compare October 28, 2026 13:42
Base automatically changed from 28-migrate-kc-themes-to-vaadin-part-4 to main October 28, 2026 15:32
A child theme with parent=openremote can override a page's .ftl and ship its own
resources, but its CSS never loads: `styles=` in theme.properties becomes a <link>
only in a FreeMarker theme, and these pages are a compiled bundle.

The pages now read `orStyles` from the theme properties Keycloak already sends and
append a <link> each, after the bundle's own so the child wins where specificity
ties. Not Keycloak's own `styles=`, which is inherited from the fallback theme and
renders the pages this theme does not implement.
@wborn
wborn force-pushed the 28-migrate-kc-themes-to-vaadin-part-5 branch from 40238d4 to 0cbfd88 Compare October 28, 2026 15:32
@Ekhorn
Ekhorn merged commit 93044d2 into main Oct 30, 2026
5 checks passed
@Ekhorn
Ekhorn deleted the 28-migrate-kc-themes-to-vaadin-part-5 branch October 30, 2026 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate Keycloak OpenRemote templates to Vaadin

3 participants