Web Components con Claude Code
Aprenda sobre Web Components usando Claude Code. Incluye consejos practicos y ejemplos de codigo.
Web Components の概要
Web Componentsは、再利用可能なカスタムHTML要素を作成するためのWeb標準技術です。フレームワークに依存せず、どのプロジェクトでも使えるコンポーネントを作れます。Claude Codeを使えば、Web Componentsの開発を効率的に進められます。
Custom Elements の基本
class AppCounter extends HTMLElement {
private count = 0;
private shadow: ShadowRoot;
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
// 監視する属性
static get observedAttributes() {
return ["initial", "step"];
}
connectedCallback() {
this.count = parseInt(this.getAttribute("initial") || "0");
this.render();
}
attributeChangedCallback(
name: string,
oldValue: string,
newValue: string
) {
if (name === "initial" && oldValue !== newValue) {
this.count = parseInt(newValue);
this.render();
}
}
private get step(): number {
return parseInt(this.getAttribute("step") || "1");
}
private render() {
this.shadow.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
gap: 8px;
font-family: system-ui, sans-serif;
}
button {
padding: 4px 12px;
border: 1px solid #ccc;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #f0f0f0;
}
.count {
font-size: 24px;
font-weight: bold;
min-width: 40px;
text-align: center;
}
</style>
<button id="dec">-</button>
<span class="count">${this.count}</span>
<button id="inc">+</button>
`;
this.shadow.getElementById("dec")!.addEventListener("click", () => {
this.count -= this.step;
this.render();
this.dispatchEvent(new CustomEvent("change", { detail: this.count }));
});
this.shadow.getElementById("inc")!.addEventListener("click", () => {
this.count += this.step;
this.render();
this.dispatchEvent(new CustomEvent("change", { detail: this.count }));
});
}
}
customElements.define("app-counter", AppCounter);
使い方:
<app-counter initial="10" step="5"></app-counter>
Lit フレームワークで効率化
import { LitElement, html, css } from "lit";
import { customElement, property, state } from "lit/decorators.js";
@customElement("app-todo-list")
class AppTodoList extends LitElement {
static styles = css`
:host {
display: block;
max-width: 400px;
font-family: system-ui, sans-serif;
}
.input-row {
display: flex;
gap: 8px;
margin-bottom: 16px;
}
input {
flex: 1;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
ul {
list-style: none;
padding: 0;
}
li {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 0;
border-bottom: 1px solid #eee;
}
.done {
text-decoration: line-through;
color: #999;
}
`;
@state()
private todos: Array<{ text: string; done: boolean }> = [];
@state()
private newTodo = "";
private addTodo() {
if (!this.newTodo.trim()) return;
this.todos = [...this.todos, { text: this.newTodo, done: false }];
this.newTodo = "";
}
private toggleTodo(index: number) {
this.todos = this.todos.map((todo, i) =>
i === index ? { ...todo, done: !todo.done } : todo
);
}
render() {
return html`
<div class="input-row">
<input
.value=${this.newTodo}
@input=${(e: InputEvent) =>
(this.newTodo = (e.target as HTMLInputElement).value)}
@keyup=${(e: KeyboardEvent) => e.key === "Enter" && this.addTodo()}
placeholder="タスクを入力..."
/>
<button @click=${this.addTodo}>追加</button>
</div>
<ul>
${this.todos.map(
(todo, i) => html`
<li>
<input
type="checkbox"
.checked=${todo.done}
@change=${() => this.toggleTodo(i)}
/>
<span class=${todo.done ? "done" : ""}>${todo.text}</span>
</li>
`
)}
</ul>
`;
}
}
スロットによるコンポジション
@customElement("app-card")
class AppCard extends LitElement {
static styles = css`
:host {
display: block;
border: 1px solid #e2e8f0;
border-radius: 8px;
overflow: hidden;
}
.header {
padding: 16px;
background: #f8fafc;
border-bottom: 1px solid #e2e8f0;
}
.body {
padding: 16px;
}
.footer {
padding: 16px;
background: #f8fafc;
border-top: 1px solid #e2e8f0;
}
`;
render() {
return html`
<div class="header">
<slot name="header"></slot>
</div>
<div class="body">
<slot></slot>
</div>
<div class="footer">
<slot name="footer"></slot>
</div>
`;
}
}
<app-card>
<h2 slot="header">カードタイトル</h2>
<p>カードの本文がここに入ります。</p>
<button slot="footer">アクション</button>
</app-card>
Reactとの統合
import { useRef, useEffect } from "react";
function CounterWrapper({
initial,
onChange,
}: {
initial: number;
onChange: (value: number) => void;
}) {
const ref = useRef<HTMLElement>(null);
useEffect(() => {
const el = ref.current;
const handler = (e: Event) => {
onChange((e as CustomEvent).detail);
};
el?.addEventListener("change", handler);
return () => el?.removeEventListener("change", handler);
}, [onChange]);
return <app-counter ref={ref} initial={initial} />;
}
Claude Codeでの活用
Web Components開発をClaude Codeに依頼する例です。スタイリングにはTailwind CSS活用法、コンポーネント設計の参考としてコード分割・遅延読み込みも参照してください。
Litを使ってデザインシステムのコンポーネントを作って。
- app-button, app-input, app-modal, app-toast
- CSS Custom Propertiesでテーマ対応
- TypeScriptで型安全に
- Storybookでドキュメント化して
Web Componentsの仕様はMDN Web Componentsを参照してください。Claude Codeの詳細は公式ドキュメントで確認できます。
Summary
Web Componentsはフレームワーク非依存の再利用可能なUIを構築できる標準技術です。Claude Codeを使えば、Custom ElementsやLitの実装を効率的に進められ、既存プロジェクトとの統合もスムーズに行えます。
PDF gratuito: Hoja de trucos de Claude Code en 5 minutos
Solo deja tu correo y te enviaremos al instante la hoja de trucos en una página A4.
Cuidamos tus datos personales y nunca enviamos spam.
Sobre el autor
Masa
Ingeniero apasionado por Claude Code. Dirige claudecode-lab.com, un medio tecnológico en 10 idiomas con más de 2.000 páginas.
Artículos relacionados
7 comprobaciones antes de publicar cada día un artículo multilingüe sobre Claude Code
Una lista práctica para publicar artículos multilingües sobre Claude Code todos los días sin olvidar idiomas, romper CTAs ni dejar páginas antiguas en producción.
Que es Codex Automations y como dejar que la IA gestione contenido mientras duermes
Guia practica para usar Codex Automations en analitica, articulos, CTA, despliegue y monetizacion.
Claude Code × GCP Cloud Functions Guía Completa | Desarrollo Serverless Ultrarrápido
Optimiza GCP Cloud Functions con Claude Code. Implementa triggers HTTP/Pub/Sub/Firestore, pruebas locales y automatización de despliegues con ejemplos de código reales de la experiencia de Masa.