On the misson of ZUi to become micro-frontend (mFE) - ready we have found, that the old approach of global, runtime-based theming does not work in more advanced use case and for ZUi web components themselves. Thus with build time theming we also changed the internal code infrastructure for themes, to make maintenance easier and development less error-prone for ZUi.
if you are using zui version 2.x.x and want to update of the latest 3.x.x have a look at the Migrationguide.
Using themes directly from @zeiss/zui
Starting with @zeiss/zui@2.11.0-beta.7
all of the current theming utility functions are now accessible directly from @zeiss/zui
itself, so you do not need to add @zeiss/zui-themes
anymore to your project.:
before:
import {
themeZbdsBase,
themeZbdsLight,
themeZbdsDark,
themeZbdsTranslucent,
registerTheme,
setAppTheme
} from '@zeiss/zui-themes';
registerTheme(themeZbdsBase);
registerTheme(themeZbdsLight);
registerTheme(themeZbdsDark);
registerTheme(themeZbdsTranslucent);
setAppTheme('zbds-light');
This will simply change to after:
import {
themeZbdsBase,
themeZbdsLight,
themeZbdsDark,
registerTheme,
setAppTheme
// now use it directly from zui!
} from '@zeiss/zui';
registerTheme(themeZbdsBase);
registerTheme(themeZbdsLight);
registerTheme(themeZbdsDark);
setAppTheme('zbds-light');
N.B.: Don't you worry,
@zeiss/zui-themes
still continues to work, because it is now just a re-export from@zeiss/zui
; but it will be deprecated soon. Notice: with v3.2@zeiss/zui-themes
is deprecated.
Build Time Theming
Another design decision that we made to become mFE-ready is, that now all components are actually self-contained and bring their own themes when build time theming is used. This allows for multiple versions of the same theme (think: 'light'
vs. 'zbds-light'
) to be used on a web site, when final mFE support is shipped.
When build time theming is enabled, the existing imperative theming API will become obsolete, meaning you do not have to make any calls to registerTheme()
etc. anymore.
N.B.: Don't you worry, if you enable build time theming, you can still use the imperative API, but it won't do any harm, because it then simply does nothing.
Diabling build time theming
Because build time theming is such a big conceptual change, you have the option to disable this. We won't be supporting runtime themes in the future and there will be a point - after a certain grace period, where you will have to opt-out of it.
Diabling build time theming can be done in two different ways:
Opt-in into build time theming using a query parameter
You simply have to pass zui-feature-disable-build-themes
as a query parameter (with no value). This is especially useful, if you want to compare your applications side-by-side, simply use the latest beta version of zui
and open your local dev server twice and add to the second instance feature-disable-build-themes
as a proper query parameter.
Have a look at:
- Storybook of integration, with runtime theming vs.
- Storybook of integration, with build time theming
This is the way to go, to test whether things break in your application, without having to touch your code.
(permanently) Opt-out into build time theming using session storage
You can permanently opt-out into build time theming by setting a feature flag on sessionStorage
:
window.sessionStorage.setItem(
'zui.features',
JSON.stringify({
'feature-disable-build-themes': true
})
);
N.B.: You have to make sure, that this is set before any component, that should use build time theming is added to the document, i.e. either in a
<script>
within<head>
or in case of Angular in itspolyfills.ts
.
Switching themes
The old API for switching themes, was simply adding a theme
attribute to any DOM element. Now there is an explicit provider component for this, the zui-theme-provider
, changing its theme
attribute will change the themes of all descending ZUi components, regardless whether they are in nested ShadowDOM or not.
before:
<!-- [...] leaving out imperative setup for brevity -->
<div theme="light">
<zui-button>I am a light-hearted button!</zui-button>
</div>
after:
<zui-theme-provider theme="light">
<zui-button>I am a light-hearted button!</zui-button>
</zui-theme-provider>
N.B.: You can nest
zui-theme-provider
and you can still explicitly set themes on components. Explicitly set themes always win over thezui-theme-provider
.
N.B.: If a component does not find a parent
zui-theme-provider
in the DOM, its theme will default tolight
.
Build Time Theming benefits
Declarative usage
Apart from being the basis for mFE-readiness, using build time theming, allows you to use ZUi completely declaratively, if you supply the various NotoSans fonts at public/fonts
. @zeiss/zui
conveniently ships with NotoSans in public
for all your vendor-copy needs. If you need to supply them from another location, you can use the old imperative API registerTypefaces()
with an URL.
Mix+Match
You can use any combination of themes; this was not possible before and you can also now securely use ZUi components in nested ShadowDOM.
Build Time Theming limitations
Visual differences
While we spent a lot of time, making sure, that we won't break the existing APIs, we figured out, that when you enable build time theming we accidentally fixed ™ bugs, i.e. there might be some minor visual differences, but they should actually be now conforming to the design guide.
Overwriting themes is not supported anymore
Now, that components are self-contained, it becomes hard to overwrite the themes or supply your own theme. While in theory this was possible with runtime theming, no one ever used it and it never worked to that extent, that it would justify retaining that API.
Rule of one
You cannot mix+match runtime theming with build time theming. While you can turn the old imperative runtime theming into build time theming, by opting in, this does not work vice versa. This also does not allow to use the 'theme'
attribute on arbitrary DOM elements.
One Font to rule them all
All themes are sharing the same set of global font rules, thus fonts are consequently still added to the global scope. This is not very likely to change in the future.
Migration Guide
Migrating your code base to build time theming is very easy:
- Use latest beta version of
@zeiss/zui
(e.g.npm i --save @zeiss/zui@beta
) - Verify that everything works™ , by simply opting into build time theming using the query parameter.
- Replace the points in your application (templates), that switches the theme from a wrapper element with
'theme'
attribute (e.g.<div id="theme-wrapper" theme="dark">
to<zui-theme-provider id="theme-wrapper" theme="dark">
- Replace imperative API
setAppTheme()
with code / template magic, that simply modifies the'theme'
attribute of abovezui-theme-provider
- Remove imperative theme API calls
registerTheme()
- Replace any left imports from
@zeiss/zui-themes
with@zeiss/zui
- Remove dependency to
@zeiss/zui-themes
altogether