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