-
Notifications
You must be signed in to change notification settings - Fork 22
Library Controllers for Developers
File lib/DirController.ts
Discovers and reports the host element's closest dir
,
even across shadow roots. Does not observe DOM changes.
see https://caniuse.com/css-dir-pseudo
File: elements/rh-secondary-nav/rh-secondary-nav.ts
Importing the controller
import { DirController } from '../../lib/DirController.js';
Adding the controller
#dir = new DirController(this);
Using the controller
const navClasses = { rtl: this.#dir.dir === 'rtl' };
...
return html`
<nav part="nav" class="${classMap(navClasses)}">
...
File lib/ScreenSizeController.ts
Used to determine the current size of the screen inside of a component.
Includes the following breakpoints:
- Mobile
- Mobile Portrait
- Mobile Landscape
- Tablet Portrait
- Tablet Landscape
- Desktop Small
- Desktop Large
These are determined by using the following matchMedia query
screen and (max-width: ${exampleBreakpoint})
where exampleBreakpoint
is replaced depending on the breakpoint being used (ex. mobile uses tabletPortraitBreakpoint
). These breakpoint values can be found in tokens.js
.
rh-secondary-nav-menu.ts
// Importing the controller
import { ScreenSizeController } from '../../lib/ScreenSizeController.js';
. . .
// Creating the private screenSize controller in the element
#screenSize = new ScreenSizeController(this);
. . .
// Creating a private state variable for the component to use for styling / logic.
@observed
@state() private _compact = false;
. . .
// This hooks into the ScreenSizeController to tell the component that when it matches tabletLandscape to change the compact variable.
protected screenSize = new ScreenSizeController(this, 'tabletLandscape', {
onChange: matches => {
this._compact = !matches;
}
});
File lib/color/Controller.ts
The Red Hat Design System color context API is an implementation of the context protocol based off of the recently upgraded @lit/context
and the web components community group proposal. The API consists of controllers and decorators that allow communication between components lower in the DOM hierarchy with their ancestors allowing us to pass context data without the need for prop drilling.
The decorators @colorContextProvider()
and @colorContextConsumer()
are added to many of our elements and define if they provide or consume context.
/**
* Sets color theme based on parent context
*/
@colorContextConsumer() private on?: ColorTheme;
/**
* Sets color palette, which affects the element's styles as well as descendants' color theme.
* Overrides parent color context.
* Your theme will influence these colors so check there first if you are seeing inconsistencies.
* See [CSS Custom Properties](#css-custom-properties) for default values
*
* Card always resets its context to `base`, unless explicitly provided with a `color-palette`.
*/
@colorContextProvider()
@property({ reflect: true, attribute: 'color-palette' }) colorPalette?: ColorPalette;
As a HTML first design system, the only thing a page author has to be aware of is setting the color-palette
on an element that is a @colorContextProvider()
, the API will handle the rest ensuring our components provide an accessible user experience as context providers define a color palette for themselves and their child elements.
<rh-card color-palette="darkest">
<h2>Card Title</h2>
<p>Card content</p>
<rh-cta>
<a href="/elements/call-to-action/">Read CTA docs</a>
</rh-cta>
</rh-card>
In the example above the rh-card
is setting a color-palette
of darkest
for itself and all of its children. The rh-cta
element is a context consumer and will inherit the darkest
color palette from its parent.
The color context API's design allows us to get close to the future state implementation of the style query proposal. We designed the API surface to have little to no impact on the end user HTML when the standard lands in all browsers. We will be able to simply remove the javascript layer and replace it with CSS container style queries inside the components shadow CSS providing a clear and simple upgrade path for our users.
Future state:
<rh-card color-palette="darkest">
<h2>Card Title</h2>
<p>Card content</p>
<rh-cta>
<a href="/elements/call-to-action/">Read CTA docs</a>
</rh-cta>
</rh-card>
/* rh-card.css */
:host([color-palette="darkest"]) {
--context: darkest;
}
/* rh-cta.css */
@container (--context: darkest) {
#container {
/* dark theme styles */
}
}
Examples how style queries work can be found in Google Chrome’s implementation docs.
CSS custom properties are great for piercing through shadow DOM encapsulation. However when you introduce nested elements in shadow roots which themselves have additional color context switching this solution unfortunately no longer works without reimporting the base styles in every component bloating the entire library.
<rh-some-element color-palette="darkest">
<div>I say hello</div>
<!-- element shadowroot renders here -->
</rh-some-element>
/* rh-some-element shadowroot renders */
render() {
return html`
<slot></slot>
<!-- nested element with its own provider -->
<rh-some-nested-element color-palette="lightest">Hello World</rh-some-nested-element>
`
}
Our goal is to provide performance and consistency within the design system and strive to avoid implementing solutions that may break in the future or cause large maintenance overhead when things ultimately do change either internally or externally.
Questions? Please contact [email protected]. Please review our Code of Conduct