feat(wcctools): Add section-based configuration API for setupWccTools, new Views, and section-aware routing/sidebar

This commit is contained in:
2025-12-28 12:51:55 +00:00
parent dd151bdad8
commit 14e63738b7
14 changed files with 1709 additions and 212 deletions

229
readme.md
View File

@@ -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
```