blob: 660f19a19192a8f48890c6bbfce3f357a3bf801e [file] [log] [blame] [view]
# Modern Component Architecture: SketchTailwindElement
**IMPORTANT: New component architecture standards for all Sketch web components**
## New Component Standard (Use This)
All new Sketch web components should:
1. **Inherit from `SketchTailwindElement`** instead of `LitElement`
2. **Use Tailwind CSS classes** for styling instead of CSS-in-JS
3. **Use property-based composition** instead of slot-based composition
4. **Avoid Shadow DOM** whenever possible
### Example of Modern Component:
```typescript
import { html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { SketchTailwindElement } from "./sketch-tailwind-element";
import "./sketch-tool-card-base";
@customElement("sketch-tool-card-example")
export class SketchToolCardExample extends SketchTailwindElement {
@property() toolCall: ToolCall;
@property() open: boolean;
render() {
const summaryContent = html`<span class="font-mono text-sm text-gray-700">
${this.toolCall?.name}
</span>`;
const inputContent = html`<div class="p-2 bg-gray-100 rounded">
<pre class="whitespace-pre-wrap break-words">${this.toolCall?.input}</pre>
</div>`;
return html`<sketch-tool-card-base
.open=${this.open}
.toolCall=${this.toolCall}
.summaryContent=${summaryContent}
.inputContent=${inputContent}
></sketch-tool-card-base>`;
}
}
```
### Key Differences from Legacy Components:
- **Extends SketchTailwindElement** (not LitElement)
- **Uses sketch-tool-card-base** with property binding (not slots)
- **Tailwind classes** like `font-mono text-sm text-gray-700` (not CSS-in-JS)
- **No static styles** or Shadow DOM
- **Property-based composition** (`.summaryContent=${html\`...\`}`)
## Preview, debug and iterate on your component changes with the demo server
### Setup (first time):
1. Navigate to the webui directory: `cd ./sketch/webui`
2. Install dependencies: `npm install`
3. If you encounter rollup/architecture errors, remove dependencies and reinstall:
```bash
rm -rf node_modules package-lock.json
npm install
```
### Running the demo server:
- Use the `npm run demo:runner` command to start the demo server. It will render your component changes, populated with fake example data.
- The server runs at http://localhost:5173/src/web-components/demo/demo-runner.html
- If you need to write or update the demo definition for an element, do so in demo files like ./demo/some-component-name.demo.ts
- If you need to add new example data objects for demoing components, do so in ./demo/fixtures
## Legacy Components (Do NOT Use as Examples)
Some existing components still use the old architecture and will be migrated:
- Components that extend `LitElement` directly
- Components that use `static styles = css\`...\``
- Components that use slot-based composition (`<slot name="summary"></slot>`)
- Components that rely on Shadow DOM
**Do not use these legacy patterns for new components.** They are being phased out.
# API URLs Must Be Relative
When making fetch requests to backend APIs in Sketch, all URLs **must be relative** without leading slashes. The base URL for Sketch varies depending on how it is deployed and run:
```javascript
// CORRECT - use relative paths without leading slash
const response = await fetch(`git/rawdiff?commit=${commit}`);
const data = await fetch(`git/show?hash=${hash}`);
// INCORRECT - do not use absolute paths with leading slash
const response = await fetch(`/git/rawdiff?commit=${commit}`); // WRONG!
const data = await fetch(`/git/show?hash=${hash}`); // WRONG!
```
The reason for this requirement is that Sketch may be deployed:
1. At the root path of a domain
2. In a subdirectory
3. Behind a proxy with a path prefix
4. In different environments (dev, production)
Using relative paths ensures that requests are correctly routed regardless of the deployment configuration. The browser will resolve the URLs relative to the current page location.