Web Components
Web Components Custom Elements Shadow DOM HTML Templates Design System Storybook Reusable Community Open Source npm Framework-agnostic React Vue Angular
| Library | Size | DX | Framework | เหมาะกับ |
|---|---|---|---|---|
| Lit | 5KB | ดีมาก | Any | Production |
| Stencil | Compiler | ดี | Any + React/Vue | Enterprise |
| Vanilla | 0KB | ปานกลาง | Any | Simple Components |
| Shoelace | Full Library | ดีมาก | Any | Ready-made UI |
Custom Elements
# === Web Components with Lit ===
# npm install lit
# // my-button.ts
# import { LitElement, html, css } from 'lit';
# import { customElement, property } from 'lit/decorators.js';
#
# @customElement('my-button')
# export class MyButton extends LitElement {
# static styles = css`
# :host {
# display: inline-block;
# }
# button {
# padding: 8px 16px;
# border: none;
# border-radius: 6px;
# font-size: 14px;
# cursor: pointer;
# transition: all 0.2s;
# background: var(--btn-bg, #3b82f6);
# color: var(--btn-color, white);
# }
# button:hover {
# opacity: 0.9;
# transform: translateY(-1px);
# }
# button[disabled] {
# opacity: 0.5;
# cursor: not-allowed;
# }
# :host([variant="outline"]) button {
# background: transparent;
# border: 2px solid var(--btn-bg, #3b82f6);
# color: var(--btn-bg, #3b82f6);
# }
# `;
#
# @property() variant = 'solid';
# @property({ type: Boolean }) disabled = false;
# @property() size = 'md';
#
# render() {
# return html`
#
# `;
# }
#
# _handleClick(e) {
# if (!this.disabled) {
# this.dispatchEvent(new CustomEvent('btn-click', {
# bubbles: true, composed: true
# }));
# }
# }
# }
# Usage in HTML:
# Click Me
# Outline
# Disabled
# Vanilla Web Component (no library)
# class MyCard extends HTMLElement {
# constructor() {
# super();
# this.attachShadow({ mode: 'open' });
# }
# connectedCallback() {
# this.shadowRoot.innerHTML = `
#
#
#
#
#
# `;
# }
# }
# customElements.define('my-card', MyCard);
from dataclasses import dataclass
@dataclass
class Component:
name: str
category: str
props: int
events: int
slots: int
status: str
components = [
Component("my-button", "Action", 5, 1, 1, "Stable"),
Component("my-input", "Form", 8, 3, 2, "Stable"),
Component("my-card", "Layout", 3, 0, 3, "Stable"),
Component("my-modal", "Overlay", 4, 2, 2, "Stable"),
Component("my-table", "Data", 6, 4, 3, "Beta"),
Component("my-toast", "Feedback", 4, 1, 1, "Stable"),
Component("my-tabs", "Navigation", 3, 2, 2, "Stable"),
Component("my-dropdown", "Action", 5, 3, 2, "Beta"),
]
print("=== Component Library ===")
for c in components:
print(f" [{c.status}] <{c.name}> ({c.category})")
print(f" Props: {c.props} | Events: {c.events} | Slots: {c.slots}")
Design System
# === Design System Setup ===
# Design Tokens (CSS Custom Properties)
# :root {
# /* Colors */
# --color-primary: #3b82f6;
# --color-secondary: #6366f1;
# --color-success: #22c55e;
# --color-warning: #f59e0b;
# --color-error: #ef4444;
#
# /* Typography */
# --font-sans: 'Inter', system-ui, sans-serif;
# --font-mono: 'JetBrains Mono', monospace;
# --text-xs: 0.75rem;
# --text-sm: 0.875rem;
# --text-base: 1rem;
# --text-lg: 1.125rem;
#
# /* Spacing */
# --space-1: 0.25rem;
# --space-2: 0.5rem;
# --space-4: 1rem;
# --space-8: 2rem;
#
# /* Border Radius */
# --radius-sm: 4px;
# --radius-md: 8px;
# --radius-lg: 12px;
# --radius-full: 9999px;
# }
# Storybook Setup
# npx storybook@latest init
# npm run storybook
# // my-button.stories.ts
# import { html } from 'lit';
# import './my-button';
#
# export default {
# title: 'Components/Button',
# component: 'my-button',
# argTypes: {
# variant: { control: 'select', options: ['solid', 'outline'] },
# disabled: { control: 'boolean' },
# },
# };
#
# export const Primary = { args: {} };
# export const Outline = { args: { variant: 'outline' } };
# export const Disabled = { args: { disabled: true } };
design_tokens = {
"Colors": "Primary, Secondary, Success, Warning, Error + Shades",
"Typography": "Font Family, Sizes (xs-2xl), Weight, Line Height",
"Spacing": "4px base, Scale 1-12 (4px-48px)",
"Border Radius": "sm 4px, md 8px, lg 12px, full",
"Shadows": "sm, md, lg, xl for elevation",
"Breakpoints": "sm 640px, md 768px, lg 1024px, xl 1280px",
"Animation": "Duration 150ms-500ms, Easing ease-in-out",
}
print("\nDesign Tokens:")
for category, tokens in design_tokens.items():
print(f" [{category}]: {tokens}")
Community Building
# === Open Source Community ===
# GitHub Repository Structure
# my-components/
# ├── .github/
# │ ├── ISSUE_TEMPLATE/
# │ ├── PULL_REQUEST_TEMPLATE.md
# │ └── workflows/ci.yml
# ├── src/
# │ ├── components/
# │ │ ├── button/
# │ │ ├── input/
# │ │ └── card/
# │ └── styles/tokens.css
# ├── docs/
# ├── .storybook/
# ├── package.json
# ├── CONTRIBUTING.md
# ├── CHANGELOG.md
# └── README.md
# npm publish
# npm login
# npm version patch # 1.0.0 -> 1.0.1
# npm publish --access public
# CI/CD — GitHub Actions
# name: CI
# on: [push, pull_request]
# jobs:
# test:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: actions/setup-node@v4
# - run: npm ci
# - run: npm test
# - run: npm run build
# publish:
# if: startsWith(github.ref, 'refs/tags/')
# needs: test
# steps:
# - run: npm publish
# env:
# NODE_AUTH_TOKEN: }
community_metrics = {
"GitHub Stars": "1,250",
"npm Weekly Downloads": "5,800",
"Contributors": "28",
"Open Issues": "15",
"Closed Issues": "342",
"Components": "24",
"Discord Members": "180",
"Storybook Views/mo": "3,200",
}
print("Community Metrics:")
for k, v in community_metrics.items():
print(f" {k}: {v}")
growth_tips = [
"README ดี มี Demo GIF ตัวอย่าง Quick Start",
"Storybook Deploy บน Chromatic หรือ GitHub Pages",
"CONTRIBUTING.md อธิบายวิธี Contribute ชัดเจน",
"Good First Issue Label สำหรับคนใหม่",
"Semantic Versioning + Changelog ทุก Release",
"Blog Post อธิบาย Component Design Decision",
"Twitter/X แชร์ Update ใหม่ สม่ำเสมอ",
"Conference Talk แชร์ประสบการณ์ Design System",
]
print(f"\n\nCommunity Growth Tips:")
for i, t in enumerate(growth_tips, 1):
print(f" {i}. {t}")
เคล็ดลับ
- Lit: ใช้ Lit สำหรับ Web Components เร็ว เบา 5KB
- Tokens: ใช้ CSS Custom Properties เป็น Design Tokens
- Storybook: สร้าง Storybook สำหรับ Document และ Demo
- npm: Publish บน npm ให้คนใช้ง่าย
- Community: Good First Issue + CONTRIBUTING.md สำคัญ
Web Components คืออะไร
Web Standard Reusable Custom Elements Shadow DOM HTML Templates ทุก Framework React Vue Angular Vanilla Browser Design System
สร้าง Custom Element อย่างไร
Class extends HTMLElement connectedCallback disconnectedCallback observedAttributes Shadow DOM customElements.define Hyphen ชื่อ Lit Stencil
Shadow DOM คืออะไร
Encapsulated DOM Tree แยก Style ไม่ชน attachShadow open Slot Content Projection CSS Custom Properties ทะลุได้ ป้องกัน Conflict
สร้าง Community รอบ Component Library อย่างไร
GitHub MIT Storybook CONTRIBUTING Issue PR Template Semantic Versioning npm publish Discord Blog Conference Good First Issue
สรุป
Web Components Custom Elements Shadow DOM Lit Stencil Design System Storybook Design Tokens npm Community Open Source GitHub CI/CD Framework-agnostic
