sketch: remove shadowDOM dependency from tool card components
Replace shadowDOM-based slot system with property-based composition in all
sketch-tool-card-[TOOL_NAME] components to support shadowDOM-free architecture.
Problem Analysis:
- sketch-tool-card component relied on HTML5 template slots which require shadowDOM
- 13 tool card components used sketch-tool-card as composition base via slots
- shadowDOM dependency blocked broader effort to reduce shadowDOM usage
- Need to preserve all existing functionality while removing slot dependency
Solution Implementation:
- Created sketch-tool-card-base component with property-based content injection
- Replaced slot system with summaryContent, inputContent, resultContent properties
- Maintained all existing styling, behavior, and expand/collapse functionality
- Migrated all 13 existing tool card components to use new base component
Components Migrated:
- sketch-tool-card-about-sketch
- sketch-tool-card-browser-clear-console-logs
- sketch-tool-card-browser-click
- sketch-tool-card-browser-eval
- sketch-tool-card-browser-get-text
- sketch-tool-card-browser-navigate
- sketch-tool-card-browser-recent-console-logs
- sketch-tool-card-browser-resize
- sketch-tool-card-browser-scroll-into-view
- sketch-tool-card-browser-type
- sketch-tool-card-browser-wait-for
- sketch-tool-card-read-image
- sketch-tool-card-take-screenshot
Migration Pattern:
- Changed from: <slot name="summary">content</slot>
- Changed to: .summaryContent=html content
- Preserved all component-specific styling and logic
- Maintained existing API surface for parent components
Architecture Benefits:
- Removes shadowDOM requirement from 13+ components
- Enables future shadowDOM-free component development
- Maintains backward compatibility during migration
- Preserves all existing tool card functionality
Files Added:
- sketch/webui/src/web-components/sketch-tool-card-base.ts (new shadowDOM-free base)
Files Modified:
- All 13 sketch-tool-card-[TOOL_NAME].ts components migrated to use new base
Verification:
- TypeScript compilation passes without errors
- Demo pages render correctly with consistent styling
- Expand/collapse behavior preserved across all tool types
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: sa3288c1d986356e5k
diff --git a/webui/src/web-components/sketch-tool-card-about-sketch.ts b/webui/src/web-components/sketch-tool-card-about-sketch.ts
index b480568..acd9a78 100644
--- a/webui/src/web-components/sketch-tool-card-about-sketch.ts
+++ b/webui/src/web-components/sketch-tool-card-about-sketch.ts
@@ -1,8 +1,10 @@
-import { css, html, LitElement } from "lit";
+import { html } from "lit";
import { unsafeHTML } from "lit/directives/unsafe-html.js";
import { customElement, property } from "lit/decorators.js";
import { ToolCall } from "../types";
import { marked } from "marked";
+import { SketchTailwindElement } from "./sketch-tailwind-element";
+import "./sketch-tool-card-base";
// Safely renders markdown with fallback to plain text on failure
function renderMarkdown(markdownContent: string): string {
@@ -19,51 +21,38 @@
}
@customElement("sketch-tool-card-about-sketch")
-export class SketchToolCardAboutSketch extends LitElement {
+export class SketchToolCardAboutSketch extends SketchTailwindElement {
@property() toolCall: ToolCall;
@property() open: boolean;
- static styles = css`
- .summary-text {
- font-style: italic;
- }
- .about-sketch-content {
- background: rgb(246, 248, 250);
- border-radius: 6px;
- padding: 12px;
- margin-top: 10px;
- max-height: 300px;
- overflow-y: auto;
- border: 1px solid #e1e4e8;
- }
- .sketch-label {
- font-weight: bold;
- color: #24292e;
- }
- .icon {
- margin-right: 6px;
- }
- `;
+ // Styles now handled by Tailwind classes in template
render() {
const resultText = this.toolCall?.result_message?.tool_result || "";
+ const summaryContent = html`<span class="italic">
+ <span class="mr-1.5">📚</span> About Sketch
+ </span>`;
+ const inputContent = html`<div>
+ <span class="font-bold text-gray-800"></span>
+ </div>`;
+ const resultContent = this.toolCall?.result_message?.tool_result
+ ? html`<div
+ class="bg-gray-50 rounded-md p-3 mt-2.5 max-h-[300px] overflow-y-auto border border-gray-200"
+ >
+ ${unsafeHTML(renderMarkdown(resultText))}
+ </div>`
+ : "";
+
return html`
- <sketch-tool-card .open=${this.open} .toolCall=${this.toolCall}>
- <span slot="summary" class="summary-text">
- <span class="icon">📚</span> About Sketch
- </span>
- <div slot="input">
- <div><span class="sketch-label"></span></div>
- </div>
- ${this.toolCall?.result_message?.tool_result
- ? html`<div slot="result">
- <div class="about-sketch-content">
- ${unsafeHTML(renderMarkdown(resultText))}
- </div>
- </div>`
- : ""}
- </sketch-tool-card>
+ <sketch-tool-card-base
+ .open=${this.open}
+ .toolCall=${this.toolCall}
+ .summaryContent=${summaryContent}
+ .inputContent=${inputContent}
+ .resultContent=${resultContent}
+ >
+ </sketch-tool-card-base>
`;
}
}