From f602dc5df4f58717f20047f6a3bfb2159b6ca027 Mon Sep 17 00:00:00 2001 From: Baivab Sarkar Date: Mon, 6 Jul 2026 20:47:29 +0530 Subject: [PATCH 1/3] feat(diagrams): group insert diagram categories --- desktop-app/resources/js/script.js | 91 ++++++++++++++++++++++-------- desktop-app/resources/styles.css | 19 +++++++ script.js | 91 ++++++++++++++++++++++-------- styles.css | 18 ++++++ 4 files changed, 171 insertions(+), 48 deletions(-) diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index ac6eb77b..db774252 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -6596,7 +6596,8 @@ document.addEventListener("DOMContentLoaded", async function () { WaveDrom: 'wavedrom', Markmap: 'markmap', Mermaid: 'mermaid', - 'ABC Notation': 'abc' + 'ABC Notation': 'abc', + 'STL (3D)': 'stl' }; return engines[category] || null; } @@ -6698,7 +6699,7 @@ document.addEventListener("DOMContentLoaded", async function () { const cleanCode = getCleanCode(template.code); const engine = getDiagramEngineForCategory(template.category); try { - if (template.category === 'ABC Notation') { + if (template.category === 'ABC Notation' || template.category === 'STL (3D)') { callback(null); return; } @@ -6758,15 +6759,27 @@ document.addEventListener("DOMContentLoaded", async function () { if (previewCode) previewCode.value = ''; confirmBtn.disabled = true; - const categories = [ - 'Mermaid', - 'PlantUML', - 'Graphviz', - 'D2', - 'Vega-Lite', - 'ABC Notation', - 'WaveDrom', - 'Markmap' + const categoryGroups = [ + { + label: 'Diagrams', + categories: ['Mermaid', 'PlantUML', 'Graphviz', 'D2'] + }, + { + label: 'Mind Maps', + categories: ['Markmap'] + }, + { + label: 'Data Visualization', + categories: ['Vega-Lite'] + }, + { + label: 'Technical Notation', + categories: ['WaveDrom', 'ABC Notation'] + }, + { + label: '3D Models', + categories: ['STL (3D)'] + } ]; const svgFlowchart = `StartEnd`; @@ -6879,6 +6892,10 @@ document.addEventListener("DOMContentLoaded", async function () { const svgMarkmapChecklist = `Tasks☒ Todo A☑ Todo B`; const svgMarkmapCode = `Projectcode()test()`; + // STL (3D) local previews + const svgStlTetrahedron = `STL`; + const svgStlBracket = `3D Mesh`; + const templates = [ // Mermaid { @@ -7462,6 +7479,24 @@ document.addEventListener("DOMContentLoaded", async function () { label: 'Inline Code Blocks', svg: svgMarkmapCode, code: '```markmap\n# Development\n## Languages\n- `JavaScript`\n- `Python`\n## Functions\n- `main()`\n- `helper_func()`\n```\n' + }, + + // STL (3D) + { + id: 'stl-tetrahedron', + category: 'STL (3D)', + title: 'Tetrahedron Mesh', + label: 'Tetrahedron Mesh', + svg: svgStlTetrahedron, + code: '```stl\nsolid tetrahedron\n facet normal 0 0 1\n outer loop\n vertex 0 0 0\n vertex 1 0 0\n vertex 0 1 0\n endloop\n endfacet\n facet normal 0 1 0\n outer loop\n vertex 0 0 0\n vertex 0 0 1\n vertex 1 0 0\n endloop\n endfacet\n facet normal 1 0 0\n outer loop\n vertex 0 0 0\n vertex 0 1 0\n vertex 0 0 1\n endloop\n endfacet\n facet normal 1 1 1\n outer loop\n vertex 1 0 0\n vertex 0 0 1\n vertex 0 1 0\n endloop\n endfacet\nendsolid tetrahedron\n```\n' + }, + { + id: 'stl-triangle-panel', + category: 'STL (3D)', + title: 'Triangle Panel', + label: 'Triangle Panel', + svg: svgStlBracket, + code: '```stl\nsolid triangle_panel\n facet normal 0 0 1\n outer loop\n vertex -1 -1 0\n vertex 1 -1 0\n vertex 0 1 0\n endloop\n endfacet\n facet normal 0 0 -1\n outer loop\n vertex -1 -1 -0.15\n vertex 0 1 -0.15\n vertex 1 -1 -0.15\n endloop\n endfacet\nendsolid triangle_panel\n```\n' } ]; @@ -7470,18 +7505,26 @@ document.addEventListener("DOMContentLoaded", async function () { function renderSidebar() { sidebar.textContent = ''; - categories.forEach(cat => { - const btn = document.createElement('button'); - btn.type = 'button'; - btn.className = 'diagram-sidebar-btn'; - if (cat === activeCategory) btn.classList.add('is-active'); - btn.textContent = cat; - btn.addEventListener('click', () => { - activeCategory = cat; - renderSidebar(); - renderGrid(); + categoryGroups.forEach(group => { + const heading = document.createElement('div'); + heading.className = 'diagram-sidebar-group-title'; + heading.setAttribute('role', 'presentation'); + heading.textContent = group.label; + sidebar.appendChild(heading); + + group.categories.forEach(cat => { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'diagram-sidebar-btn'; + if (cat === activeCategory) btn.classList.add('is-active'); + btn.textContent = cat; + btn.addEventListener('click', () => { + activeCategory = cat; + renderSidebar(); + renderGrid(); + }); + sidebar.appendChild(btn); }); - sidebar.appendChild(btn); }); } @@ -7514,7 +7557,7 @@ document.addEventListener("DOMContentLoaded", async function () { const previewDiv = document.createElement('div'); previewDiv.className = 'diagram-card-preview'; - const catClass = t.category.toLowerCase().replace(/\s+/g, ''); + const catClass = t.category.toLowerCase().replace(/[^a-z0-9]+/g, ''); previewDiv.innerHTML = `
@@ -7552,7 +7595,7 @@ document.addEventListener("DOMContentLoaded", async function () { if (previewCode) previewCode.value = t.code.trim(); confirmBtn.disabled = false; - const catClass = t.category.toLowerCase().replace(/\s+/g, ''); + const catClass = t.category.toLowerCase().replace(/[^a-z0-9]+/g, ''); // Render bottom preview container with API image & fallback previewContainer.innerHTML = `
diff --git a/desktop-app/resources/styles.css b/desktop-app/resources/styles.css index 20fff841..0ceb7246 100644 --- a/desktop-app/resources/styles.css +++ b/desktop-app/resources/styles.css @@ -5376,6 +5376,20 @@ html[data-theme="dark"] .d2-diagram > svg:not([data-diagram-native-dark="true"]) flex-shrink: 0; } +.diagram-sidebar-group-title { + padding: 14px 14px 5px; + color: var(--text-muted, #6b7280); + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.04em; + line-height: 1.2; + text-transform: uppercase; +} + +.diagram-sidebar-group-title:first-child { + padding-top: 2px; +} + .diagram-sidebar-btn { display: flex; align-items: center; @@ -5658,6 +5672,11 @@ html[data-theme="dark"] .diagram-preview-container { border-bottom: 1px solid var(--border-color); padding: 8px; } + + .diagram-sidebar-group-title { + display: none; + } + .diagram-modal-box { height: 95vh; } diff --git a/script.js b/script.js index 00801071..a6ca5bad 100644 --- a/script.js +++ b/script.js @@ -6836,7 +6836,8 @@ ${selector} .arrowheadPath { WaveDrom: 'wavedrom', Markmap: 'markmap', Mermaid: 'mermaid', - 'ABC Notation': 'abc' + 'ABC Notation': 'abc', + 'STL (3D)': 'stl' }; return engines[category] || null; } @@ -6938,7 +6939,7 @@ ${selector} .arrowheadPath { const cleanCode = getCleanCode(template.code); const engine = getDiagramEngineForCategory(template.category); try { - if (template.category === 'ABC Notation') { + if (template.category === 'ABC Notation' || template.category === 'STL (3D)') { callback(null); return; } @@ -6998,15 +6999,27 @@ ${selector} .arrowheadPath { if (previewCode) previewCode.value = ''; confirmBtn.disabled = true; - const categories = [ - 'Mermaid', - 'PlantUML', - 'Graphviz', - 'D2', - 'Vega-Lite', - 'ABC Notation', - 'WaveDrom', - 'Markmap' + const categoryGroups = [ + { + label: 'Diagrams', + categories: ['Mermaid', 'PlantUML', 'Graphviz', 'D2'] + }, + { + label: 'Mind Maps', + categories: ['Markmap'] + }, + { + label: 'Data Visualization', + categories: ['Vega-Lite'] + }, + { + label: 'Technical Notation', + categories: ['WaveDrom', 'ABC Notation'] + }, + { + label: '3D Models', + categories: ['STL (3D)'] + } ]; const svgFlowchart = `StartEnd`; @@ -7119,6 +7132,10 @@ ${selector} .arrowheadPath { const svgMarkmapChecklist = `Tasks☒ Todo A☑ Todo B`; const svgMarkmapCode = `Projectcode()test()`; + // STL (3D) local previews + const svgStlTetrahedron = `STL`; + const svgStlBracket = `3D Mesh`; + const templates = [ // Mermaid { @@ -7702,6 +7719,24 @@ ${selector} .arrowheadPath { label: 'Inline Code Blocks', svg: svgMarkmapCode, code: '```markmap\n# Development\n## Languages\n- `JavaScript`\n- `Python`\n## Functions\n- `main()`\n- `helper_func()`\n```\n' + }, + + // STL (3D) + { + id: 'stl-tetrahedron', + category: 'STL (3D)', + title: 'Tetrahedron Mesh', + label: 'Tetrahedron Mesh', + svg: svgStlTetrahedron, + code: '```stl\nsolid tetrahedron\n facet normal 0 0 1\n outer loop\n vertex 0 0 0\n vertex 1 0 0\n vertex 0 1 0\n endloop\n endfacet\n facet normal 0 1 0\n outer loop\n vertex 0 0 0\n vertex 0 0 1\n vertex 1 0 0\n endloop\n endfacet\n facet normal 1 0 0\n outer loop\n vertex 0 0 0\n vertex 0 1 0\n vertex 0 0 1\n endloop\n endfacet\n facet normal 1 1 1\n outer loop\n vertex 1 0 0\n vertex 0 0 1\n vertex 0 1 0\n endloop\n endfacet\nendsolid tetrahedron\n```\n' + }, + { + id: 'stl-triangle-panel', + category: 'STL (3D)', + title: 'Triangle Panel', + label: 'Triangle Panel', + svg: svgStlBracket, + code: '```stl\nsolid triangle_panel\n facet normal 0 0 1\n outer loop\n vertex -1 -1 0\n vertex 1 -1 0\n vertex 0 1 0\n endloop\n endfacet\n facet normal 0 0 -1\n outer loop\n vertex -1 -1 -0.15\n vertex 0 1 -0.15\n vertex 1 -1 -0.15\n endloop\n endfacet\nendsolid triangle_panel\n```\n' } ]; @@ -7710,18 +7745,26 @@ ${selector} .arrowheadPath { function renderSidebar() { sidebar.textContent = ''; - categories.forEach(cat => { - const btn = document.createElement('button'); - btn.type = 'button'; - btn.className = 'diagram-sidebar-btn'; - if (cat === activeCategory) btn.classList.add('is-active'); - btn.textContent = cat; - btn.addEventListener('click', () => { - activeCategory = cat; - renderSidebar(); - renderGrid(); + categoryGroups.forEach(group => { + const heading = document.createElement('div'); + heading.className = 'diagram-sidebar-group-title'; + heading.setAttribute('role', 'presentation'); + heading.textContent = group.label; + sidebar.appendChild(heading); + + group.categories.forEach(cat => { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'diagram-sidebar-btn'; + if (cat === activeCategory) btn.classList.add('is-active'); + btn.textContent = cat; + btn.addEventListener('click', () => { + activeCategory = cat; + renderSidebar(); + renderGrid(); + }); + sidebar.appendChild(btn); }); - sidebar.appendChild(btn); }); } @@ -7754,7 +7797,7 @@ ${selector} .arrowheadPath { const previewDiv = document.createElement('div'); previewDiv.className = 'diagram-card-preview'; - const catClass = t.category.toLowerCase().replace(/\s+/g, ''); + const catClass = t.category.toLowerCase().replace(/[^a-z0-9]+/g, ''); previewDiv.innerHTML = `
@@ -7792,7 +7835,7 @@ ${selector} .arrowheadPath { if (previewCode) previewCode.value = t.code.trim(); confirmBtn.disabled = false; - const catClass = t.category.toLowerCase().replace(/\s+/g, ''); + const catClass = t.category.toLowerCase().replace(/[^a-z0-9]+/g, ''); // Render bottom preview container with API image & fallback previewContainer.innerHTML = `
diff --git a/styles.css b/styles.css index d32280ac..7b10a80f 100644 --- a/styles.css +++ b/styles.css @@ -5464,6 +5464,20 @@ html[data-theme="dark"] .d2-diagram>svg:not([data-diagram-native-dark="true"]) { flex-shrink: 0; } +.diagram-sidebar-group-title { + padding: 14px 14px 5px; + color: var(--text-muted, #6b7280); + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.04em; + line-height: 1.2; + text-transform: uppercase; +} + +.diagram-sidebar-group-title:first-child { + padding-top: 2px; +} + .diagram-sidebar-btn { display: flex; align-items: center; @@ -5748,6 +5762,10 @@ html[data-theme="dark"] .diagram-preview-container { padding: 8px; } + .diagram-sidebar-group-title { + display: none; + } + .diagram-modal-box { height: 95vh; } From 8026b79afcdf56d72296c61d3ed64c2839cf7900 Mon Sep 17 00:00:00 2001 From: Baivab Sarkar Date: Mon, 6 Jul 2026 21:02:57 +0530 Subject: [PATCH 2/3] style(diagrams): simplify diagram group picker UI --- desktop-app/resources/js/script.js | 21 ++++++++++------- desktop-app/resources/styles.css | 36 +++++++++++++++++------------- script.js | 21 ++++++++++------- styles.css | 36 +++++++++++++++++------------- 4 files changed, 68 insertions(+), 46 deletions(-) diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index db774252..4cc69df1 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -6894,7 +6894,7 @@ document.addEventListener("DOMContentLoaded", async function () { // STL (3D) local previews const svgStlTetrahedron = `STL`; - const svgStlBracket = `3D Mesh`; + const svgStlCube = `20 mm cube`; const templates = [ // Mermaid @@ -7491,12 +7491,12 @@ document.addEventListener("DOMContentLoaded", async function () { code: '```stl\nsolid tetrahedron\n facet normal 0 0 1\n outer loop\n vertex 0 0 0\n vertex 1 0 0\n vertex 0 1 0\n endloop\n endfacet\n facet normal 0 1 0\n outer loop\n vertex 0 0 0\n vertex 0 0 1\n vertex 1 0 0\n endloop\n endfacet\n facet normal 1 0 0\n outer loop\n vertex 0 0 0\n vertex 0 1 0\n vertex 0 0 1\n endloop\n endfacet\n facet normal 1 1 1\n outer loop\n vertex 1 0 0\n vertex 0 0 1\n vertex 0 1 0\n endloop\n endfacet\nendsolid tetrahedron\n```\n' }, { - id: 'stl-triangle-panel', + id: 'stl-calibration-cube', category: 'STL (3D)', - title: 'Triangle Panel', - label: 'Triangle Panel', - svg: svgStlBracket, - code: '```stl\nsolid triangle_panel\n facet normal 0 0 1\n outer loop\n vertex -1 -1 0\n vertex 1 -1 0\n vertex 0 1 0\n endloop\n endfacet\n facet normal 0 0 -1\n outer loop\n vertex -1 -1 -0.15\n vertex 0 1 -0.15\n vertex 1 -1 -0.15\n endloop\n endfacet\nendsolid triangle_panel\n```\n' + title: 'Calibration Cube', + label: 'Calibration Cube', + svg: svgStlCube, + code: '```stl\nsolid calibration_cube_20mm\n facet normal 0 0 -1\n outer loop\n vertex 0 0 0\n vertex 20 0 0\n vertex 20 20 0\n endloop\n endfacet\n facet normal 0 0 -1\n outer loop\n vertex 0 0 0\n vertex 20 20 0\n vertex 0 20 0\n endloop\n endfacet\n facet normal 0 0 1\n outer loop\n vertex 0 0 20\n vertex 20 20 20\n vertex 20 0 20\n endloop\n endfacet\n facet normal 0 0 1\n outer loop\n vertex 0 0 20\n vertex 0 20 20\n vertex 20 20 20\n endloop\n endfacet\n facet normal 0 -1 0\n outer loop\n vertex 0 0 0\n vertex 0 0 20\n vertex 20 0 20\n endloop\n endfacet\n facet normal 0 -1 0\n outer loop\n vertex 0 0 0\n vertex 20 0 20\n vertex 20 0 0\n endloop\n endfacet\n facet normal 1 0 0\n outer loop\n vertex 20 0 0\n vertex 20 0 20\n vertex 20 20 20\n endloop\n endfacet\n facet normal 1 0 0\n outer loop\n vertex 20 0 0\n vertex 20 20 20\n vertex 20 20 0\n endloop\n endfacet\n facet normal 0 1 0\n outer loop\n vertex 20 20 0\n vertex 20 20 20\n vertex 0 20 20\n endloop\n endfacet\n facet normal 0 1 0\n outer loop\n vertex 20 20 0\n vertex 0 20 20\n vertex 0 20 0\n endloop\n endfacet\n facet normal -1 0 0\n outer loop\n vertex 0 20 0\n vertex 0 20 20\n vertex 0 0 20\n endloop\n endfacet\n facet normal -1 0 0\n outer loop\n vertex 0 20 0\n vertex 0 0 20\n vertex 0 0 0\n endloop\n endfacet\nendsolid calibration_cube_20mm\n```\n' } ]; @@ -7506,11 +7506,14 @@ document.addEventListener("DOMContentLoaded", async function () { function renderSidebar() { sidebar.textContent = ''; categoryGroups.forEach(group => { + const groupEl = document.createElement('div'); + groupEl.className = 'diagram-sidebar-group'; + const heading = document.createElement('div'); heading.className = 'diagram-sidebar-group-title'; heading.setAttribute('role', 'presentation'); heading.textContent = group.label; - sidebar.appendChild(heading); + groupEl.appendChild(heading); group.categories.forEach(cat => { const btn = document.createElement('button'); @@ -7523,8 +7526,10 @@ document.addEventListener("DOMContentLoaded", async function () { renderSidebar(); renderGrid(); }); - sidebar.appendChild(btn); + groupEl.appendChild(btn); }); + + sidebar.appendChild(groupEl); }); } diff --git a/desktop-app/resources/styles.css b/desktop-app/resources/styles.css index 0ceb7246..6f7602a4 100644 --- a/desktop-app/resources/styles.css +++ b/desktop-app/resources/styles.css @@ -5368,33 +5368,34 @@ html[data-theme="dark"] .d2-diagram > svg:not([data-diagram-native-dark="true"]) .diagram-modal-sidebar { width: 220px; border-right: 1px solid var(--border-color); - padding: 16px 8px; + padding: 14px 10px; overflow-y: auto; display: flex; flex-direction: column; - gap: 4px; + gap: 14px; flex-shrink: 0; } +.diagram-sidebar-group { + display: flex; + flex-direction: column; + gap: 3px; +} + .diagram-sidebar-group-title { - padding: 14px 14px 5px; + padding: 0 10px 4px; color: var(--text-muted, #6b7280); - font-size: 0.72rem; - font-weight: 700; - letter-spacing: 0.04em; + font-size: 0.76rem; + font-weight: 600; + letter-spacing: 0; line-height: 1.2; - text-transform: uppercase; -} - -.diagram-sidebar-group-title:first-child { - padding-top: 2px; } .diagram-sidebar-btn { display: flex; align-items: center; gap: 10px; - padding: 10px 14px; + padding: 9px 12px; border: none; background: transparent; color: var(--text-color); @@ -5407,12 +5408,13 @@ html[data-theme="dark"] .d2-diagram > svg:not([data-diagram-native-dark="true"]) } .diagram-sidebar-btn:hover { - background-color: var(--button-hover-bg, rgba(120, 120, 120, 0.1)); + background-color: var(--button-hover-bg, rgba(120, 120, 120, 0.08)); } .diagram-sidebar-btn.is-active { - background-color: var(--accent-color, #0076ff); - color: #fff; + background-color: color-mix(in srgb, var(--accent-color, #0076ff) 12%, transparent); + color: var(--accent-color, #0076ff); + font-weight: 650; } .diagram-modal-content { @@ -5677,6 +5679,10 @@ html[data-theme="dark"] .diagram-preview-container { display: none; } + .diagram-sidebar-group { + display: contents; + } + .diagram-modal-box { height: 95vh; } diff --git a/script.js b/script.js index a6ca5bad..6303caa1 100644 --- a/script.js +++ b/script.js @@ -7134,7 +7134,7 @@ ${selector} .arrowheadPath { // STL (3D) local previews const svgStlTetrahedron = `STL`; - const svgStlBracket = `3D Mesh`; + const svgStlCube = `20 mm cube`; const templates = [ // Mermaid @@ -7731,12 +7731,12 @@ ${selector} .arrowheadPath { code: '```stl\nsolid tetrahedron\n facet normal 0 0 1\n outer loop\n vertex 0 0 0\n vertex 1 0 0\n vertex 0 1 0\n endloop\n endfacet\n facet normal 0 1 0\n outer loop\n vertex 0 0 0\n vertex 0 0 1\n vertex 1 0 0\n endloop\n endfacet\n facet normal 1 0 0\n outer loop\n vertex 0 0 0\n vertex 0 1 0\n vertex 0 0 1\n endloop\n endfacet\n facet normal 1 1 1\n outer loop\n vertex 1 0 0\n vertex 0 0 1\n vertex 0 1 0\n endloop\n endfacet\nendsolid tetrahedron\n```\n' }, { - id: 'stl-triangle-panel', + id: 'stl-calibration-cube', category: 'STL (3D)', - title: 'Triangle Panel', - label: 'Triangle Panel', - svg: svgStlBracket, - code: '```stl\nsolid triangle_panel\n facet normal 0 0 1\n outer loop\n vertex -1 -1 0\n vertex 1 -1 0\n vertex 0 1 0\n endloop\n endfacet\n facet normal 0 0 -1\n outer loop\n vertex -1 -1 -0.15\n vertex 0 1 -0.15\n vertex 1 -1 -0.15\n endloop\n endfacet\nendsolid triangle_panel\n```\n' + title: 'Calibration Cube', + label: 'Calibration Cube', + svg: svgStlCube, + code: '```stl\nsolid calibration_cube_20mm\n facet normal 0 0 -1\n outer loop\n vertex 0 0 0\n vertex 20 0 0\n vertex 20 20 0\n endloop\n endfacet\n facet normal 0 0 -1\n outer loop\n vertex 0 0 0\n vertex 20 20 0\n vertex 0 20 0\n endloop\n endfacet\n facet normal 0 0 1\n outer loop\n vertex 0 0 20\n vertex 20 20 20\n vertex 20 0 20\n endloop\n endfacet\n facet normal 0 0 1\n outer loop\n vertex 0 0 20\n vertex 0 20 20\n vertex 20 20 20\n endloop\n endfacet\n facet normal 0 -1 0\n outer loop\n vertex 0 0 0\n vertex 0 0 20\n vertex 20 0 20\n endloop\n endfacet\n facet normal 0 -1 0\n outer loop\n vertex 0 0 0\n vertex 20 0 20\n vertex 20 0 0\n endloop\n endfacet\n facet normal 1 0 0\n outer loop\n vertex 20 0 0\n vertex 20 0 20\n vertex 20 20 20\n endloop\n endfacet\n facet normal 1 0 0\n outer loop\n vertex 20 0 0\n vertex 20 20 20\n vertex 20 20 0\n endloop\n endfacet\n facet normal 0 1 0\n outer loop\n vertex 20 20 0\n vertex 20 20 20\n vertex 0 20 20\n endloop\n endfacet\n facet normal 0 1 0\n outer loop\n vertex 20 20 0\n vertex 0 20 20\n vertex 0 20 0\n endloop\n endfacet\n facet normal -1 0 0\n outer loop\n vertex 0 20 0\n vertex 0 20 20\n vertex 0 0 20\n endloop\n endfacet\n facet normal -1 0 0\n outer loop\n vertex 0 20 0\n vertex 0 0 20\n vertex 0 0 0\n endloop\n endfacet\nendsolid calibration_cube_20mm\n```\n' } ]; @@ -7746,11 +7746,14 @@ ${selector} .arrowheadPath { function renderSidebar() { sidebar.textContent = ''; categoryGroups.forEach(group => { + const groupEl = document.createElement('div'); + groupEl.className = 'diagram-sidebar-group'; + const heading = document.createElement('div'); heading.className = 'diagram-sidebar-group-title'; heading.setAttribute('role', 'presentation'); heading.textContent = group.label; - sidebar.appendChild(heading); + groupEl.appendChild(heading); group.categories.forEach(cat => { const btn = document.createElement('button'); @@ -7763,8 +7766,10 @@ ${selector} .arrowheadPath { renderSidebar(); renderGrid(); }); - sidebar.appendChild(btn); + groupEl.appendChild(btn); }); + + sidebar.appendChild(groupEl); }); } diff --git a/styles.css b/styles.css index 7b10a80f..2eef166a 100644 --- a/styles.css +++ b/styles.css @@ -5456,33 +5456,34 @@ html[data-theme="dark"] .d2-diagram>svg:not([data-diagram-native-dark="true"]) { .diagram-modal-sidebar { width: 220px; border-right: 1px solid var(--border-color); - padding: 16px 8px; + padding: 14px 10px; overflow-y: auto; display: flex; flex-direction: column; - gap: 4px; + gap: 14px; flex-shrink: 0; } +.diagram-sidebar-group { + display: flex; + flex-direction: column; + gap: 3px; +} + .diagram-sidebar-group-title { - padding: 14px 14px 5px; + padding: 0 10px 4px; color: var(--text-muted, #6b7280); - font-size: 0.72rem; - font-weight: 700; - letter-spacing: 0.04em; + font-size: 0.76rem; + font-weight: 600; + letter-spacing: 0; line-height: 1.2; - text-transform: uppercase; -} - -.diagram-sidebar-group-title:first-child { - padding-top: 2px; } .diagram-sidebar-btn { display: flex; align-items: center; gap: 10px; - padding: 10px 14px; + padding: 9px 12px; border: none; background: transparent; color: var(--text-color); @@ -5495,12 +5496,13 @@ html[data-theme="dark"] .d2-diagram>svg:not([data-diagram-native-dark="true"]) { } .diagram-sidebar-btn:hover { - background-color: var(--button-hover-bg, rgba(120, 120, 120, 0.1)); + background-color: var(--button-hover-bg, rgba(120, 120, 120, 0.08)); } .diagram-sidebar-btn.is-active { - background-color: var(--accent-color, #0076ff); - color: #fff; + background-color: color-mix(in srgb, var(--accent-color, #0076ff) 12%, transparent); + color: var(--accent-color, #0076ff); + font-weight: 650; } .diagram-modal-content { @@ -5766,6 +5768,10 @@ html[data-theme="dark"] .diagram-preview-container { display: none; } + .diagram-sidebar-group { + display: contents; + } + .diagram-modal-box { height: 95vh; } From fd3d24787ee4998c05e54f1a73e40d9160bc8868 Mon Sep 17 00:00:00 2001 From: Baivab Sarkar Date: Mon, 6 Jul 2026 22:04:14 +0530 Subject: [PATCH 3/3] style(diagrams): match sidebar accordion design --- desktop-app/resources/js/script.js | 54 +++++++++++-- desktop-app/resources/styles.css | 122 +++++++++++++++++++++++------ script.js | 54 +++++++++++-- styles.css | 122 +++++++++++++++++++++++------ 4 files changed, 290 insertions(+), 62 deletions(-) diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index 4cc69df1..79c8dd5a 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -6762,25 +6762,42 @@ document.addEventListener("DOMContentLoaded", async function () { const categoryGroups = [ { label: 'Diagrams', + icon: 'bi-diagram-3', categories: ['Mermaid', 'PlantUML', 'Graphviz', 'D2'] }, { label: 'Mind Maps', + icon: 'bi-diagram-2', categories: ['Markmap'] }, { label: 'Data Visualization', + icon: 'bi-bar-chart-line', categories: ['Vega-Lite'] }, { label: 'Technical Notation', + icon: 'bi-code-slash', categories: ['WaveDrom', 'ABC Notation'] }, { label: '3D Models', + icon: 'bi-box', categories: ['STL (3D)'] } ]; + + const categoryIcons = { + Mermaid: 'bi-water', + PlantUML: 'bi-leaf', + Graphviz: 'bi-bezier2', + D2: 'bi-badge-2d', + Markmap: 'bi-diagram-2', + 'Vega-Lite': 'bi-bar-chart-line', + WaveDrom: 'bi-activity', + 'ABC Notation': 'bi-music-note-beamed', + 'STL (3D)': 'bi-box' + }; const svgFlowchart = `StartEnd`; const svgMermaidFlowchartLR = `LeftRight`; @@ -7506,29 +7523,52 @@ document.addEventListener("DOMContentLoaded", async function () { function renderSidebar() { sidebar.textContent = ''; categoryGroups.forEach(group => { + const isExpanded = group.categories.includes(activeCategory); const groupEl = document.createElement('div'); groupEl.className = 'diagram-sidebar-group'; - - const heading = document.createElement('div'); - heading.className = 'diagram-sidebar-group-title'; - heading.setAttribute('role', 'presentation'); - heading.textContent = group.label; + if (isExpanded) groupEl.classList.add('is-expanded'); + + const heading = document.createElement('button'); + heading.type = 'button'; + heading.className = 'diagram-sidebar-group-header'; + heading.setAttribute('aria-expanded', String(isExpanded)); + heading.innerHTML = ` + + ${group.label} + + `; + heading.addEventListener('click', () => { + if (!isExpanded) { + activeCategory = group.categories[0]; + selectedTemplate = null; + renderSidebar(); + renderGrid(); + } + }); groupEl.appendChild(heading); + const itemsEl = document.createElement('div'); + itemsEl.className = 'diagram-sidebar-items'; + group.categories.forEach(cat => { const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'diagram-sidebar-btn'; if (cat === activeCategory) btn.classList.add('is-active'); - btn.textContent = cat; + btn.innerHTML = ` + + ${cat} + `; btn.addEventListener('click', () => { activeCategory = cat; renderSidebar(); renderGrid(); }); - groupEl.appendChild(btn); + itemsEl.appendChild(btn); }); + groupEl.appendChild(itemsEl); + sidebar.appendChild(groupEl); }); } diff --git a/desktop-app/resources/styles.css b/desktop-app/resources/styles.css index 6f7602a4..72391f1c 100644 --- a/desktop-app/resources/styles.css +++ b/desktop-app/resources/styles.css @@ -5366,57 +5366,116 @@ html[data-theme="dark"] .d2-diagram > svg:not([data-diagram-native-dark="true"]) } .diagram-modal-sidebar { - width: 220px; - border-right: 1px solid var(--border-color); - padding: 14px 10px; + width: 260px; + margin: 16px 0 16px 16px; + border: 1px solid var(--border-color); + border-radius: 8px; + background: var(--bg-color); + padding: 0; overflow-y: auto; display: flex; flex-direction: column; - gap: 14px; + gap: 0; flex-shrink: 0; } .diagram-sidebar-group { display: flex; flex-direction: column; - gap: 3px; + border-top: 1px solid var(--border-color); } -.diagram-sidebar-group-title { - padding: 0 10px 4px; - color: var(--text-muted, #6b7280); - font-size: 0.76rem; - font-weight: 600; - letter-spacing: 0; - line-height: 1.2; +.diagram-sidebar-group:first-child { + border-top: none; } +.diagram-sidebar-group-header, .diagram-sidebar-btn { - display: flex; - align-items: center; - gap: 10px; - padding: 9px 12px; + width: 100%; border: none; background: transparent; color: var(--text-color); - text-align: left; - border-radius: 6px; cursor: pointer; - font-size: 0.9rem; - font-weight: 500; + font-size: 0.95rem; + text-align: left; transition: background-color 0.15s ease, color 0.15s ease; } +.diagram-sidebar-group-header { + display: grid; + grid-template-columns: 24px 1fr 18px; + align-items: center; + gap: 12px; + min-height: 62px; + padding: 0 18px; + font-weight: 500; +} + +.diagram-sidebar-group-header:hover { + background-color: var(--button-hover-bg, rgba(120, 120, 120, 0.06)); +} + +.diagram-sidebar-group-icon, +.diagram-sidebar-item-icon, +.diagram-sidebar-chevron { + display: inline-flex; + align-items: center; + justify-content: center; + line-height: 1; +} + +.diagram-sidebar-group-icon { + color: var(--text-color); + font-size: 1.1rem; +} + +.diagram-sidebar-chevron { + justify-self: end; + color: var(--text-muted, #6b7280); + font-size: 0.85rem; +} + +.diagram-sidebar-items { + display: none; + flex-direction: column; + gap: 4px; + padding: 0 12px 12px; +} + +.diagram-sidebar-group.is-expanded .diagram-sidebar-items { + display: flex; +} + +.diagram-sidebar-btn { + display: flex; + align-items: center; + gap: 14px; + min-height: 50px; + padding: 0 16px 0 20px; + border-radius: 7px; + font-weight: 500; +} + .diagram-sidebar-btn:hover { - background-color: var(--button-hover-bg, rgba(120, 120, 120, 0.08)); + background-color: var(--button-hover-bg, rgba(120, 120, 120, 0.06)); } .diagram-sidebar-btn.is-active { - background-color: color-mix(in srgb, var(--accent-color, #0076ff) 12%, transparent); + background-color: color-mix(in srgb, var(--accent-color, #0076ff) 13%, transparent); color: var(--accent-color, #0076ff); font-weight: 650; } +.diagram-sidebar-btn.is-active .diagram-sidebar-item-icon { + color: var(--accent-color, #0076ff); +} + +.diagram-sidebar-item-icon { + width: 22px; + color: var(--text-muted, #6b7280); + font-size: 1.05rem; +} + .diagram-modal-content { flex: 1; display: flex; @@ -5662,20 +5721,24 @@ html[data-theme="dark"] .diagram-preview-container { display: none !important; } -@media (max-width: 768px) { +@media (max-width: 640px) { .diagram-modal-body { flex-direction: column; } .diagram-modal-sidebar { width: 100%; height: 60px; + margin: 0; flex-direction: row; border-right: none; border-bottom: 1px solid var(--border-color); + border-left: none; + border-radius: 0; padding: 8px; + gap: 6px; } - .diagram-sidebar-group-title { + .diagram-sidebar-group-header { display: none; } @@ -5683,6 +5746,17 @@ html[data-theme="dark"] .diagram-preview-container { display: contents; } + .diagram-sidebar-items { + display: contents; + } + + .diagram-sidebar-btn { + width: auto; + min-height: 36px; + flex-shrink: 0; + padding: 0 12px; + } + .diagram-modal-box { height: 95vh; } diff --git a/script.js b/script.js index 6303caa1..82a110fd 100644 --- a/script.js +++ b/script.js @@ -7002,25 +7002,42 @@ ${selector} .arrowheadPath { const categoryGroups = [ { label: 'Diagrams', + icon: 'bi-diagram-3', categories: ['Mermaid', 'PlantUML', 'Graphviz', 'D2'] }, { label: 'Mind Maps', + icon: 'bi-diagram-2', categories: ['Markmap'] }, { label: 'Data Visualization', + icon: 'bi-bar-chart-line', categories: ['Vega-Lite'] }, { label: 'Technical Notation', + icon: 'bi-code-slash', categories: ['WaveDrom', 'ABC Notation'] }, { label: '3D Models', + icon: 'bi-box', categories: ['STL (3D)'] } ]; + + const categoryIcons = { + Mermaid: 'bi-water', + PlantUML: 'bi-leaf', + Graphviz: 'bi-bezier2', + D2: 'bi-badge-2d', + Markmap: 'bi-diagram-2', + 'Vega-Lite': 'bi-bar-chart-line', + WaveDrom: 'bi-activity', + 'ABC Notation': 'bi-music-note-beamed', + 'STL (3D)': 'bi-box' + }; const svgFlowchart = `StartEnd`; const svgMermaidFlowchartLR = `LeftRight`; @@ -7746,29 +7763,52 @@ ${selector} .arrowheadPath { function renderSidebar() { sidebar.textContent = ''; categoryGroups.forEach(group => { + const isExpanded = group.categories.includes(activeCategory); const groupEl = document.createElement('div'); groupEl.className = 'diagram-sidebar-group'; - - const heading = document.createElement('div'); - heading.className = 'diagram-sidebar-group-title'; - heading.setAttribute('role', 'presentation'); - heading.textContent = group.label; + if (isExpanded) groupEl.classList.add('is-expanded'); + + const heading = document.createElement('button'); + heading.type = 'button'; + heading.className = 'diagram-sidebar-group-header'; + heading.setAttribute('aria-expanded', String(isExpanded)); + heading.innerHTML = ` + + ${group.label} + + `; + heading.addEventListener('click', () => { + if (!isExpanded) { + activeCategory = group.categories[0]; + selectedTemplate = null; + renderSidebar(); + renderGrid(); + } + }); groupEl.appendChild(heading); + const itemsEl = document.createElement('div'); + itemsEl.className = 'diagram-sidebar-items'; + group.categories.forEach(cat => { const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'diagram-sidebar-btn'; if (cat === activeCategory) btn.classList.add('is-active'); - btn.textContent = cat; + btn.innerHTML = ` + + ${cat} + `; btn.addEventListener('click', () => { activeCategory = cat; renderSidebar(); renderGrid(); }); - groupEl.appendChild(btn); + itemsEl.appendChild(btn); }); + groupEl.appendChild(itemsEl); + sidebar.appendChild(groupEl); }); } diff --git a/styles.css b/styles.css index 2eef166a..5c11af99 100644 --- a/styles.css +++ b/styles.css @@ -5454,57 +5454,116 @@ html[data-theme="dark"] .d2-diagram>svg:not([data-diagram-native-dark="true"]) { } .diagram-modal-sidebar { - width: 220px; - border-right: 1px solid var(--border-color); - padding: 14px 10px; + width: 260px; + margin: 16px 0 16px 16px; + border: 1px solid var(--border-color); + border-radius: 8px; + background: var(--bg-color); + padding: 0; overflow-y: auto; display: flex; flex-direction: column; - gap: 14px; + gap: 0; flex-shrink: 0; } .diagram-sidebar-group { display: flex; flex-direction: column; - gap: 3px; + border-top: 1px solid var(--border-color); } -.diagram-sidebar-group-title { - padding: 0 10px 4px; - color: var(--text-muted, #6b7280); - font-size: 0.76rem; - font-weight: 600; - letter-spacing: 0; - line-height: 1.2; +.diagram-sidebar-group:first-child { + border-top: none; } +.diagram-sidebar-group-header, .diagram-sidebar-btn { - display: flex; - align-items: center; - gap: 10px; - padding: 9px 12px; + width: 100%; border: none; background: transparent; color: var(--text-color); - text-align: left; - border-radius: 6px; cursor: pointer; - font-size: 0.9rem; - font-weight: 500; + font-size: 0.95rem; + text-align: left; transition: background-color 0.15s ease, color 0.15s ease; } +.diagram-sidebar-group-header { + display: grid; + grid-template-columns: 24px 1fr 18px; + align-items: center; + gap: 12px; + min-height: 62px; + padding: 0 18px; + font-weight: 500; +} + +.diagram-sidebar-group-header:hover { + background-color: var(--button-hover-bg, rgba(120, 120, 120, 0.06)); +} + +.diagram-sidebar-group-icon, +.diagram-sidebar-item-icon, +.diagram-sidebar-chevron { + display: inline-flex; + align-items: center; + justify-content: center; + line-height: 1; +} + +.diagram-sidebar-group-icon { + color: var(--text-color); + font-size: 1.1rem; +} + +.diagram-sidebar-chevron { + justify-self: end; + color: var(--text-muted, #6b7280); + font-size: 0.85rem; +} + +.diagram-sidebar-items { + display: none; + flex-direction: column; + gap: 4px; + padding: 0 12px 12px; +} + +.diagram-sidebar-group.is-expanded .diagram-sidebar-items { + display: flex; +} + +.diagram-sidebar-btn { + display: flex; + align-items: center; + gap: 14px; + min-height: 50px; + padding: 0 16px 0 20px; + border-radius: 7px; + font-weight: 500; +} + .diagram-sidebar-btn:hover { - background-color: var(--button-hover-bg, rgba(120, 120, 120, 0.08)); + background-color: var(--button-hover-bg, rgba(120, 120, 120, 0.06)); } .diagram-sidebar-btn.is-active { - background-color: color-mix(in srgb, var(--accent-color, #0076ff) 12%, transparent); + background-color: color-mix(in srgb, var(--accent-color, #0076ff) 13%, transparent); color: var(--accent-color, #0076ff); font-weight: 650; } +.diagram-sidebar-btn.is-active .diagram-sidebar-item-icon { + color: var(--accent-color, #0076ff); +} + +.diagram-sidebar-item-icon { + width: 22px; + color: var(--text-muted, #6b7280); + font-size: 1.05rem; +} + .diagram-modal-content { flex: 1; display: flex; @@ -5750,7 +5809,7 @@ html[data-theme="dark"] .diagram-preview-container { display: none !important; } -@media (max-width: 768px) { +@media (max-width: 640px) { .diagram-modal-body { flex-direction: column; } @@ -5758,13 +5817,17 @@ html[data-theme="dark"] .diagram-preview-container { .diagram-modal-sidebar { width: 100%; height: 60px; + margin: 0; flex-direction: row; border-right: none; border-bottom: 1px solid var(--border-color); + border-left: none; + border-radius: 0; padding: 8px; + gap: 6px; } - .diagram-sidebar-group-title { + .diagram-sidebar-group-header { display: none; } @@ -5772,6 +5835,17 @@ html[data-theme="dark"] .diagram-preview-container { display: contents; } + .diagram-sidebar-items { + display: contents; + } + + .diagram-sidebar-btn { + width: auto; + min-height: 36px; + flex-shrink: 0; + padding: 0 12px; + } + .diagram-modal-box { height: 95vh; }