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}
-
+
+
emit('click')}
+ >
${slot()}
+
+ `;
+}, ['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`
+
`;
-}, ['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`
+
+
+
+ ${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`
+
+
+
+
+
+
+ ${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`
+
+
+
+
+
+
+ ${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
+```
---