Web Components Skill
This skill covers the two JavaScript components that render icons.
ss-icon Web Component
Location: src/ss-icon.js
Usage
<ss-icon icon="check"></ss-icon>
<ss-icon icon="arrow-left" thickness="1.5"></ss-icon>
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
icon |
string | - | Icon slug from icons.json |
thickness |
number | 2 | Stroke width of the icon |
How It Works
class SSIcon extends HTMLElement {
// Watch for attribute changes
static get observedAttributes() {
return ["icon", "thickness"];
}
constructor() {
super();
this.attachShadow({ mode: "open" });
}
// Re-render when attributes change
attributeChangedCallback(name, oldValue, newValue) {
if (name === "icon" || name === "thickness") {
this.render();
}
}
render() {
const iconName = this.getAttribute("icon");
const iconSvg = icons[iconName];
// Inject SVG with custom thickness into shadow DOM
}
}
customElements.define("ss-icon", SSIcon);
Styling
The component inherits color from parent:
.my-button {
color: blue;
}
.my-button ss-icon {
/* Icon will be blue */
}
Override size:
ss-icon {
font-size: 24px; /* Icons scale with font-size */
}
ss-loader (Class-based Icons)
Location: src/ss-loader.js
Usage
<i class="ss ss-check"></i>
<i class="ss ss-arrow-left"></i>
How It Works
- Initial Load: On DOMContentLoaded, finds all
i.sselements - Extract Icon: Looks for class starting with
ss- - Inject SVG: Inserts SVG content into the element
- Mark Loaded: Adds
data-ss-loaded="true"to prevent reprocessing - Observe Changes: MutationObserver watches for new icons added dynamically
function replaceIcons() {
const elements = document.querySelectorAll("i.ss");
elements.forEach((el) => {
if (el.dataset.ssLoaded) return; // Skip already processed
const iconClass = classes.find(c => c.startsWith("ss-"));
const iconName = iconClass.replace("ss-", "");
const iconSvg = icons[iconName];
if (iconSvg) {
el.innerHTML = iconSvg;
el.dataset.ssLoaded = "true";
}
});
}
// Watch for dynamically added icons
const observer = new MutationObserver((mutations) => {
// Check for added nodes or class changes
if (shouldUpdate) replaceIcons();
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ["class"]
});
Styling Class-based Icons
.ss {
display: inline-block;
width: 1em;
height: 1em;
vertical-align: middle;
}
/* Custom styling */
.ss-check {
color: green;
font-size: 2rem;
}
CSS-Only Icons (Alternative)
For environments without JavaScript, use the CSS-only approach:
<link rel="stylesheet" href="senangstart.min.css">
<i class="ss ss-check"></i>
The CSS uses mask-image with data URIs - no JavaScript required.
Extending the Components
Adding New Attributes to ss-icon
- Add to
observedAttributesarray - Handle in
render()method - Update tests in
tests/ss-icon.test.js
Example: Adding a color attribute
static get observedAttributes() {
return ["icon", "thickness", "color"];
}
render() {
const color = this.getAttribute("color") || "currentColor";
this.shadowRoot.innerHTML = `
<style>
:host { color: ${color}; }
/* ... */
</style>
${finalSvg}
`;
}
Adding Animation Support
render() {
const animate = this.hasAttribute("animate");
this.shadowRoot.innerHTML = `
<style>
${animate ? `
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
svg { animation: spin 1s linear infinite; }
` : ""}
</style>
${finalSvg}
`;
}
Converted and distributed by TomeVault — claim your Tome and manage your conversions.