SiamCafe.net Blog
Technology

Web Components Community Building

web components community building
Web Components Community Building | SiamCafe Blog
2025-11-17· อ. บอม — SiamCafe.net· 11,230 คำ

Web Components

Web Components Custom Elements Shadow DOM HTML Templates Design System Storybook Reusable Community Open Source npm Framework-agnostic React Vue Angular

LibrarySizeDXFrameworkเหมาะกับ
Lit5KBดีมากAnyProduction
StencilCompilerดีAny + React/VueEnterprise
Vanilla0KBปานกลางAnySimple Components
ShoelaceFull LibraryดีมากAnyReady-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}")

เคล็ดลับ

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

📖 บทความที่เกี่ยวข้อง

API Rate Limiting Community Buildingอ่านบทความ → Web Components Shift Left Securityอ่านบทความ → Java Micronaut Community Buildingอ่านบทความ → Avro Schema Community Buildingอ่านบทความ → Opsgenie Alert Community Buildingอ่านบทความ →

📚 ดูบทความทั้งหมด →