Guia Pratico de Desenvolvimento de Web Components com Claude Code
Um guia pratico de guide to developing web components usando o Claude Code com exemplos de codigo reais.
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: Cheatsheet do Claude Code em 5 minutos
Basta informar seu e-mail e enviamos na hora o cheatsheet em uma página A4.
Cuidamos dos seus dados pessoais e nunca enviamos spam.
Sobre o autor
Masa
Engenheiro apaixonado por Claude Code. Mantém o claudecode-lab.com, uma mídia tech em 10 idiomas com mais de 2.000 páginas.
Artigos relacionados
7 verificações antes de publicar todos os dias um artigo multilíngue sobre Claude Code
Uma checklist prática para publicar artigos multilíngues sobre Claude Code todos os dias sem esquecer idiomas, quebrar CTAs ou deixar páginas antigas no ar.
O que e Codex Automations? Conteudo, analise e deploy com IA enquanto voce dorme
Guia pratico para usar Codex Automations em analytics, artigos, CTA, deploy e monetizacao.
Desenhe Firestore com Claude Code: comece pelas consultas
Workflow prático para Firestore com Claude Code: schema orientado por consultas, índices, custos, regras de segurança e TypeScript.