blob: befdc581b5af3790aad226775a56c9b976aeb070 [file] [log] [blame]
philip.zeyliger26bc6592025-06-30 20:15:30 -07001/* eslint-disable @typescript-eslint/no-explicit-any */
bankseand5c849d2025-06-26 15:48:31 +00002/**
3 * Demo module for sketch-view-mode-select component
4 */
5
6import { DemoModule } from "./demo-framework/types";
7import {
8 demoUtils,
9 sampleViewModeConfigs,
10 viewModeScenarios,
11 applyViewModeConfig,
12 createViewModeTestButtons,
13} from "./demo-fixtures/index";
14
15const demo: DemoModule = {
16 title: "View Mode Select Demo",
17 description:
18 "Interactive tab navigation for switching between chat, diff, and terminal views",
19 imports: ["../sketch-view-mode-select"],
20 styles: ["/dist/tailwind.css"],
21
22 setup: async (container: HTMLElement) => {
23 // Create demo sections
24 const basicSection = demoUtils.createDemoSection(
25 "Basic View Mode Selector",
26 "Click buttons to switch between different views",
27 );
28
29 const scenariosSection = demoUtils.createDemoSection(
30 "Different Scenarios",
31 "Pre-configured scenarios showing various diff stats and active modes",
32 );
33
34 const interactiveSection = demoUtils.createDemoSection(
35 "Interactive Testing",
36 "Test different configurations and watch the component update",
37 );
38
39 // Basic view mode selector
40 const basicContainer = document.createElement("div");
41 basicContainer.className = "@container";
42
43 const basicSelector = document.createElement(
44 "sketch-view-mode-select",
45 ) as any;
46 basicSelector.id = "basic-selector";
47 applyViewModeConfig(basicSelector, sampleViewModeConfigs.basic);
48
49 basicContainer.appendChild(basicSelector);
50
51 // Status display for basic selector
52 const basicStatus = document.createElement("div");
53 basicStatus.id = "basic-status";
54 basicStatus.style.cssText = `
55 margin-top: 15px;
56 padding: 10px;
57 background: #f6f8fa;
58 border-radius: 6px;
59 font-family: monospace;
60 font-size: 14px;
61 `;
62
63 const updateBasicStatus = () => {
64 basicStatus.innerHTML = `
65 <strong>Current State:</strong><br>
66 Active Mode: <code>${basicSelector.activeMode}</code><br>
67 Diff Stats: <code>+${basicSelector.diffLinesAdded} -${basicSelector.diffLinesRemoved}</code>
68 `;
69 };
70 updateBasicStatus();
71
72 // Listen for view mode changes
73 basicSelector.addEventListener("view-mode-select", (event: CustomEvent) => {
74 console.log("View mode changed:", event.detail);
75 basicSelector.activeMode = event.detail.mode;
76 updateBasicStatus();
77 });
78
79 // Create scenario examples
80 const scenarioContainer = document.createElement("div");
81 scenarioContainer.style.cssText = `
82 display: grid;
83 grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
84 gap: 15px;
85 margin-top: 15px;
86 `;
87
88 viewModeScenarios.forEach((scenario) => {
89 const scenarioCard = document.createElement("div");
90 scenarioCard.style.cssText = `
91 padding: 15px;
92 border: 1px solid #d0d7de;
93 border-radius: 8px;
94 background: white;
95 `;
96
97 const scenarioTitle = document.createElement("h4");
98 scenarioTitle.textContent = scenario.name;
banksean1ee0bc62025-07-22 23:24:18 +000099 scenarioTitle.style.cssText =
100 "margin: 0 0 5px 0; color: var(--demo-label-color);";
bankseand5c849d2025-06-26 15:48:31 +0000101
102 const scenarioDesc = document.createElement("p");
103 scenarioDesc.textContent = scenario.description;
104 scenarioDesc.style.cssText =
banksean1ee0bc62025-07-22 23:24:18 +0000105 "margin: 0 0 10px 0; color: var(--demo-fixture-text-color); font-size: 14px;";
bankseand5c849d2025-06-26 15:48:31 +0000106
107 const scenarioWrapper = document.createElement("div");
108 scenarioWrapper.className = "@container";
109
110 const scenarioSelector = document.createElement(
111 "sketch-view-mode-select",
112 ) as any;
113 applyViewModeConfig(scenarioSelector, scenario.config);
114
115 scenarioWrapper.appendChild(scenarioSelector);
116
117 scenarioCard.appendChild(scenarioTitle);
118 scenarioCard.appendChild(scenarioDesc);
119 scenarioCard.appendChild(scenarioWrapper);
120 scenarioContainer.appendChild(scenarioCard);
121 });
122
123 // Interactive testing component
124 const interactiveSelectorContainer = document.createElement("div");
125 interactiveSelectorContainer.className = "@container";
126
127 const interactiveSelector = document.createElement(
128 "sketch-view-mode-select",
129 ) as any;
130 interactiveSelector.id = "interactive-selector";
131 applyViewModeConfig(interactiveSelector, sampleViewModeConfigs.basic);
132
133 interactiveSelectorContainer.appendChild(interactiveSelector);
134
135 // Status display for interactive selector
136 const interactiveStatus = document.createElement("div");
137 interactiveStatus.id = "interactive-status";
138 interactiveStatus.style.cssText = basicStatus.style.cssText;
139
140 const updateInteractiveStatus = () => {
141 interactiveStatus.innerHTML = `
142 <strong>Interactive Component State:</strong><br>
143 Active Mode: <code>${interactiveSelector.activeMode}</code><br>
144 Diff Lines Added: <code>${interactiveSelector.diffLinesAdded}</code><br>
145 Diff Lines Removed: <code>${interactiveSelector.diffLinesRemoved}</code><br>
146 <em>Click scenario buttons above to test different configurations</em>
147 `;
148 };
149 updateInteractiveStatus();
150
151 // Listen for view mode changes on interactive selector
152 interactiveSelector.addEventListener(
153 "view-mode-select",
154 (event: CustomEvent) => {
155 console.log("Interactive view mode changed:", event.detail);
156 interactiveSelector.activeMode = event.detail.mode;
157 updateInteractiveStatus();
158 },
159 );
160
161 // Custom controls for interactive testing
162 const customControls = document.createElement("div");
163 customControls.style.cssText = `
164 margin: 15px 0;
165 padding: 15px;
166 background: #f6f8fa;
167 border-radius: 6px;
168 `;
169
170 const addLinesButton = demoUtils.createButton("Add +5 Lines", () => {
171 interactiveSelector.diffLinesAdded += 5;
172 interactiveSelector.requestUpdate();
173 updateInteractiveStatus();
174 });
175
176 const removeLinesButton = demoUtils.createButton("Add -3 Lines", () => {
177 interactiveSelector.diffLinesRemoved += 3;
178 interactiveSelector.requestUpdate();
179 updateInteractiveStatus();
180 });
181
182 const clearDiffButton = demoUtils.createButton("Clear Diff", () => {
183 interactiveSelector.diffLinesAdded = 0;
184 interactiveSelector.diffLinesRemoved = 0;
185 interactiveSelector.requestUpdate();
186 updateInteractiveStatus();
187 });
188
189 const randomDiffButton = demoUtils.createButton("Random Diff", () => {
190 interactiveSelector.diffLinesAdded = Math.floor(Math.random() * 100) + 1;
191 interactiveSelector.diffLinesRemoved = Math.floor(Math.random() * 50) + 1;
192 interactiveSelector.requestUpdate();
193 updateInteractiveStatus();
194 });
195
196 customControls.appendChild(addLinesButton);
197 customControls.appendChild(removeLinesButton);
198 customControls.appendChild(clearDiffButton);
199 customControls.appendChild(randomDiffButton);
200
201 // Assemble the demo
202 basicSection.appendChild(basicContainer);
203 basicSection.appendChild(basicStatus);
204
205 scenariosSection.appendChild(scenarioContainer);
206
207 interactiveSection.appendChild(interactiveSelectorContainer);
208
209 // Add test buttons for interactive section
210 createViewModeTestButtons(interactiveSelector, interactiveSection);
211
212 interactiveSection.appendChild(customControls);
213 interactiveSection.appendChild(interactiveStatus);
214
215 container.appendChild(basicSection);
216 container.appendChild(scenariosSection);
217 container.appendChild(interactiveSection);
218
219 // Add container queries responsive testing section
220 const responsiveSection = demoUtils.createDemoSection(
221 "Container Query Responsive Testing",
222 "Demonstrates how the component behaves at different container sizes using Tailwind container queries",
223 );
224
225 // Create explanation text
226 const explanation = document.createElement("p");
banksean1ee0bc62025-07-22 23:24:18 +0000227 explanation.style.cssText =
228 "margin: 10px 0; color: var(--demo-secondary-text); font-size: 14px;";
bankseand5c849d2025-06-26 15:48:31 +0000229 explanation.innerHTML = `
230 <strong>Container Queries:</strong> The component now uses Tailwind <code>@container</code> queries instead of viewport media queries.<br>
231 This allows different sized containers to show different responsive behaviors simultaneously.
232 `;
233 responsiveSection.appendChild(explanation);
234
235 // Create different sized container examples
236 const containerExamples = [
237 {
238 title: "Extra Wide Container (700px)",
239 description: "Shows full text labels and complete layout",
240 width: "700px",
241 config: sampleViewModeConfigs.largeDiff,
242 containerClass: "w-[700px]",
243 borderColor: "border-green-500",
244 },
245 {
246 title: "Very Narrow Container (250px)",
247 description: "Shows icons only (text hidden due to container query)",
248 width: "250px",
249 config: sampleViewModeConfigs.terminalActive,
250 containerClass: "w-[250px]",
251 borderColor: "border-orange-500",
252 },
253 ];
254
255 const examplesContainer = document.createElement("div");
256 examplesContainer.style.cssText =
257 "display: flex; flex-direction: column; gap: 20px; margin: 20px 0;";
258
philip.zeyliger26bc6592025-06-30 20:15:30 -0700259 containerExamples.forEach((example) => {
bankseand5c849d2025-06-26 15:48:31 +0000260 // Create container wrapper
261 const wrapper = document.createElement("div");
262 wrapper.style.cssText = `
263 border: 2px solid;
264 border-radius: 8px;
265 padding: 15px;
266 background: #f9f9f9;
267 `;
268 wrapper.className = example.borderColor;
269
270 // Create title and description
271 const header = document.createElement("div");
272 header.style.cssText = "margin-bottom: 10px;";
273 header.innerHTML = `
banksean1ee0bc62025-07-22 23:24:18 +0000274 <h4 style="margin: 0 0 5px 0; font-weight: 600; color: var(--demo-label-color);">${example.title}</h4>
275 <p style="margin: 0; font-size: 14px; color: var(--demo-secondary-text);">${example.description}</p>
bankseand5c849d2025-06-26 15:48:31 +0000276 `;
277 wrapper.appendChild(header);
278
279 // Create constrained container for the component
280 const componentContainer = document.createElement("div");
281 componentContainer.className = "@container";
282 componentContainer.style.cssText = `
283 width: ${example.width};
284 border: 1px dashed #ccc;
285 padding: 10px;
286 background: white;
287 border-radius: 4px;
288 `;
289
290 // Create the component
291 const component = document.createElement(
292 "sketch-view-mode-select",
293 ) as any;
294 applyViewModeConfig(component, example.config);
295
296 componentContainer.appendChild(component);
297 wrapper.appendChild(componentContainer);
298 examplesContainer.appendChild(wrapper);
299 });
300
301 responsiveSection.appendChild(examplesContainer);
302
303 // Add interactive container size testing
304 const containerTestSection = document.createElement("div");
305 containerTestSection.style.cssText =
306 "margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd;";
307
308 const interactiveTitle = document.createElement("h4");
309 interactiveTitle.textContent = "Interactive Container Size Testing";
310 interactiveTitle.style.cssText = "margin: 0 0 10px 0; font-weight: 600;";
311
312 const interactiveDesc = document.createElement("p");
313 interactiveDesc.textContent =
314 "Use the buttons below to change the container size and see the responsive behavior in real-time.";
315 interactiveDesc.style.cssText =
banksean1ee0bc62025-07-22 23:24:18 +0000316 "margin: 0 0 15px 0; color: var(--demo-secondary-text); font-size: 14px;";
bankseand5c849d2025-06-26 15:48:31 +0000317
318 // Create interactive container
319 const interactiveContainer = document.createElement("div");
320 interactiveContainer.className = "@container";
321 interactiveContainer.style.cssText = `
322 border: 2px solid #007acc;
323 border-radius: 8px;
324 padding: 15px;
325 background: #f0f8ff;
326 transition: width 0.3s ease;
327 width: 700px;
328 `;
329
330 // Create interactive component
331 const interactiveComponent = document.createElement(
332 "sketch-view-mode-select",
333 ) as any;
334 applyViewModeConfig(interactiveComponent, sampleViewModeConfigs.largeDiff);
335
336 // Size info display
337 const sizeInfo = document.createElement("div");
338 sizeInfo.style.cssText =
banksean1ee0bc62025-07-22 23:24:18 +0000339 "margin-bottom: 10px; font-family: monospace; font-size: 12px; color: var(--demo-label-color);";
bankseand5c849d2025-06-26 15:48:31 +0000340 sizeInfo.textContent = "Current container width: 700px";
341
342 interactiveContainer.appendChild(sizeInfo);
343 interactiveContainer.appendChild(interactiveComponent);
344
345 // Control buttons
346 const controlButtons = document.createElement("div");
347 controlButtons.style.cssText =
348 "margin-top: 15px; display: flex; gap: 8px; flex-wrap: wrap;";
349
350 const sizes = [
351 { label: "Extra Wide (700px)", width: "700px" },
352 { label: "Medium (400px)", width: "400px" },
353 { label: "Very Narrow (250px)", width: "250px" },
354 ];
355
356 sizes.forEach((size) => {
357 const button = demoUtils.createButton(size.label, () => {
358 interactiveContainer.style.width = size.width;
359 sizeInfo.textContent = `Current container width: ${size.width}`;
360 });
361 controlButtons.appendChild(button);
362 });
363
364 containerTestSection.appendChild(interactiveTitle);
365 containerTestSection.appendChild(interactiveDesc);
366 containerTestSection.appendChild(interactiveContainer);
367 containerTestSection.appendChild(controlButtons);
368
369 responsiveSection.appendChild(containerTestSection);
370 container.appendChild(responsiveSection);
371 },
372
373 cleanup: async () => {
374 // Clean up any event listeners or intervals if needed
375 console.log("Cleaning up sketch-view-mode-select demo");
376 },
377};
378
379export default demo;