diff --git a/packages/calcite-components/src/demos/_assets/demo-theme.ts b/packages/calcite-components/src/demos/_assets/demo-theme.ts new file mode 100644 index 00000000000..8fec8edb784 --- /dev/null +++ b/packages/calcite-components/src/demos/_assets/demo-theme.ts @@ -0,0 +1,112 @@ +/* + * EXAMPLE USAGE: + * + * Button + * + */ + +const defaultTheme = { + background: "blue", + cornerRadius: "42px", + shadowColor: "black", + shadowValues: "0 1px 2px 0 1", + space: "24px", + textColor: "green", + zIndex: "9999", +}; + +export class DemoTheme extends HTMLElement { + _slot: HTMLSlotElement; + + _el: HTMLElement; + + _theme: Record = defaultTheme; + + static observedAttributes = ["tokens"]; + + constructor() { + super(); + const shadow = this.attachShadow({ mode: "open" }); + const slot = document.createElement("slot"); + shadow.append(slot); + this._slot = slot; + if (this._slot.assignedNodes().length === 1 && this._slot.assignedNodes()[0].nodeName.includes("calcite")) { + this._el = this._slot.assignedNodes()[0] as HTMLElement; + } + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string): void { + if (newValue !== oldValue && name === "tokens") { + this.updateTheme(newValue); + } + } + + updateTheme(newValue: string): void { + if (typeof newValue === "string") { + const textIconColorRegex = new RegExp(/(text|icon)-color/); + const backgroundBorderRegex = new RegExp(/(background|border)-color/); + const cornerRegex = new RegExp(/corner-radius/); + const zIndexRegex = new RegExp(/z-index/); + const spaceRegex = new RegExp(/space/); + const shadowRegex = new RegExp(/shadow(-color)*/); + + const theme = {}; + + let tokensList; + + try { + tokensList = JSON.parse(newValue); + } catch (error) { + tokensList = newValue.split(",").map((t) => t.trim()); + } + + if (Array.isArray(tokensList)) { + tokensList.forEach((token) => { + let value = ""; + if (textIconColorRegex.test(token)) { + value = this._theme.textColor; + } else if (backgroundBorderRegex.test(token)) { + value = this._theme.background; + } else if (shadowRegex.test(token)) { + value = token.includes("color") + ? `${this._theme.shadowColor}` + : `${this._theme.shadowValues} ${this._theme.shadowColor}`; + } else if (cornerRegex.test(token)) { + value = `${this._theme.cornerRadius}`; + } else if (zIndexRegex.test(token)) { + value = `${this._theme.zIndex}`; + } else if (spaceRegex.test(token)) { + value = `${this._theme.space}`; + } + theme[token] = value; + }); + } + + const stringifiedTheme = Object.entries(theme) + .map(([key, value]) => { + return `${key}: ${value};`; + }) + .join(" "); + + if (this._el) { + this._el.style.cssText = stringifiedTheme; + } else { + this.setAttribute("style", stringifiedTheme); + } + } + } +} + +customElements.define("demo-theme", DemoTheme); diff --git a/packages/calcite-components/src/demos/button.html b/packages/calcite-components/src/demos/button.html index 0e141ff1803..fcef34b7885 100644 --- a/packages/calcite-components/src/demos/button.html +++ b/packages/calcite-components/src/demos/button.html @@ -93,6 +93,7 @@ + @@ -2564,6 +2565,37 @@ + + +
+
+

THEMED Solid Inverse

+
+ + +
+

+ Button +

+
+