SiamCafe · Blog
Web Components Community Building — สร้าง
บทความ

Web Components Community Building — สร้าง

เผยแพร่ 28 พฤษภาคม 2569

Web Components

Web Components Community Building — สร้าง

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`

<button

?disabled=

@click=

>

<slot></slot>

</button>

`;

}

_handleClick(e) {

if (!this.disabled) {

this.dispatchEvent(new CustomEvent('btn-click', {

bubbles: true, composed: true

}));

}

}

}

Usage in HTML:

<my-button>Click Me</my-button>

<my-button variant="outline">Outline</my-button>

<my-button disabled>Disabled</my-button>

Vanilla Web Component (no library)

class MyCard extends HTMLElement {

constructor() {

super();

this.attachShadow({ mode: 'open' });

}

connectedCallback() {

this.shadowRoot.innerHTML = `

<div class="card">

<div class="title"><slot name="title"></slot></div>

<slot></slot>

</div>

`;

}

}

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:

Web Components Community Building — สร้าง

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