blob: f3b62497233868f2b2aeb0dd167fa5e22a0e4d8e [file] [log] [blame] [view]
banksean333aa672025-07-13 19:49:21 +00001# Modern Component Architecture: SketchTailwindElement
2
3**IMPORTANT: New component architecture standards for all Sketch web components**
4
5## New Component Standard (Use This)
6
7All new Sketch web components should:
8
91. **Inherit from `SketchTailwindElement`** instead of `LitElement`
102. **Use Tailwind CSS classes** for styling instead of CSS-in-JS
113. **Use property-based composition** instead of slot-based composition
124. **Avoid Shadow DOM** whenever possible
13
14### Example of Modern Component:
15
16```typescript
17import { html } from "lit";
18import { customElement, property } from "lit/decorators.js";
19import { SketchTailwindElement } from "./sketch-tailwind-element";
20import "./sketch-tool-card-base";
21
22@customElement("sketch-tool-card-example")
23export class SketchToolCardExample extends SketchTailwindElement {
24 @property() toolCall: ToolCall;
25 @property() open: boolean;
26
27 render() {
28 const summaryContent = html`<span class="font-mono text-sm text-gray-700">
29 ${this.toolCall?.name}
30 </span>`;
31
32 const inputContent = html`<div class="p-2 bg-gray-100 rounded">
33 <pre class="whitespace-pre-wrap break-words">${this.toolCall?.input}</pre>
34 </div>`;
35
36 return html`<sketch-tool-card-base
37 .open=${this.open}
38 .toolCall=${this.toolCall}
39 .summaryContent=${summaryContent}
40 .inputContent=${inputContent}
41 ></sketch-tool-card-base>`;
42 }
43}
44```
45
46### Key Differences from Legacy Components:
47
48- **Extends SketchTailwindElement** (not LitElement)
49- **Uses sketch-tool-card-base** with property binding (not slots)
50- **Tailwind classes** like `font-mono text-sm text-gray-700` (not CSS-in-JS)
51- **No static styles** or Shadow DOM
52- **Property-based composition** (`.summaryContent=${html\`...\`}`)
53
54## Legacy Components (Do NOT Use as Examples)
55
56Some existing components still use the old architecture and will be migrated:
57
58- Components that extend `LitElement` directly
59- Components that use `static styles = css\`...\``
60- Components that use slot-based composition (`<slot name="summary"></slot>`)
61- Components that rely on Shadow DOM
62
63**Do not use these legacy patterns for new components.** They are being phased out.
64
65## Migration Status
66
67As of the latest migration:
68
69- All tool card components now use SketchTailwindElement
70- Complete Shadow DOM elimination in tool card hierarchy
71- Consistent Tailwind CSS styling approach
72- 🔄 Other components will be migrated over time
73
74---
75
Sean McCullough848572d2025-05-13 22:27:42 +000076# Component Architecture: sketch-tool-card and Related Components
77
78This document explains the relationship between LitElement subclasses in webui/src/web-components/ and the sketch-tool-card custom element, focusing on their containment relationship and CSS styling effects.
79
80## Containment Relationship
81
82The component hierarchy and containment relationship is structured as follows:
83
841. **sketch-app-shell** (the main application container)
85 - Contains **sketch-timeline** (for displaying conversation history)
86 - Contains **sketch-timeline-message** (for individual messages)
87 - Contains **sketch-tool-calls** (collection of tool calls)
88 - Contains specific tool card components like:
89 - **sketch-tool-card-bash**
90 - **sketch-tool-card-think**
91 - **sketch-tool-card-codereview**
92 - **sketch-tool-card-done**
93 - **sketch-tool-card-patch**
94 - **sketch-tool-card-take-screenshot**
Josh Bleecher Snyder19969a92025-06-05 14:34:02 -070095 - **sketch-tool-card-set-slug**
96 - **sketch-tool-card-commit-message-style**
Sean McCullough848572d2025-05-13 22:27:42 +000097 - **sketch-tool-card-multiple-choice**
98 - **sketch-tool-card-generic** (fallback for unknown tools)
99 - All of these specialized components **contain** or **compose with** the base **sketch-tool-card**
100
101The key aspect is that the specialized tool card components do not inherit from `SketchToolCard` in a class hierarchy sense. Instead, they **use composition** by embedding a `<sketch-tool-card>` element within their render method and passing data to it.
102
103For example, from `sketch-tool-card-bash.ts`:
104
105```typescript
106render() {
107 return html` <sketch-tool-card
108 .open=${this.open}
109 .toolCall=${this.toolCall}
110 >
111 <span slot="summary" class="summary-text">...</span>
112 <div slot="input" class="input">...</div>
113 <div slot="result" class="result">...</div>
114 </sketch-tool-card>`;
115}
116```
117
118## CSS Styling and Effects
119
120Regarding how CSS rules defined in sketch-tool-card affect elements that contain it:
121
1221. **Shadow DOM Encapsulation**:
Philip Zeyliger29732712025-06-27 09:57:12 -0700123
Sean McCullough848572d2025-05-13 22:27:42 +0000124 - Each Web Component has its own Shadow DOM, which encapsulates its styles
125 - Styles defined in `sketch-tool-card` apply only within its shadow DOM, not to parent components
126
1272. **Slot Content Styling**:
Philip Zeyliger29732712025-06-27 09:57:12 -0700128
Sean McCullough848572d2025-05-13 22:27:42 +0000129 - The base `sketch-tool-card` defines three slots: "summary", "input", and "result"
130 - Specialized tool cards provide content for these slots
131 - The base component can style the slot containers, but cannot directly style the slotted content
132
1333. **Style Inheritance and Sharing**:
Philip Zeyliger29732712025-06-27 09:57:12 -0700134
Sean McCullough848572d2025-05-13 22:27:42 +0000135 - The code uses a `commonStyles` constant that is shared across some components
136 - These common styles ensure consistent styling for elements like pre, code blocks
137 - Each specialized component adds its own unique styles as needed
138
1394. **Parent CSS Targeting**:
Philip Zeyliger29732712025-06-27 09:57:12 -0700140
Sean McCullough848572d2025-05-13 22:27:42 +0000141 - In `sketch-timeline-message.ts`, there are styles that target the tool components using the `::slotted()` pseudo-element:
142
143 ```css
144 ::slotted(sketch-tool-calls) {
145 max-width: 100%;
146 width: 100%;
147 overflow-wrap: break-word;
148 word-break: break-word;
149 }
150 ```
Philip Zeyligerb01b1502025-06-26 21:20:12 -0700151
Sean McCullough848572d2025-05-13 22:27:42 +0000152 - This allows parent components to influence the layout of slotted components while preserving Shadow DOM encapsulation
153
1545. **Host Element Styling**:
Philip Zeyliger29732712025-06-27 09:57:12 -0700155
Sean McCullough848572d2025-05-13 22:27:42 +0000156 - The `:host` selector is used in sketch-tool-card for styling the component itself:
banksean9aa141a2025-06-27 05:02:24 +0000157
Sean McCullough848572d2025-05-13 22:27:42 +0000158 ```css
159 :host {
160 display: block;
161 max-width: 100%;
162 width: 100%;
163 box-sizing: border-box;
164 overflow: hidden;
165 }
166 ```
Philip Zeyligerb01b1502025-06-26 21:20:12 -0700167
Sean McCullough848572d2025-05-13 22:27:42 +0000168 - This affects how the component is displayed in its parent context
169
170In summary, the architecture uses composition rather than inheritance, with specialized tool cards wrapping the base sketch-tool-card component and filling its slots with custom content. The CSS styling is carefully managed through Shadow DOM, with some targeted styling using ::slotted selectors to ensure proper layout and appearance throughout the component hierarchy.
Philip Zeyliger33219392025-05-14 20:43:24 -0700171
172# API URLs Must Be Relative
173
174When 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:
175
176```javascript
177// CORRECT - use relative paths without leading slash
178const response = await fetch(`git/rawdiff?commit=${commit}`);
179const data = await fetch(`git/show?hash=${hash}`);
180
181// INCORRECT - do not use absolute paths with leading slash
182const response = await fetch(`/git/rawdiff?commit=${commit}`); // WRONG!
183const data = await fetch(`/git/show?hash=${hash}`); // WRONG!
184```
185
186The reason for this requirement is that Sketch may be deployed:
187
1881. At the root path of a domain
1892. In a subdirectory
1903. Behind a proxy with a path prefix
1914. In different environments (dev, production)
192
193Using 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.