Replies: 2 comments
-
A good example is the accordion component which:
There, not only the background color should change but the whole theme (for example, the text on a dark background is white, but the text in a gray accordion on a dark background is black). To implement this behavior I simply used CSS custom properties like so:
This approach work find for the styles package, but the variable declared in To me, there are then three solutions:
The first approach is not that nice for the development journey and leads to potential errors. @gfellerph Do you think of another approach? |
Beta Was this translation helpful? Give feedback.
-
In the long run, I think it will be beneficial to have customisable components through CSS variables. I'm assuming the accordion defines it's background-color something like this (as it would be after implementing the above solution). .accordion {
background-color: var(--post-accordion-background-color, var(--post-background-color, color.$grey));
} My first thought was that project devs should specify this in the form of <!-- Grey, because that's the default accordion background color -->
<post-accordion>...</post-accordion>
<div class="p-4 bg-light">
<!-- Dev needs to add bg-white on this background, according to design -->
<post-accordion class="bg-white">...</post-accordion>
</div> For Post projects, the theming file could then contain exceptions like this specifically for the accordion - or potentially for other components as necessary. theming/post.css .bg-light {
--post-accordion-background-color: color.$white;
--post-accordion-color: color.$black;
} The contextual definition is not made inside the component, but inside the theming file. The accordion just knows that somebody can define it's background colour and text colour and does not care who that is or if they define it correctly. In the theming file, we can make devs life easier and handle the special case of the white accordion. |
Beta Was this translation helpful? Give feedback.
-
A couple of issues came up that could potentially be solved by introducing design tokens, sub-atomic particles in the Atomic Design methodology.
Issues
Theming
Interest in custom theming for Post related projects with slightly different styling is starting to build. At the moment, theming possibilities are not documented and only partially implemented by overriding sass variables at build time:
The following scenarios could be handled by themes:
Dark mode
Similar to theming, a dark mode is not available for most patterns. While some patterns work on a dark background, documentation and support is lacking for most parts. As the mobile app is already implementing a dark mode, interest for a dark mode on the web is there as well.
An initial idea with utility classes for background colours has shown potential but could be improved further. The following snippet will render a white button with black text colour on a dark grey background. The light mode primary button would be dark grey with white text colour. The button is using CSS Custom Variables internally and
.bg-primary
is overriding the used variables.Composed web components
It's hard to style slotted components. This would be useful for some of the more re-useable components like
<post-button>
or<post-link>
.Inside
<post-menu>
, any defined parts of the<post-button>
cannot be accessed because the button belongs to the light-dom (https://stackoverflow.com/questions/65540853/how-to-style-slotted-parts-from-the-parent-downwards).Principles
There are some principles that help with finding the best way to solve the issues above.
Tooling
Layering
Many different tools and methods are available for working with design tokens. Research shows, a three layered approach, also promoted by Brad Frost (Creating and maintaining successful Design Systems, Smashing Course), seems to be the most popular one:
--post-yellow: #fc0;
--post-primary: var(--post-gray-80);
--post-button-background: var(--post-primary);
Implementations
There are different approaches to bring the token layers into a project. This list contains a few examples and could be expanded by more research.
Build time theming
This approach loads a theming layer at build time. The resulting CSS is static but only contains the necessary tokens for the current theme. Changing the theme at runtime would require some custom JS or a page refresh.
Theming via media query
This approach is specifically useful for light/dark themes, also for loading special print or tv styles. It's a great declarative way for theming and respects user preferences automatically. It would only load the necessary variables and can be changed at runtime by updating the operating system preferences. A theme switch on the page however, would be difficult to implement.
All in one
This approach is very flexible, as it allows to easily change theming at runtime and also combine different themes on the same page by scoping themes to certain elements. It needs to load all variables for all themes initially. Increasing number of tokens and themes could add up quickly and increase initial loading times.
Maybe the future?
Just a speculation, but maybe something like this will be available one day.
Possible solutions
What's necessary for such approaches to work in the Swiss Post Design System?
CSS custom properties
The first requirement would be strict component layer token implementation for components. This requirement is specifically not tied to the other layers or even integration with third party tools like Style Dictionary or Figma variables.
This example shows component styles for a tooltip web component. The component itself does not care how it actually looks. The only thing it cares about is that it displays and functions in a correct way and that semantics and accessibility (except for appearance related rules) are respected.
Available customisation options can easily be documented along with props, methods and events in storybook. Functionality of the component can be ensured by carefully selecting available options.
tooltip.component.css
Performance considerations: https://lisilinhart.info/posts/css-variables-performance
A theme file overrides the component defaults (or leaves them as is) and can be very flexible in the definition of variables.
theme.css
CSS Custom properties + utility classes
Taking it a step further, utility classes could be used to simplify customisation. An example would be the currently implemented background colour classes.
The background utility class defines accessible colour combinations that can be flexibly used throughout the document.
background-class.css
Component styles can expect these utility variables to be around and implement support
tooltip.component.css
index.html
Examples from other Design Systems
Adobe spectrum and salesforce lightning use a different namespace for theming.
color: var(--slds-c-button-text-color, var(--sds-c-button-text-color, #0176d3));
border-radius: var(--mod-avatar-border-radius, var(--spectrum-avatar-border-radius));
Examples of excessive token definitions
Carbon button height tokens
Styling slotted components
Using CSS Custom Properties allows for styling slotted components, something that is otherwise quite hard (without injecting styles through JavaScript).
In this example, the
<post-menu>
is able to set variables that can be used to style the buttons slotted inside, even if the buttons belong to the document and not the menu shadow dom (codepen example for styling slotted components).The menu has access to slotted components through the
::slotted
selector. That selector does not allow to style elements inside the<post-button>
component. If the button implements variables, it's possible to set variables from the menu.post-menu.component.css
Beta Was this translation helpful? Give feedback.
All reactions