The Agent Skills Directory
npx skills add https://smithery.ai/skills/bookklik-technologies/web-components此技能涵盖渲染图标的两个 JavaScript 组件。
位置: src/ss-icon.js
<ss-icon icon="check"></ss-icon>
<ss-icon icon="arrow-left" thickness="1.5"></ss-icon>
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
icon | string | - | 来自 icons.json 的图标标识符 |
thickness | number | 2 | 图标的描边宽度 |
class SSIcon extends HTMLElement {
// 监听属性变化
static get observedAttributes() {
return ["icon", "thickness"];
}
constructor() {
super();
this.attachShadow({ mode: "open" });
}
// 属性变化时重新渲染
attributeChangedCallback(name, oldValue, newValue) {
if (name === "icon" || name === "thickness") {
this.render();
}
}
render() {
const iconName = this.getAttribute("icon");
const iconSvg = icons[iconName];
// 将带有自定义描边宽度的 SVG 注入到 shadow DOM 中
}
}
customElements.define("ss-icon", SSIcon);
组件从父元素继承颜色:
.my-button {
color: blue;
}
.my-button ss-icon {
/* 图标将变为蓝色 */
}
覆盖尺寸:
ss-icon {
font-size: 24px; /* 图标随字体大小缩放 */
}
位置: src/ss-loader.js
<i class="ss ss-check"></i>
<i class="ss ss-arrow-left"></i>
i.ss 元素ss- 开头的类名data-ss-loaded="true" 以防止重复处理function replaceIcons() {
const elements = document.querySelectorAll("i.ss");
elements.forEach((el) => {
if (el.dataset.ssLoaded) return; // 跳过已处理的元素
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";
}
});
}
// 监视动态添加的图标
const observer = new MutationObserver((mutations) => {
// 检查添加的节点或类更改
if (shouldUpdate) replaceIcons();
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ["class"]
});
.ss {
display: inline-block;
width: 1em;
height: 1em;
vertical-align: middle;
}
/* 自定义样式 */
.ss-check {
color: green;
font-size: 2rem;
}
对于没有 JavaScript 的环境,使用纯 CSS 方案:
<link rel="stylesheet" href="senangstart.min.css">
<i class="ss ss-check"></i>
CSS 使用带有数据 URI 的 mask-image - 无需 JavaScript。
observedAttributes 数组render() 方法中处理tests/ss-icon.test.js 中的测试color 属性static get observedAttributes() {
return ["icon", "thickness", "color"];
}
render() {
const color = this.getAttribute("color") || "currentColor";
this.shadowRoot.innerHTML = `
<style>
:host { color: ${color}; }
/* ... */
</style>
${finalSvg}
`;
}
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}
`;
}
每周安装次数
–
来源
首次出现
–
This skill covers the two JavaScript components that render icons.
Location: src/ss-icon.js
<ss-icon icon="check"></ss-icon>
<ss-icon icon="arrow-left" thickness="1.5"></ss-icon>
| Attribute | Type | Default | Description |
|---|---|---|---|
icon | string | - | Icon slug from icons.json |
thickness | number | 2 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| Stroke width of the icon |
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);
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 */
}
Location: src/ss-loader.js
<i class="ss ss-check"></i>
<i class="ss ss-arrow-left"></i>
i.ss elementsss-data-ss-loaded="true" to prevent reprocessingfunction 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"]
});
.ss {
display: inline-block;
width: 1em;
height: 1em;
vertical-align: middle;
}
/* Custom styling */
.ss-check {
color: green;
font-size: 2rem;
}
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.
observedAttributes arrayrender() methodtests/ss-icon.test.jscolor attributestatic get observedAttributes() {
return ["icon", "thickness", "color"];
}
render() {
const color = this.getAttribute("color") || "currentColor";
this.shadowRoot.innerHTML = `
<style>
:host { color: ${color}; }
/* ... */
</style>
${finalSvg}
`;
}
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}
`;
}
Weekly Installs
–
Source
First Seen
–
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
111,800 周安装