| Sean McCullough | 848572d | 2025-05-13 22:27:42 +0000 | [diff] [blame] | 1 | # Component Architecture: sketch-tool-card and Related Components |
| 2 | |
| 3 | This 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. |
| 4 | |
| 5 | ## Containment Relationship |
| 6 | |
| 7 | The component hierarchy and containment relationship is structured as follows: |
| 8 | |
| 9 | 1. **sketch-app-shell** (the main application container) |
| 10 | - Contains **sketch-timeline** (for displaying conversation history) |
| 11 | - Contains **sketch-timeline-message** (for individual messages) |
| 12 | - Contains **sketch-tool-calls** (collection of tool calls) |
| 13 | - Contains specific tool card components like: |
| 14 | - **sketch-tool-card-bash** |
| 15 | - **sketch-tool-card-think** |
| 16 | - **sketch-tool-card-codereview** |
| 17 | - **sketch-tool-card-done** |
| 18 | - **sketch-tool-card-patch** |
| 19 | - **sketch-tool-card-take-screenshot** |
| Josh Bleecher Snyder | 19969a9 | 2025-06-05 14:34:02 -0700 | [diff] [blame] | 20 | - **sketch-tool-card-set-slug** |
| 21 | - **sketch-tool-card-commit-message-style** |
| Sean McCullough | 848572d | 2025-05-13 22:27:42 +0000 | [diff] [blame] | 22 | - **sketch-tool-card-multiple-choice** |
| 23 | - **sketch-tool-card-generic** (fallback for unknown tools) |
| 24 | - All of these specialized components **contain** or **compose with** the base **sketch-tool-card** |
| 25 | |
| 26 | The 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. |
| 27 | |
| 28 | For example, from `sketch-tool-card-bash.ts`: |
| 29 | |
| 30 | ```typescript |
| 31 | render() { |
| 32 | return html` <sketch-tool-card |
| 33 | .open=${this.open} |
| 34 | .toolCall=${this.toolCall} |
| 35 | > |
| 36 | <span slot="summary" class="summary-text">...</span> |
| 37 | <div slot="input" class="input">...</div> |
| 38 | <div slot="result" class="result">...</div> |
| 39 | </sketch-tool-card>`; |
| 40 | } |
| 41 | ``` |
| 42 | |
| 43 | ## CSS Styling and Effects |
| 44 | |
| 45 | Regarding how CSS rules defined in sketch-tool-card affect elements that contain it: |
| 46 | |
| 47 | 1. **Shadow DOM Encapsulation**: |
| Sean McCullough | 848572d | 2025-05-13 22:27:42 +0000 | [diff] [blame] | 48 | - Each Web Component has its own Shadow DOM, which encapsulates its styles |
| 49 | - Styles defined in `sketch-tool-card` apply only within its shadow DOM, not to parent components |
| 50 | |
| 51 | 2. **Slot Content Styling**: |
| Sean McCullough | 848572d | 2025-05-13 22:27:42 +0000 | [diff] [blame] | 52 | - The base `sketch-tool-card` defines three slots: "summary", "input", and "result" |
| 53 | - Specialized tool cards provide content for these slots |
| 54 | - The base component can style the slot containers, but cannot directly style the slotted content |
| 55 | |
| 56 | 3. **Style Inheritance and Sharing**: |
| Sean McCullough | 848572d | 2025-05-13 22:27:42 +0000 | [diff] [blame] | 57 | - The code uses a `commonStyles` constant that is shared across some components |
| 58 | - These common styles ensure consistent styling for elements like pre, code blocks |
| 59 | - Each specialized component adds its own unique styles as needed |
| 60 | |
| 61 | 4. **Parent CSS Targeting**: |
| Sean McCullough | 848572d | 2025-05-13 22:27:42 +0000 | [diff] [blame] | 62 | - In `sketch-timeline-message.ts`, there are styles that target the tool components using the `::slotted()` pseudo-element: |
| 63 | |
| 64 | ```css |
| 65 | ::slotted(sketch-tool-calls) { |
| 66 | max-width: 100%; |
| 67 | width: 100%; |
| 68 | overflow-wrap: break-word; |
| 69 | word-break: break-word; |
| 70 | } |
| 71 | ``` |
| Philip Zeyliger | b01b150 | 2025-06-26 21:20:12 -0700 | [diff] [blame^] | 72 | |
| Sean McCullough | 848572d | 2025-05-13 22:27:42 +0000 | [diff] [blame] | 73 | - This allows parent components to influence the layout of slotted components while preserving Shadow DOM encapsulation |
| 74 | |
| 75 | 5. **Host Element Styling**: |
| 76 | - The `:host` selector is used in sketch-tool-card for styling the component itself: |
| 77 | ```css |
| 78 | :host { |
| 79 | display: block; |
| 80 | max-width: 100%; |
| 81 | width: 100%; |
| 82 | box-sizing: border-box; |
| 83 | overflow: hidden; |
| 84 | } |
| 85 | ``` |
| Philip Zeyliger | b01b150 | 2025-06-26 21:20:12 -0700 | [diff] [blame^] | 86 | |
| Sean McCullough | 848572d | 2025-05-13 22:27:42 +0000 | [diff] [blame] | 87 | - This affects how the component is displayed in its parent context |
| 88 | |
| 89 | In 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 Zeyliger | 3321939 | 2025-05-14 20:43:24 -0700 | [diff] [blame] | 90 | |
| 91 | # API URLs Must Be Relative |
| 92 | |
| 93 | 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: |
| 94 | |
| 95 | ```javascript |
| 96 | // CORRECT - use relative paths without leading slash |
| 97 | const response = await fetch(`git/rawdiff?commit=${commit}`); |
| 98 | const data = await fetch(`git/show?hash=${hash}`); |
| 99 | |
| 100 | // INCORRECT - do not use absolute paths with leading slash |
| 101 | const response = await fetch(`/git/rawdiff?commit=${commit}`); // WRONG! |
| 102 | const data = await fetch(`/git/show?hash=${hash}`); // WRONG! |
| 103 | ``` |
| 104 | |
| 105 | The reason for this requirement is that Sketch may be deployed: |
| 106 | |
| 107 | 1. At the root path of a domain |
| 108 | 2. In a subdirectory |
| 109 | 3. Behind a proxy with a path prefix |
| 110 | 4. In different environments (dev, production) |
| 111 | |
| 112 | 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. |