blob: 71354bc732c6725c4e7ed6519b2cdee5e83e95ec [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";
banksean3d1308e2025-07-29 17:20:10 +000053 basicStatus.className = `
54 mt-4 p-3 bg-gray-50 dark:bg-gray-800 rounded font-mono text-sm
55 text-gray-900 dark:text-gray-100
bankseand5c849d2025-06-26 15:48:31 +000056 `;
57
58 const updateBasicStatus = () => {
59 basicStatus.innerHTML = `
60 <strong>Current State:</strong><br>
61 Active Mode: <code>${basicSelector.activeMode}</code><br>
62 Diff Stats: <code>+${basicSelector.diffLinesAdded} -${basicSelector.diffLinesRemoved}</code>
63 `;
64 };
65 updateBasicStatus();
66
67 // Listen for view mode changes
68 basicSelector.addEventListener("view-mode-select", (event: CustomEvent) => {
69 console.log("View mode changed:", event.detail);
70 basicSelector.activeMode = event.detail.mode;
71 updateBasicStatus();
72 });
73
74 // Create scenario examples
75 const scenarioContainer = document.createElement("div");
76 scenarioContainer.style.cssText = `
77 display: grid;
78 grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
79 gap: 15px;
80 margin-top: 15px;
81 `;
82
83 viewModeScenarios.forEach((scenario) => {
84 const scenarioCard = document.createElement("div");
banksean3d1308e2025-07-29 17:20:10 +000085 scenarioCard.className = `
86 p-4 border border-gray-300 dark:border-gray-600 rounded-lg
87 bg-white dark:bg-gray-800
bankseand5c849d2025-06-26 15:48:31 +000088 `;
89
90 const scenarioTitle = document.createElement("h4");
91 scenarioTitle.textContent = scenario.name;
banksean1ee0bc62025-07-22 23:24:18 +000092 scenarioTitle.style.cssText =
93 "margin: 0 0 5px 0; color: var(--demo-label-color);";
bankseand5c849d2025-06-26 15:48:31 +000094
95 const scenarioDesc = document.createElement("p");
96 scenarioDesc.textContent = scenario.description;
97 scenarioDesc.style.cssText =
banksean1ee0bc62025-07-22 23:24:18 +000098 "margin: 0 0 10px 0; color: var(--demo-fixture-text-color); font-size: 14px;";
bankseand5c849d2025-06-26 15:48:31 +000099
100 const scenarioWrapper = document.createElement("div");
101 scenarioWrapper.className = "@container";
102
103 const scenarioSelector = document.createElement(
104 "sketch-view-mode-select",
105 ) as any;
106 applyViewModeConfig(scenarioSelector, scenario.config);
107
108 scenarioWrapper.appendChild(scenarioSelector);
109
110 scenarioCard.appendChild(scenarioTitle);
111 scenarioCard.appendChild(scenarioDesc);
112 scenarioCard.appendChild(scenarioWrapper);
113 scenarioContainer.appendChild(scenarioCard);
114 });
115
116 // Interactive testing component
117 const interactiveSelectorContainer = document.createElement("div");
118 interactiveSelectorContainer.className = "@container";
119
120 const interactiveSelector = document.createElement(
121 "sketch-view-mode-select",
122 ) as any;
123 interactiveSelector.id = "interactive-selector";
124 applyViewModeConfig(interactiveSelector, sampleViewModeConfigs.basic);
125
126 interactiveSelectorContainer.appendChild(interactiveSelector);
127
128 // Status display for interactive selector
129 const interactiveStatus = document.createElement("div");
130 interactiveStatus.id = "interactive-status";
banksean3d1308e2025-07-29 17:20:10 +0000131 interactiveStatus.className = basicStatus.className;
bankseand5c849d2025-06-26 15:48:31 +0000132
133 const updateInteractiveStatus = () => {
134 interactiveStatus.innerHTML = `
135 <strong>Interactive Component State:</strong><br>
136 Active Mode: <code>${interactiveSelector.activeMode}</code><br>
137 Diff Lines Added: <code>${interactiveSelector.diffLinesAdded}</code><br>
138 Diff Lines Removed: <code>${interactiveSelector.diffLinesRemoved}</code><br>
139 <em>Click scenario buttons above to test different configurations</em>
140 `;
141 };
142 updateInteractiveStatus();
143
144 // Listen for view mode changes on interactive selector
145 interactiveSelector.addEventListener(
146 "view-mode-select",
147 (event: CustomEvent) => {
148 console.log("Interactive view mode changed:", event.detail);
149 interactiveSelector.activeMode = event.detail.mode;
150 updateInteractiveStatus();
151 },
152 );
153
154 // Custom controls for interactive testing
155 const customControls = document.createElement("div");
banksean3d1308e2025-07-29 17:20:10 +0000156 customControls.className = `
157 my-4 p-4 bg-gray-50 dark:bg-gray-800 rounded
bankseand5c849d2025-06-26 15:48:31 +0000158 `;
159
160 const addLinesButton = demoUtils.createButton("Add +5 Lines", () => {
161 interactiveSelector.diffLinesAdded += 5;
162 interactiveSelector.requestUpdate();
163 updateInteractiveStatus();
164 });
165
166 const removeLinesButton = demoUtils.createButton("Add -3 Lines", () => {
167 interactiveSelector.diffLinesRemoved += 3;
168 interactiveSelector.requestUpdate();
169 updateInteractiveStatus();
170 });
171
172 const clearDiffButton = demoUtils.createButton("Clear Diff", () => {
173 interactiveSelector.diffLinesAdded = 0;
174 interactiveSelector.diffLinesRemoved = 0;
175 interactiveSelector.requestUpdate();
176 updateInteractiveStatus();
177 });
178
179 const randomDiffButton = demoUtils.createButton("Random Diff", () => {
180 interactiveSelector.diffLinesAdded = Math.floor(Math.random() * 100) + 1;
181 interactiveSelector.diffLinesRemoved = Math.floor(Math.random() * 50) + 1;
182 interactiveSelector.requestUpdate();
183 updateInteractiveStatus();
184 });
185
186 customControls.appendChild(addLinesButton);
187 customControls.appendChild(removeLinesButton);
188 customControls.appendChild(clearDiffButton);
189 customControls.appendChild(randomDiffButton);
190
191 // Assemble the demo
192 basicSection.appendChild(basicContainer);
193 basicSection.appendChild(basicStatus);
194
195 scenariosSection.appendChild(scenarioContainer);
196
197 interactiveSection.appendChild(interactiveSelectorContainer);
198
199 // Add test buttons for interactive section
200 createViewModeTestButtons(interactiveSelector, interactiveSection);
201
202 interactiveSection.appendChild(customControls);
203 interactiveSection.appendChild(interactiveStatus);
204
205 container.appendChild(basicSection);
206 container.appendChild(scenariosSection);
207 container.appendChild(interactiveSection);
208
209 // Add container queries responsive testing section
210 const responsiveSection = demoUtils.createDemoSection(
211 "Container Query Responsive Testing",
212 "Demonstrates how the component behaves at different container sizes using Tailwind container queries",
213 );
214
215 // Create explanation text
216 const explanation = document.createElement("p");
banksean1ee0bc62025-07-22 23:24:18 +0000217 explanation.style.cssText =
218 "margin: 10px 0; color: var(--demo-secondary-text); font-size: 14px;";
bankseand5c849d2025-06-26 15:48:31 +0000219 explanation.innerHTML = `
220 <strong>Container Queries:</strong> The component now uses Tailwind <code>@container</code> queries instead of viewport media queries.<br>
221 This allows different sized containers to show different responsive behaviors simultaneously.
222 `;
223 responsiveSection.appendChild(explanation);
224
225 // Create different sized container examples
226 const containerExamples = [
227 {
228 title: "Extra Wide Container (700px)",
229 description: "Shows full text labels and complete layout",
230 width: "700px",
231 config: sampleViewModeConfigs.largeDiff,
232 containerClass: "w-[700px]",
233 borderColor: "border-green-500",
234 },
235 {
236 title: "Very Narrow Container (250px)",
237 description: "Shows icons only (text hidden due to container query)",
238 width: "250px",
239 config: sampleViewModeConfigs.terminalActive,
240 containerClass: "w-[250px]",
241 borderColor: "border-orange-500",
242 },
243 ];
244
245 const examplesContainer = document.createElement("div");
246 examplesContainer.style.cssText =
247 "display: flex; flex-direction: column; gap: 20px; margin: 20px 0;";
248
philip.zeyliger26bc6592025-06-30 20:15:30 -0700249 containerExamples.forEach((example) => {
bankseand5c849d2025-06-26 15:48:31 +0000250 // Create container wrapper
251 const wrapper = document.createElement("div");
banksean3d1308e2025-07-29 17:20:10 +0000252 wrapper.className = `
253 border-2 rounded-lg p-4 bg-gray-50 dark:bg-gray-800 ${example.borderColor}
bankseand5c849d2025-06-26 15:48:31 +0000254 `;
255 wrapper.className = example.borderColor;
256
257 // Create title and description
258 const header = document.createElement("div");
259 header.style.cssText = "margin-bottom: 10px;";
260 header.innerHTML = `
banksean1ee0bc62025-07-22 23:24:18 +0000261 <h4 style="margin: 0 0 5px 0; font-weight: 600; color: var(--demo-label-color);">${example.title}</h4>
262 <p style="margin: 0; font-size: 14px; color: var(--demo-secondary-text);">${example.description}</p>
bankseand5c849d2025-06-26 15:48:31 +0000263 `;
264 wrapper.appendChild(header);
265
266 // Create constrained container for the component
267 const componentContainer = document.createElement("div");
268 componentContainer.className = "@container";
banksean3d1308e2025-07-29 17:20:10 +0000269 componentContainer.className = `
270 border border-dashed border-gray-400 dark:border-gray-600 p-3
271 bg-white dark:bg-gray-800 rounded ${example.containerClass}
bankseand5c849d2025-06-26 15:48:31 +0000272 `;
273
274 // Create the component
275 const component = document.createElement(
276 "sketch-view-mode-select",
277 ) as any;
278 applyViewModeConfig(component, example.config);
279
280 componentContainer.appendChild(component);
281 wrapper.appendChild(componentContainer);
282 examplesContainer.appendChild(wrapper);
283 });
284
285 responsiveSection.appendChild(examplesContainer);
286
287 // Add interactive container size testing
288 const containerTestSection = document.createElement("div");
289 containerTestSection.style.cssText =
290 "margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd;";
291
292 const interactiveTitle = document.createElement("h4");
293 interactiveTitle.textContent = "Interactive Container Size Testing";
294 interactiveTitle.style.cssText = "margin: 0 0 10px 0; font-weight: 600;";
295
296 const interactiveDesc = document.createElement("p");
297 interactiveDesc.textContent =
298 "Use the buttons below to change the container size and see the responsive behavior in real-time.";
299 interactiveDesc.style.cssText =
banksean1ee0bc62025-07-22 23:24:18 +0000300 "margin: 0 0 15px 0; color: var(--demo-secondary-text); font-size: 14px;";
bankseand5c849d2025-06-26 15:48:31 +0000301
302 // Create interactive container
303 const interactiveContainer = document.createElement("div");
304 interactiveContainer.className = "@container";
banksean3d1308e2025-07-29 17:20:10 +0000305 interactiveContainer.className = `
306 @container border-2 border-blue-600 dark:border-blue-400 rounded-lg p-4
307 bg-blue-50 dark:bg-blue-900/20 transition-all duration-300 w-[700px]
bankseand5c849d2025-06-26 15:48:31 +0000308 `;
309
310 // Create interactive component
311 const interactiveComponent = document.createElement(
312 "sketch-view-mode-select",
313 ) as any;
314 applyViewModeConfig(interactiveComponent, sampleViewModeConfigs.largeDiff);
315
316 // Size info display
317 const sizeInfo = document.createElement("div");
318 sizeInfo.style.cssText =
banksean1ee0bc62025-07-22 23:24:18 +0000319 "margin-bottom: 10px; font-family: monospace; font-size: 12px; color: var(--demo-label-color);";
bankseand5c849d2025-06-26 15:48:31 +0000320 sizeInfo.textContent = "Current container width: 700px";
321
322 interactiveContainer.appendChild(sizeInfo);
323 interactiveContainer.appendChild(interactiveComponent);
324
325 // Control buttons
326 const controlButtons = document.createElement("div");
327 controlButtons.style.cssText =
328 "margin-top: 15px; display: flex; gap: 8px; flex-wrap: wrap;";
329
330 const sizes = [
331 { label: "Extra Wide (700px)", width: "700px" },
332 { label: "Medium (400px)", width: "400px" },
333 { label: "Very Narrow (250px)", width: "250px" },
334 ];
335
336 sizes.forEach((size) => {
337 const button = demoUtils.createButton(size.label, () => {
338 interactiveContainer.style.width = size.width;
339 sizeInfo.textContent = `Current container width: ${size.width}`;
340 });
341 controlButtons.appendChild(button);
342 });
343
344 containerTestSection.appendChild(interactiveTitle);
345 containerTestSection.appendChild(interactiveDesc);
346 containerTestSection.appendChild(interactiveContainer);
347 containerTestSection.appendChild(controlButtons);
348
349 responsiveSection.appendChild(containerTestSection);
350 container.appendChild(responsiveSection);
351 },
352
353 cleanup: async () => {
354 // Clean up any event listeners or intervals if needed
355 console.log("Cleaning up sketch-view-mode-select demo");
356 },
357};
358
359export default demo;