https://www.webcomponents.org/ https://www.polymer-project.org/
Best Practices: https://developers.google.com/web/fundamentals/web-components/
Styling within the Shadow Dom w/ CSS Properties: https://developers.google.com/web/fundamentals/web-components/shadowdom#stylefromoutside
State of Web Components: 2019 https://web.dev/web-components-io-2019
Link to Carbon WC repo (and relevant issue): https://github.com/carbon-design-system/carbon-custom-elements carbon-design-system/issue-tracking#121
Patrick's Slides on Lit-HTML/Lit-Elements https://docs.google.com/presentation/d/16m9BkgJuoX2ymLeNwuGQxO5d5yDe_2IJMFX7LQnYx-g/edit?usp=sharing
POC Repo: https://github.com/priley86/pf4-webcomponents-poc
Deployed Storybook: http://pf4-webcomponents-poc.surge.sh/?path=/story/button--default
Some notes/questions I've gathered so far:
- There are actually three Storybooks here which we can build and demo - a Polymer version (that uses our vanilla lit-html web components), a React version, and an Angular version. The link above is just the Polymer version. I highly recommend this approach because it is actually integration testing WCs developed alongside frameworks as you develop new WCs.
- Carbon uses a "createReactCustomElementType" utility to automatically build React shims. These can then be used in the React storybook and even exposed as wrappers to React consumers (although that may be a bit too automated if custom shims are needed): https://github.com/priley86/pf4-webcomponents-poc/blob/initial/src/globals/wrappers/createReactCustomElementType.ts
Discovered challenges so far within POC:
- Some CSS selectors which make uses of nested selection, i.e.:
.class1 > .class2
or.class1 > *
do not penetrate the Shadow DOM root of a custom element if defined outside the WC. We'll need to analyze this and see what cases need adjustment (there are over 247 uses of the> *
selector in patternfly.css today for example). Another such case is thepf-m-redhat-font
class which applies globally for applying fonts. To work around this, we can setfont-family
on the element or the:root
:
:root {
font-family: var(--pf-global--FontFamily--redhatfont--sans-serif);
}
- Lit-Elements does not provide a context mechanism for higher level/complex components to pass data down the DOM/component tree. This typically results in things like "for loops" in the top level component: https://github.com/carbon-design-system/carbon-custom-elements/blob/master/src/components/dropdown/dropdown.ts#L419
A better way may be to implement something like cascading attributes: https://github.com/patternfly/patternfly-elements/blob/master/elements/pfe-band/src/pfe-band.js#L123
OR self implement a Context pattern. Stencil JS has done exactly this w/ "State Tunneling": https://www.joshmorony.com/state-management-with-state-tunnel-in-stencil-js/
How-To-Components Demos https://developers.google.com/web/fundamentals/web-components/examples
Polyfill (and potential component bundler) polyfill.io
Disabling JS - should still render light DOM for other web crawlers, Chrome is the only engine that runs JS.
Light Dom - if semantically important, place it in the light DOM, then use a slot to progressively enhance content.
Light Dom styles will override host styles (:host
) - higher specificity.
Broadcast variables - used w/ themes for variation (dark/light). These are css properties with fallbacks. CSS properties don’t really have conditionals. patternfly/patternfly-elements#392
Current components (notes on a few):
pfe-content-set
- a component that changes content based on the window size
pfe-datetime
- uses the Intl object instead of Moment.js
pfe-icon
- icon works with any font awesome or red hat font, svg
PF Elements blog: https://medium.com/patternfly-elements
Problems w/ Angular:
https://medium.com/patternfly-elements/using-patternfly-elements-web-components-in-your-angular-app-4b18b1c9c363
MutationObserver - an alternative to slotChanged
with more granularity on content changed.
Lit-Element (and Templates) as a potential option to replacing rendering. Per Google, reusing template blocks is the most performant.
document.createElement(‘template’);
Service Workers - not currently exploring these (would need more infrastructure).
SSR (for React testing w/ JSDOM) - it's possible as long as you polyfill window and mutation observer