← スキル一覧に戻る

templ-components
by ev3rlit
claude code web과 skills를 이용해서 이것저것 만들어보는 실험실
⭐ 0🍴 0📅 2025年12月10日
SKILL.md
name: templ-components description: Create reusable templ UI components with props, children, and composition patterns. Use when building UI components, creating component libraries, mentions 'button component', 'card component', or 'reusable templ components'.
Templ Components
Overview
Build reusable, type-safe UI components with templ. Components accept strongly-typed props and can be composed together to create complex UIs.
When to Use This Skill
Use when:
- Creating reusable UI components
- Building component libraries
- User mentions "button", "card", "form", "modal" components
- Designing component APIs
- Working on design systems
Core Component Patterns
Basic Component
package components
templ Button(text string) {
<button class="btn">
{ text }
</button>
}
Component with Multiple Props
templ Button(text string, variant string, disabled bool) {
<button
class={ "btn btn-" + variant }
disabled?={ disabled }
>
{ text }
</button>
}
Usage:
components.Button("Submit", "primary", false)
Component with Children
templ Card(title string) {
<div class="card">
<div class="card-header">
<h3>{ title }</h3>
</div>
<div class="card-body">
{ children... }
</div>
</div>
}
Usage:
@Card("User Profile") {
<p>Name: John Doe</p>
<p>Email: john@example.com</p>
}
Component with Struct Props
package components
type ButtonProps struct {
Text string
Variant string
Disabled bool
OnClick string
}
templ Button(props ButtonProps) {
<button
class={ "btn btn-" + props.Variant }
disabled?={ props.Disabled }
onclick={ props.OnClick }
>
{ props.Text }
</button>
}
Common Components
Button Variants
templ PrimaryButton(text string) {
<button class="btn btn-primary">{ text }</button>
}
templ SecondaryButton(text string) {
<button class="btn btn-secondary">{ text }</button>
}
templ DangerButton(text string, onclick string) {
<button class="btn btn-danger" onclick={ onclick }>
{ text }
</button>
}
Card Component
templ Card(title string, footer string) {
<div class="card">
if title != "" {
<div class="card-header">
<h3>{ title }</h3>
</div>
}
<div class="card-body">
{ children... }
</div>
if footer != "" {
<div class="card-footer">
{ footer }
</div>
}
</div>
}
List Component
type ListItem struct {
ID string
Text string
}
templ List(items []ListItem) {
<ul class="list">
for _, item := range items {
<li data-id={ item.ID }>
{ item.Text }
</li>
}
</ul>
}
Modal Component
templ Modal(id string, title string, isOpen bool) {
<div
class={ "modal", templ.KV("modal-open", isOpen) }
id={ id }
>
<div class="modal-backdrop"></div>
<div class="modal-content">
<div class="modal-header">
<h2>{ title }</h2>
<button class="modal-close">×</button>
</div>
<div class="modal-body">
{ children... }
</div>
</div>
</div>
}
Form Components
templ Input(name string, label string, value string) {
<div class="form-group">
<label for={ name }>{ label }</label>
<input
type="text"
id={ name }
name={ name }
value={ value }
class="form-control"
/>
</div>
}
templ TextArea(name string, label string, rows int) {
<div class="form-group">
<label for={ name }>{ label }</label>
<textarea
id={ name }
name={ name }
rows={ strconv.Itoa(rows) }
class="form-control"
>
{ children... }
</textarea>
</div>
}
templ Select(name string, label string, options []string) {
<div class="form-group">
<label for={ name }>{ label }</label>
<select id={ name } name={ name } class="form-control">
for _, option := range options {
<option value={ option }>{ option }</option>
}
</select>
</div>
}
Layout Components
Container
templ Container(fluid bool) {
<div class={ templ.KV("container", !fluid), templ.KV("container-fluid", fluid) }>
{ children... }
</div>
}
Grid
templ Row() {
<div class="row">
{ children... }
</div>
}
templ Col(size int) {
<div class={ "col-" + strconv.Itoa(size) }>
{ children... }
</div>
}
Usage:
@Container(false) {
@Row() {
@Col(6) {
<p>Left column</p>
}
@Col(6) {
<p>Right column</p>
}
}
}
Navigation
type NavItem struct {
Text string
Href string
Active bool
}
templ Nav(items []NavItem) {
<nav class="navbar">
<ul class="nav">
for _, item := range items {
<li class={ templ.KV("nav-item-active", item.Active) }>
<a href={ templ.URL(item.Href) }>
{ item.Text }
</a>
</li>
}
</ul>
</nav>
}
Composition Patterns
Slots Pattern
templ Layout(title string, headerContent templ.Component, footerContent templ.Component) {
<!DOCTYPE html>
<html>
<head>
<title>{ title }</title>
</head>
<body>
<header>
@headerContent
</header>
<main>
{ children... }
</main>
<footer>
@footerContent
</footer>
</body>
</html>
}
Render Props Pattern
templ DataTable(headers []string, renderRow func(int) templ.Component) {
<table>
<thead>
<tr>
for _, header := range headers {
<th>{ header }</th>
}
</tr>
</thead>
<tbody>
for i := 0; i < 10; i++ {
@renderRow(i)
}
</tbody>
</table>
}
Wrapper Components
templ WithLoading(isLoading bool) {
if isLoading {
<div class="spinner">Loading...</div>
} else {
{ children... }
}
}
templ WithError(err error) {
if err != nil {
<div class="alert alert-error">
{ err.Error() }
</div>
} else {
{ children... }
}
}
Best Practices
1. Single Responsibility
// ✅ Good: One purpose
templ Avatar(src string, alt string) {
<img src={ src } alt={ alt } class="avatar" />
}
// ❌ Bad: Too many responsibilities
templ UserSection(user User, posts []Post, comments []Comment) {
// Too much in one component
}
2. Type-Safe Props
// ✅ Good: Strongly typed
type ButtonProps struct {
Text string
Variant ButtonVariant
}
type ButtonVariant string
const (
Primary ButtonVariant = "primary"
Secondary ButtonVariant = "secondary"
)
templ Button(props ButtonProps) {
<button class={ "btn btn-" + string(props.Variant) }>
{ props.Text }
</button>
}
3. Composition Over Complexity
// ✅ Good: Compose small components
templ UserCard(user User) {
@Card(user.Name) {
@Avatar(user.AvatarURL, user.Name)
@UserInfo(user)
@UserActions(user.ID)
}
}
// Each sub-component is simple and reusable
4. Conditional Rendering
// ✅ Good: Clear conditions
templ Message(text string, isError bool) {
if isError {
<div class="alert-error">{ text }</div>
} else {
<div class="alert-info">{ text }</div>
}
}
5. Default Props
// In Go code
type ButtonProps struct {
Text string
Variant string
Disabled bool
}
func NewButton(text string) ButtonProps {
return ButtonProps{
Text: text,
Variant: "primary",
Disabled: false,
}
}
templ Button(props ButtonProps) {
<button
class={ "btn btn-" + props.Variant }
disabled?={ props.Disabled }
>
{ props.Text }
</button>
}
Package Organization
// components/ui/button.templ
package ui
templ Button(text string) {
<button class="btn">{ text }</button>
}
// components/layout/container.templ
package layout
templ Container() {
<div class="container">
{ children... }
</div>
}
Usage:
import (
"myapp/components/ui"
"myapp/components/layout"
)
layout.Container() {
ui.Button("Click me")
}
Testing Components
func TestButton(t *testing.T) {
var buf bytes.Buffer
props := ButtonProps{
Text: "Submit",
Variant: "primary",
}
err := Button(props).Render(context.Background(), &buf)
if err != nil {
t.Fatal(err)
}
html := buf.String()
if !strings.Contains(html, "Submit") {
t.Error("Button text not found")
}
if !strings.Contains(html, "btn-primary") {
t.Error("Primary class not found")
}
}
Next Steps
- Connect to server → Use
templ-httpskill - Add interactivity → Use
templ-htmxskill - Style components → Use
templ-cssskill
スコア
総合スコア
60/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
✓LICENSE
ライセンスが設定されている
+10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です