Skip to content

Commit 24235b1

Browse files
committed
fix(docs): Load hTWOo CSS with :root transformed to :host for Shadow DOM
The component preview web component now fetches CSS dynamically and transforms :root selectors to :host, which is required for CSS custom properties (design tokens) to work inside Shadow DOM.
1 parent b640702 commit 24235b1

2 files changed

Lines changed: 90 additions & 20 deletions

File tree

docs/htwoo-components/assets/js/htwoo-component-preview.js

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class HtwooComponentPreview extends HTMLElement {
1313
constructor() {
1414
super();
1515
this.attachShadow({ mode: 'open' });
16+
this.stylesLoaded = false;
1617
}
1718

1819
static get observedAttributes() {
@@ -21,25 +22,23 @@ class HtwooComponentPreview extends HTMLElement {
2122

2223
connectedCallback() {
2324
this.render();
24-
const patternPath = this.getAttribute('pattern');
25-
if (patternPath) {
26-
this.loadComponent(patternPath);
27-
}
25+
this.loadStyles().then(() => {
26+
const patternPath = this.getAttribute('pattern');
27+
if (patternPath) {
28+
this.loadComponent(patternPath);
29+
}
30+
});
2831
}
2932

3033
attributeChangedCallback(name, oldValue, newValue) {
31-
if (name === 'pattern' && oldValue !== newValue && newValue) {
34+
if (name === 'pattern' && oldValue !== newValue && newValue && this.stylesLoaded) {
3235
this.loadComponent(newValue);
3336
}
3437
}
3538

3639
render() {
3740
this.shadowRoot.innerHTML = `
38-
<!-- Load hTWOo Core CSS inside shadow DOM for style isolation -->
39-
<link rel="stylesheet" href="/htwoo-core/css/style.css">
40-
<link rel="stylesheet" href="/htwoo-core/css/pattern-scaffolding.css">
41-
42-
<style>
41+
<style id="base-styles">
4342
:host {
4443
display: block;
4544
padding: 2rem;
@@ -96,6 +95,42 @@ class HtwooComponentPreview extends HTMLElement {
9695
`;
9796
}
9897

98+
async loadStyles() {
99+
try {
100+
// Fetch the main hTWOo CSS and transform :root to :host for Shadow DOM compatibility
101+
const [styleResponse, scaffoldResponse] = await Promise.all([
102+
fetch('/htwoo-core/css/style.css'),
103+
fetch('/htwoo-core/css/pattern-scaffolding.css')
104+
]);
105+
106+
if (styleResponse.ok) {
107+
let styleCSS = await styleResponse.text();
108+
// Transform :root to :host for Shadow DOM - CSS custom properties need this
109+
styleCSS = styleCSS.replace(/:root\s*\{/g, ':host {');
110+
111+
const styleEl = document.createElement('style');
112+
styleEl.id = 'htwoo-styles';
113+
styleEl.textContent = styleCSS;
114+
this.shadowRoot.insertBefore(styleEl, this.shadowRoot.getElementById('base-styles'));
115+
}
116+
117+
if (scaffoldResponse.ok) {
118+
let scaffoldCSS = await scaffoldResponse.text();
119+
scaffoldCSS = scaffoldCSS.replace(/:root\s*\{/g, ':host {');
120+
121+
const scaffoldEl = document.createElement('style');
122+
scaffoldEl.id = 'scaffold-styles';
123+
scaffoldEl.textContent = scaffoldCSS;
124+
this.shadowRoot.insertBefore(scaffoldEl, this.shadowRoot.getElementById('base-styles'));
125+
}
126+
127+
this.stylesLoaded = true;
128+
} catch (error) {
129+
console.error('Error loading hTWOo styles:', error);
130+
this.stylesLoaded = true; // Continue anyway
131+
}
132+
}
133+
99134
async loadComponent(patternPath) {
100135
this.setAttribute('loading', '');
101136
const contentEl = this.shadowRoot.getElementById('content');

htwoo-core/helpers/component-docs/js/htwoo-component-preview.js

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class HtwooComponentPreview extends HTMLElement {
1313
constructor() {
1414
super();
1515
this.attachShadow({ mode: 'open' });
16+
this.stylesLoaded = false;
1617
}
1718

1819
static get observedAttributes() {
@@ -21,25 +22,23 @@ class HtwooComponentPreview extends HTMLElement {
2122

2223
connectedCallback() {
2324
this.render();
24-
const patternPath = this.getAttribute('pattern');
25-
if (patternPath) {
26-
this.loadComponent(patternPath);
27-
}
25+
this.loadStyles().then(() => {
26+
const patternPath = this.getAttribute('pattern');
27+
if (patternPath) {
28+
this.loadComponent(patternPath);
29+
}
30+
});
2831
}
2932

3033
attributeChangedCallback(name, oldValue, newValue) {
31-
if (name === 'pattern' && oldValue !== newValue && newValue) {
34+
if (name === 'pattern' && oldValue !== newValue && newValue && this.stylesLoaded) {
3235
this.loadComponent(newValue);
3336
}
3437
}
3538

3639
render() {
3740
this.shadowRoot.innerHTML = `
38-
<!-- Load hTWOo Core CSS inside shadow DOM for style isolation -->
39-
<link rel="stylesheet" href="/htwoo-core/css/style.css">
40-
<link rel="stylesheet" href="/htwoo-core/css/pattern-scaffolding.css">
41-
42-
<style>
41+
<style id="base-styles">
4342
:host {
4443
display: block;
4544
padding: 2rem;
@@ -96,6 +95,42 @@ class HtwooComponentPreview extends HTMLElement {
9695
`;
9796
}
9897

98+
async loadStyles() {
99+
try {
100+
// Fetch the main hTWOo CSS and transform :root to :host for Shadow DOM compatibility
101+
const [styleResponse, scaffoldResponse] = await Promise.all([
102+
fetch('/htwoo-core/css/style.css'),
103+
fetch('/htwoo-core/css/pattern-scaffolding.css')
104+
]);
105+
106+
if (styleResponse.ok) {
107+
let styleCSS = await styleResponse.text();
108+
// Transform :root to :host for Shadow DOM - CSS custom properties need this
109+
styleCSS = styleCSS.replace(/:root\s*\{/g, ':host {');
110+
111+
const styleEl = document.createElement('style');
112+
styleEl.id = 'htwoo-styles';
113+
styleEl.textContent = styleCSS;
114+
this.shadowRoot.insertBefore(styleEl, this.shadowRoot.getElementById('base-styles'));
115+
}
116+
117+
if (scaffoldResponse.ok) {
118+
let scaffoldCSS = await scaffoldResponse.text();
119+
scaffoldCSS = scaffoldCSS.replace(/:root\s*\{/g, ':host {');
120+
121+
const scaffoldEl = document.createElement('style');
122+
scaffoldEl.id = 'scaffold-styles';
123+
scaffoldEl.textContent = scaffoldCSS;
124+
this.shadowRoot.insertBefore(scaffoldEl, this.shadowRoot.getElementById('base-styles'));
125+
}
126+
127+
this.stylesLoaded = true;
128+
} catch (error) {
129+
console.error('Error loading hTWOo styles:', error);
130+
this.stylesLoaded = true; // Continue anyway
131+
}
132+
}
133+
99134
async loadComponent(patternPath) {
100135
this.setAttribute('loading', '');
101136
const contentEl = this.shadowRoot.getElementById('content');

0 commit comments

Comments
 (0)