feat(wcctools): Add section-based configuration API for setupWccTools, new Views, and section-aware routing/sidebar
This commit is contained in:
229
readme.md
229
readme.md
@@ -6,12 +6,13 @@
|
||||
|
||||
`@design.estate/dees-wcctools` provides a comprehensive development environment for web components, featuring:
|
||||
|
||||
- 🎨 **Interactive Component Catalogue** — Live preview with sidebar navigation
|
||||
- 🎨 **Interactive Component Catalogue** — Live preview with customizable sidebar sections
|
||||
- 🔧 **Real-time Property Editing** — Modify component props on the fly with auto-detected editors
|
||||
- 🌓 **Theme Switching** — Test light/dark modes instantly
|
||||
- 📱 **Responsive Viewport Testing** — Phone, phablet, tablet, and desktop views
|
||||
- 🎬 **Screen Recording** — Record component demos with audio support and video trimming
|
||||
- 🧪 **Advanced Demo Tools** — Post-render hooks for interactive testing
|
||||
- 📂 **Section-based Organization** — Group components into custom sections with filtering and sorting
|
||||
- 🚀 **Zero-config Setup** — TypeScript and Lit support out of the box
|
||||
|
||||
## Issue Reporting and Security
|
||||
@@ -57,29 +58,22 @@ export class MyButton extends DeesElement {
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
button.primary {
|
||||
background: #007bff;
|
||||
background: #3b82f6;
|
||||
color: white;
|
||||
}
|
||||
button.secondary {
|
||||
background: #6c757d;
|
||||
background: #6b7280;
|
||||
color: white;
|
||||
}
|
||||
button:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
`
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<button class="${this.variant}">
|
||||
${this.label}
|
||||
</button>
|
||||
<button class="${this.variant}">${this.label}</button>
|
||||
`;
|
||||
}
|
||||
}
|
||||
@@ -93,33 +87,32 @@ import { setupWccTools } from '@design.estate/dees-wcctools';
|
||||
import { html } from 'lit';
|
||||
|
||||
// Import your components
|
||||
import { MyButton } from './components/my-button.js';
|
||||
import { MyCard } from './components/my-card.js';
|
||||
import * as elements from './components/index.js';
|
||||
import * as views from './views/index.js';
|
||||
import * as pages from './pages/index.js';
|
||||
|
||||
// Define elements for the catalogue
|
||||
const elements = {
|
||||
'my-button': MyButton,
|
||||
'my-card': MyCard,
|
||||
};
|
||||
|
||||
// Optionally define pages
|
||||
const pages = {
|
||||
'home': () => html`
|
||||
<div style="padding: 20px;">
|
||||
<h1>Welcome to My Component Library</h1>
|
||||
<p>Browse components using the sidebar.</p>
|
||||
</div>
|
||||
`,
|
||||
'getting-started': () => html`
|
||||
<div style="padding: 20px;">
|
||||
<h2>Getting Started</h2>
|
||||
<p>Installation and usage instructions...</p>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
|
||||
// Initialize the catalogue
|
||||
setupWccTools(elements, pages);
|
||||
// Initialize with sections-based configuration
|
||||
setupWccTools({
|
||||
sections: [
|
||||
{
|
||||
name: 'Pages',
|
||||
type: 'pages',
|
||||
items: pages,
|
||||
},
|
||||
{
|
||||
name: 'Views',
|
||||
type: 'elements',
|
||||
items: views,
|
||||
icon: 'web',
|
||||
},
|
||||
{
|
||||
name: 'Elements',
|
||||
type: 'elements',
|
||||
items: elements,
|
||||
sort: ([a], [b]) => a.localeCompare(b),
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Create an HTML Entry Point
|
||||
@@ -137,6 +130,69 @@ setupWccTools(elements, pages);
|
||||
</html>
|
||||
```
|
||||
|
||||
## 📂 Sections Configuration
|
||||
|
||||
The sections-based API gives you full control over how components are organized in the sidebar.
|
||||
|
||||
### Section Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `name` | `string` | Display name for the section header |
|
||||
| `type` | `'elements' \| 'pages'` | How items render (`elements` show demos, `pages` render directly) |
|
||||
| `items` | `Record<string, any>` | Object containing element classes or page factories |
|
||||
| `filter` | `(name, item) => boolean` | Optional filter function to include/exclude items |
|
||||
| `sort` | `([a, itemA], [b, itemB]) => number` | Optional sort function for ordering items |
|
||||
| `icon` | `string` | Optional Material Symbols icon name |
|
||||
| `collapsed` | `boolean` | Start section collapsed (default: `false`) |
|
||||
|
||||
### Advanced Example
|
||||
|
||||
```typescript
|
||||
import { setupWccTools } from '@design.estate/dees-wcctools';
|
||||
import * as allElements from './elements/index.js';
|
||||
import * as pages from './pages/index.js';
|
||||
|
||||
setupWccTools({
|
||||
sections: [
|
||||
{
|
||||
name: 'Pages',
|
||||
type: 'pages',
|
||||
items: pages,
|
||||
},
|
||||
{
|
||||
name: 'Form Controls',
|
||||
type: 'elements',
|
||||
items: allElements,
|
||||
icon: 'edit_note',
|
||||
filter: (name) => name.startsWith('form-') || name.includes('input'),
|
||||
sort: ([a], [b]) => a.localeCompare(b),
|
||||
},
|
||||
{
|
||||
name: 'Layout',
|
||||
type: 'elements',
|
||||
items: allElements,
|
||||
icon: 'dashboard',
|
||||
filter: (name) => name.startsWith('layout-') || name.startsWith('grid-'),
|
||||
},
|
||||
{
|
||||
name: 'Legacy',
|
||||
type: 'elements',
|
||||
items: allElements,
|
||||
filter: (name) => name.startsWith('legacy-'),
|
||||
collapsed: true, // Start collapsed
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
### Legacy API (Still Supported)
|
||||
|
||||
```typescript
|
||||
// The old format still works for simple use cases
|
||||
setupWccTools(elements, pages);
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### 🎯 Live Property Editing
|
||||
@@ -162,19 +218,7 @@ Test your components across different screen sizes:
|
||||
|
||||
### 🌓 Theme Support
|
||||
|
||||
Components automatically adapt to light/dark themes using the `goBright` property:
|
||||
|
||||
```typescript
|
||||
public render() {
|
||||
return html`
|
||||
<div class="${this.goBright ? 'light-theme' : 'dark-theme'}">
|
||||
<!-- Your component content -->
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
```
|
||||
|
||||
Or use CSS custom properties with the theme manager:
|
||||
Components automatically adapt to light/dark themes. Use CSS custom properties with the theme manager:
|
||||
|
||||
```typescript
|
||||
import { cssManager } from '@design.estate/dees-element';
|
||||
@@ -182,8 +226,8 @@ import { cssManager } from '@design.estate/dees-element';
|
||||
public static styles = [
|
||||
css`
|
||||
:host {
|
||||
color: ${cssManager.bdTheme('#000', '#fff')};
|
||||
background: ${cssManager.bdTheme('#fff', '#000')};
|
||||
color: ${cssManager.bdTheme('#1a1a1a', '#e5e5e5')};
|
||||
background: ${cssManager.bdTheme('#ffffff', '#0a0a0a')};
|
||||
}
|
||||
`
|
||||
];
|
||||
@@ -191,7 +235,7 @@ public static styles = [
|
||||
|
||||
### 🎬 Screen Recording
|
||||
|
||||
Record component demos directly from the catalogue! The built-in recorder supports:
|
||||
Record component demos directly from the catalogue:
|
||||
|
||||
- **Viewport Recording** — Record just the component viewport
|
||||
- **Full Screen Recording** — Capture the entire screen
|
||||
@@ -232,9 +276,26 @@ export class MyComponent extends DeesElement {
|
||||
}
|
||||
```
|
||||
|
||||
### 🎭 Multiple Demos
|
||||
|
||||
Components can expose multiple demo variations:
|
||||
|
||||
```typescript
|
||||
@customElement('my-button')
|
||||
export class MyButton extends DeesElement {
|
||||
public static demo = [
|
||||
() => html`<my-button variant="primary">Primary</my-button>`,
|
||||
() => html`<my-button variant="secondary">Secondary</my-button>`,
|
||||
() => html`<my-button variant="danger">Danger</my-button>`,
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Each demo appears as a numbered item in an expandable folder in the sidebar.
|
||||
|
||||
### ⏳ Async Demos
|
||||
|
||||
Return a `Promise` from `demo` for async setup. The dashboard waits for resolution:
|
||||
Return a `Promise` from `demo` for async setup:
|
||||
|
||||
```typescript
|
||||
public static demo = async () => {
|
||||
@@ -243,7 +304,7 @@ public static demo = async () => {
|
||||
};
|
||||
```
|
||||
|
||||
### 🎭 Container Queries
|
||||
### 🎯 Container Queries
|
||||
|
||||
Components can respond to their container size using the `wccToolsViewport` container:
|
||||
|
||||
@@ -269,7 +330,7 @@ public static styles = [
|
||||
|
||||
### Required for Catalogue Display
|
||||
|
||||
1. Components must expose a static `demo` property returning a Lit template
|
||||
1. Components must expose a static `demo` property returning a Lit template (or array of templates)
|
||||
2. Use `@property()` decorators with the `accessor` keyword for editable properties
|
||||
3. Export component classes for proper detection
|
||||
|
||||
@@ -278,7 +339,7 @@ public static styles = [
|
||||
```typescript
|
||||
@customElement('best-practice-component')
|
||||
export class BestPracticeComponent extends DeesElement {
|
||||
// ✅ Static demo property
|
||||
// ✅ Static demo property (single or array)
|
||||
public static demo = () => html`
|
||||
<best-practice-component
|
||||
.complexProp=${{ key: 'value' }}
|
||||
@@ -305,23 +366,40 @@ export class BestPracticeComponent extends DeesElement {
|
||||
The catalogue uses URL routing for deep linking:
|
||||
|
||||
```
|
||||
/wcctools-route/:type/:name/:viewport/:theme
|
||||
/wcctools-route/:sectionName/:itemName/:demoIndex/:viewport/:theme
|
||||
|
||||
Examples:
|
||||
/wcctools-route/element/my-button/desktop/dark
|
||||
/wcctools-route/page/home/tablet/bright
|
||||
/wcctools-route/Elements/my-button/0/desktop/dark
|
||||
/wcctools-route/Views/view-dashboard/0/tablet/bright
|
||||
/wcctools-route/Pages/home/0/desktop/dark
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `setupWccTools(elements, pages?)`
|
||||
### `setupWccTools(config)`
|
||||
|
||||
Initialize the WCC Tools dashboard.
|
||||
Initialize the WCC Tools dashboard with sections configuration.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `elements` | `Record<string, typeof LitElement>` | Map of element names to classes |
|
||||
| `pages` | `Record<string, TTemplateFactory>` | Optional map of page names to template functions |
|
||||
```typescript
|
||||
interface IWccSection {
|
||||
name: string;
|
||||
type: 'elements' | 'pages';
|
||||
items: Record<string, any>;
|
||||
filter?: (name: string, item: any) => boolean;
|
||||
sort?: (a: [string, any], b: [string, any]) => number;
|
||||
icon?: string;
|
||||
collapsed?: boolean;
|
||||
}
|
||||
|
||||
interface IWccConfig {
|
||||
sections: IWccSection[];
|
||||
}
|
||||
|
||||
setupWccTools(config: IWccConfig): void;
|
||||
|
||||
// Legacy (still supported)
|
||||
setupWccTools(elements: Record<string, any>, pages?: Record<string, TTemplateFactory>): void;
|
||||
```
|
||||
|
||||
### `DeesDemoWrapper`
|
||||
|
||||
@@ -357,14 +435,21 @@ recorder.stopRecording();
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
my-components/
|
||||
my-component-library/
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ ├── elements/ # UI components
|
||||
│ │ ├── my-button.ts
|
||||
│ │ └── my-card.ts
|
||||
│ └── catalogue.ts
|
||||
├── dist/
|
||||
├── index.html
|
||||
│ │ ├── my-card.ts
|
||||
│ │ └── index.ts
|
||||
│ ├── views/ # Full-page layouts
|
||||
│ │ ├── view-dashboard.ts
|
||||
│ │ └── index.ts
|
||||
│ ├── pages/ # Documentation pages
|
||||
│ │ ├── home.ts
|
||||
│ │ └── index.ts
|
||||
│ └── catalogue.ts # WCC Tools setup
|
||||
├── html/
|
||||
│ └── index.html
|
||||
└── package.json
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user