From 2f38c9c455d4e4fdffa41e5b47d52740ba4e83ce Mon Sep 17 00:00:00 2001 From: Natxo <1172351+natxocc@users.noreply.github.com> Date: Mon, 16 Mar 2026 22:03:50 +0100 Subject: [PATCH] Update Readme.md --- Readme.md | 447 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 428 insertions(+), 19 deletions(-) diff --git a/Readme.md b/Readme.md index 53e0a2d..5485b00 100644 --- a/Readme.md +++ b/Readme.md @@ -250,42 +250,451 @@ export default $.page(({ params }) => { --- -### `$.component(tagName, setupFunction, observedAttributes)` - Web Components +## 📦 `$.component(tagName, setupFunction, observedAttributes, useShadowDOM)` - Web Components -Creates Custom Elements with reactive properties. +Creates Custom Elements with reactive properties. Choose between **Light DOM** (default) or **Shadow DOM** for style encapsulation. -#### Basic Component +### Parameters + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `tagName` | `string` | (required) | Custom element tag name (must include a hyphen, e.g., `my-button`) | +| `setupFunction` | `Function` | (required) | Function that renders the component | +| `observedAttributes` | `string[]` | `[]` | Observed attributes that react to changes | +| `useShadowDOM` | `boolean` | `false` | `true` = Shadow DOM (encapsulated), `false` = Light DOM (inherits styles) | + +--- + +### 🏠 **Light DOM** (`useShadowDOM = false`) - Default + +The component **inherits global styles** from the application. Ideal for components that should visually integrate with the rest of the interface. + +#### Example: Button with Tailwind CSS ```javascript +// button-tailwind.js import { $, html } from 'sigpro'; -$.component('my-counter', (props, { slot, emit, onUnmount }) => { - const increment = () => { - props.value(v => (parseInt(v) || 0) + 1); - emit('change', props.value()); +$.component('tw-button', (props, { slot, emit }) => { + const variant = props.variant() || 'primary'; + + const variants = { + primary: 'bg-blue-500 hover:bg-blue-600 text-white', + secondary: 'bg-gray-500 hover:bg-gray-600 text-white', + outline: 'border border-blue-500 text-blue-500 hover:bg-blue-50' }; return html` -
-

Value: ${props.value}

- + + `; +}, ['variant']); // Observe the 'variant' attribute +``` + +**Usage in HTML:** +```html + + + Save changes + + + + Cancel + +``` + +#### Example: Form Input with Validation + +```javascript +// form-input.js +$.component('form-input', (props, { emit }) => { + const handleInput = (e) => { + const value = e.target.value; + props.value(value); + emit('update', value); + + // Simple validation + if (props.pattern()) { + const regex = new RegExp(props.pattern()); + const isValid = regex.test(value); + emit('validate', isValid); + } + }; + + return html` +
+ + + ${props.error() ? html` +
${props.error()}
+ ` : ''}
`; -}, ['value']); // Observed attributes +}, ['label', 'type', 'value', 'error', 'placeholder', 'disabled', 'pattern']); ``` -Usage: +**Usage:** ```html - console.log(e.detail)}> - Child content - + email(e.detail)} + @validate=${(e) => setEmailValid(e.detail)} +> + ``` -**Parameters:** -- `tagName`: Custom element tag name (must contain a hyphen) -- `setupFunction`: Component setup function -- `observedAttributes`: Array of attribute names to observe +#### Example: Card that uses global design system + +```javascript +// content-card.js +$.component('content-card', (props, { slot }) => { + return html` +
+
+

${props.title()}

+
+
+ ${slot()} +
+ ${props.footer() ? html` + + ` : ''} +
+ `; +}, ['title', 'footer']); +``` + +**Usage:** +```html + +

Your dashboard updates will appear here.

+
+``` + +--- + +### 🛡️ **Shadow DOM** (`useShadowDOM = true`) - Encapsulated + +The component **encapsulates its styles** completely. External styles don't affect it, and its styles don't leak out. Perfect for: +- UI libraries distributed across projects +- Third-party widgets +- Components with very specific styling needs + +#### Example: Calendar Component (Distributable UI) + +```javascript +// ui-calendar.js +$.component('ui-calendar', (props, { select }) => { + const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; + const currentDate = props.date() ? new Date(props.date()) : new Date(); + + return html` + + +
+
+ + ${currentDate.toLocaleString('default', { month: 'long', year: 'numeric' })} + +
+ +
+ ${days.map(day => html`${day}`)} +
+ +
+ ${generateDays(currentDate).map(day => html` +
selectDate(day.date)} + > + ${day.number} +
+ `)} +
+
+ `; +}, ['date'], true); // true = use Shadow DOM +``` + +**Usage - anywhere, anytime, looks identical:** +```html + + +``` + +#### Example: Third-party Chat Widget + +```javascript +// chat-widget.js +$.component('chat-widget', (props, { select }) => { + return html` + + +
+
+
💬
+
+
Support Chat
+
Online
+
+
+ +
+ ${props.messages().map(msg => html` +
${msg.text}
+ `)} +
+ + +
+ `; +}, ['messages', 'currentMessage'], true); +``` + +**Usage - embed in ANY website:** +```html + +``` + +--- + +### 🎯 **Quick Decision Guide** + +| Use Light DOM (`false`) when... | Use Shadow DOM (`true`) when... | +|--------------------------------|-------------------------------| +| ✅ Component is part of your main app | ✅ Building a UI library for others | +| ✅ Using global CSS (Tailwind, Bootstrap) | ✅ Creating embeddable widgets | +| ✅ Need to inherit theme variables | ✅ Styles must be pixel-perfect everywhere | +| ✅ Working with existing design system | ✅ Component has complex, specific styles | +| ✅ Quick prototyping | ✅ Distributing to different projects | +| ✅ Form elements that should match site | ✅ Need style isolation/encapsulation | + +### 💡 **Pro Tips** + +1. **Light DOM components** are great for app-specific UI that should feel "native" to your site +2. **Shadow DOM components** are perfect for reusable "products" that must look identical everywhere +3. You can mix both in the same app - choose per component based on needs +4. Shadow DOM also provides DOM isolation - great for complex widgets + +```javascript +// Mix and match in the same app! +$.component('app-header', setup, ['title']); // Light DOM +$.component('user-menu', setup, ['items']); // Light DOM +$.component('chat-widget', setup, ['messages'], true); // Shadow DOM +$.component('data-grid', setup, ['columns', 'data'], true); // Shadow DOM +``` ---