fix: mobile UI — hamburger onClick, right-tab-bar, drawer content, topbar buttons
- Topbar: hamburger button opens left drawer (was no onClick) - Topbar: project name navigates back to dashboard - Topbar: Versionen/Teilen/Hilfe/Benachrichtigungen get placeholder handlers - App.tsx: render right-tab-bar with 4 tab buttons (tool/layer/library/ki) - App.tsx: pass LeftSidebar as leftContent to MobileDrawers - App.tsx: pass RightSidebar as rightContent to MobileDrawers - MobileDrawers: accept leftContent/rightContent ReactNode props - MobileDrawers: render sidebar content in drawer bodies (was empty) - ui.types.ts: add onOpenLeftDrawer, onNavigateBack to TopbarProps - ui.types.ts: add leftContent, rightContent to MobileDrawersProps Test: 343/343 pass, tsc clean, build succeeds
This commit is contained in:
@@ -55,6 +55,13 @@ const initialKIMessages: KIMessage[] = [
|
|||||||
{ id: 'ki-1', role: 'assistant', content: 'Hallo! Ich bin der KI Copilot. Wie kann ich helfen?' },
|
{ id: 'ki-1', role: 'assistant', content: 'Hallo! Ich bin der KI Copilot. Wie kann ich helfen?' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const rightTabItems: Array<{ id: DrawerTab; label: string; svg: React.ReactNode }> = [
|
||||||
|
{ id: 'tool', label: 'Wz', svg: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg> },
|
||||||
|
{ id: 'layer', label: 'Layer', svg: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg> },
|
||||||
|
{ id: 'library', label: 'Lib', svg: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h7a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg> },
|
||||||
|
{ id: 'ki', label: 'KI', svg: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/></svg> },
|
||||||
|
];
|
||||||
|
|
||||||
const initialKISuggestions: KISuggestion[] = [
|
const initialKISuggestions: KISuggestion[] = [
|
||||||
{ id: 'sug-1', label: 'Bestuhlung automatisch generieren' },
|
{ id: 'sug-1', label: 'Bestuhlung automatisch generieren' },
|
||||||
{ id: 'sug-2', label: 'Maße analysieren' },
|
{ id: 'sug-2', label: 'Maße analysieren' },
|
||||||
@@ -938,6 +945,8 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
|
|||||||
onRedo={handleRedo}
|
onRedo={handleRedo}
|
||||||
onThemeToggle={handleThemeToggle}
|
onThemeToggle={handleThemeToggle}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
|
onOpenLeftDrawer={() => setMobileLeftOpen(true)}
|
||||||
|
onNavigateBack={onNavigateBack}
|
||||||
/>
|
/>
|
||||||
<RibbonBar
|
<RibbonBar
|
||||||
activeTab={activeRibbonTab}
|
activeTab={activeRibbonTab}
|
||||||
@@ -1034,6 +1043,14 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
|
|||||||
onToggleGrid={handleToggleGrid}
|
onToggleGrid={handleToggleGrid}
|
||||||
seatCount={seatCount}
|
seatCount={seatCount}
|
||||||
/>
|
/>
|
||||||
|
<div className="right-tab-bar">
|
||||||
|
{rightTabItems.map(tab => (
|
||||||
|
<button key={tab.id} className={`right-tab-btn${activeDrawerTab === tab.id ? ' active' : ''}`} onClick={() => { setActiveDrawerTab(tab.id); setMobileRightOpen(true); }}>
|
||||||
|
{tab.svg}
|
||||||
|
<span>{tab.label}</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
<MobileDrawers
|
<MobileDrawers
|
||||||
leftOpen={mobileLeftOpen}
|
leftOpen={mobileLeftOpen}
|
||||||
rightOpen={mobileRightOpen}
|
rightOpen={mobileRightOpen}
|
||||||
@@ -1041,6 +1058,47 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
|
|||||||
onCloseLeft={() => setMobileLeftOpen(false)}
|
onCloseLeft={() => setMobileLeftOpen(false)}
|
||||||
onCloseRight={() => setMobileRightOpen(false)}
|
onCloseRight={() => setMobileRightOpen(false)}
|
||||||
onRightTabChange={setActiveDrawerTab}
|
onRightTabChange={setActiveDrawerTab}
|
||||||
|
leftContent={
|
||||||
|
<LeftSidebar
|
||||||
|
activeTool={activeTool}
|
||||||
|
onToolChange={handleToolChange}
|
||||||
|
selectedTemplate={selectedTemplate}
|
||||||
|
onTemplateSelect={handleTemplateSelect}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightContent={
|
||||||
|
<RightSidebar
|
||||||
|
activePanel={activeDrawerTab}
|
||||||
|
onPanelChange={(p) => setActiveDrawerTab(p as DrawerTab)}
|
||||||
|
selectedElement={selectedElement}
|
||||||
|
layers={layers}
|
||||||
|
blocks={blocks}
|
||||||
|
activeLayerId={activeLayerId}
|
||||||
|
onSelectLayer={handleSelectLayer}
|
||||||
|
onAddLayer={handleAddLayer}
|
||||||
|
onToggleLayer={handleToggleLayer}
|
||||||
|
onDeleteLayer={handleDeleteLayer}
|
||||||
|
onRenameLayer={handleRenameLayer}
|
||||||
|
onDuplicateLayer={handleDuplicateLayer}
|
||||||
|
onToggleLock={handleToggleLock}
|
||||||
|
onElementsDeleted={handleElementsDeleted}
|
||||||
|
onToggleElementVisible={handleToggleElementVisible}
|
||||||
|
elements={elements}
|
||||||
|
onRenameBlock={handleRenameBlock}
|
||||||
|
onDuplicateBlock={handleDuplicateBlock}
|
||||||
|
onDeleteBlock={handleDeleteBlock}
|
||||||
|
onSvgImport={handleSvgImport}
|
||||||
|
onSaveGroupAsBlock={handleSaveGroupAsBlock}
|
||||||
|
onBlockCategoryChange={handleBlockCategoryChange}
|
||||||
|
onBlockSearch={handleBlockSearch}
|
||||||
|
onDragBlock={handleDragBlock}
|
||||||
|
kiMessages={kiMessages}
|
||||||
|
kiSuggestions={kiSuggestions}
|
||||||
|
onKISend={handleKISend}
|
||||||
|
onKISuggestionClick={handleSuggestionClick}
|
||||||
|
kiLoading={kiLoading}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<BackgroundImport
|
<BackgroundImport
|
||||||
open={bgImportOpen}
|
open={bgImportOpen}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const drawerTabs: Array<{ id: DrawerTab; label: string; svg: React.ReactNode }>
|
|||||||
];
|
];
|
||||||
|
|
||||||
const MobileDrawers: React.FC<MobileDrawersProps> = ({
|
const MobileDrawers: React.FC<MobileDrawersProps> = ({
|
||||||
leftOpen, rightOpen, activeRightTab, onCloseLeft, onCloseRight, onRightTabChange,
|
leftOpen, rightOpen, activeRightTab, onCloseLeft, onCloseRight, onRightTabChange, leftContent, rightContent,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -23,7 +23,7 @@ const MobileDrawers: React.FC<MobileDrawersProps> = ({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="drawer-body" id="drawer-left-body">
|
<div className="drawer-body" id="drawer-left-body">
|
||||||
{/* Filled by LeftSidebar content on mobile */}
|
{leftContent}
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ const MobileDrawers: React.FC<MobileDrawersProps> = ({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="drawer-body" id="drawer-right-body">
|
<div className="drawer-body" id="drawer-right-body">
|
||||||
{/* Filled by panel content on mobile */}
|
{rightContent}
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { TopbarProps } from '../types/ui.types';
|
import type { TopbarProps } from '../types/ui.types';
|
||||||
|
|
||||||
const Topbar: React.FC<TopbarProps> = ({ projectName, savedStatus, onUndo, onRedo, onThemeToggle, theme, onOpenSettings }) => {
|
const Topbar: React.FC<TopbarProps> = ({ projectName, savedStatus, onUndo, onRedo, onThemeToggle, theme, onOpenSettings, onOpenLeftDrawer, onNavigateBack }) => {
|
||||||
return (
|
return (
|
||||||
<header className="topbar" role="banner">
|
<header className="topbar" role="banner">
|
||||||
<div className="topbar-left">
|
<div className="topbar-left">
|
||||||
<button className="hamburger-btn" aria-label="Werkzeuge öffnen">
|
<button className="hamburger-btn" aria-label="Werkzeuge öffnen" onClick={onOpenLeftDrawer}>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<div className="app-logo" aria-hidden="true">
|
<div className="app-logo" aria-hidden="true">
|
||||||
@@ -13,7 +13,7 @@ const Topbar: React.FC<TopbarProps> = ({ projectName, savedStatus, onUndo, onRed
|
|||||||
</div>
|
</div>
|
||||||
<span className="app-name">web-cad</span>
|
<span className="app-name">web-cad</span>
|
||||||
<span style={{ color: 'var(--color-border-strong)', margin: '0 4px' }}>|</span>
|
<span style={{ color: 'var(--color-border-strong)', margin: '0 4px' }}>|</span>
|
||||||
<button className="project-name" aria-label="Projekt wechseln">
|
<button className="project-name" aria-label="Projekt wechseln" onClick={onNavigateBack}>
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h7a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h7a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>
|
||||||
<span>{projectName}</span>
|
<span>{projectName}</span>
|
||||||
<svg className="caret" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>
|
<svg className="caret" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>
|
||||||
@@ -28,17 +28,17 @@ const Topbar: React.FC<TopbarProps> = ({ projectName, savedStatus, onUndo, onRed
|
|||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 15-6.7L21 13"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 15-6.7L21 13"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<span style={{ width: '1px', height: '20px', background: 'var(--color-border)', margin: '0 4px' }}></span>
|
<span style={{ width: '1px', height: '20px', background: 'var(--color-border)', margin: '0 4px' }}></span>
|
||||||
<button className="icon-btn-top" aria-label="Versionen" title="Versionsverlauf">
|
<button className="icon-btn-top" aria-label="Versionen" title="Versionsverlauf" onClick={() => console.log('Versionen clicked')}>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<button className="icon-btn-top" aria-label="Teilen" title="Projekt teilen">
|
<button className="icon-btn-top" aria-label="Teilen" title="Projekt teilen" onClick={() => console.log('Teilen clicked')}>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<span style={{ width: '1px', height: '20px', background: 'var(--color-border)', margin: '0 4px' }}></span>
|
<span style={{ width: '1px', height: '20px', background: 'var(--color-border)', margin: '0 4px' }}></span>
|
||||||
<button className="icon-btn-top" aria-label="Hell/Dunkel umschalten" title="Theme wechseln" onClick={onThemeToggle}>
|
<button className="icon-btn-top" aria-label="Hell/Dunkel umschalten" title="Theme wechseln" onClick={onThemeToggle}>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<button className="icon-btn-top" aria-label="Hilfe" title="Hilfe (F1)">
|
<button className="icon-btn-top" aria-label="Hilfe" title="Hilfe (F1)" onClick={() => console.log('Hilfe clicked')}>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<span style={{ width: '1px', height: '20px', background: 'var(--color-border)', margin: '0 4px' }}></span>
|
<span style={{ width: '1px', height: '20px', background: 'var(--color-border)', margin: '0 4px' }}></span>
|
||||||
@@ -46,7 +46,7 @@ const Topbar: React.FC<TopbarProps> = ({ projectName, savedStatus, onUndo, onRed
|
|||||||
<option value="de">DE</option>
|
<option value="de">DE</option>
|
||||||
<option value="en">EN</option>
|
<option value="en">EN</option>
|
||||||
</select>
|
</select>
|
||||||
<button className="icon-btn-top" aria-label="Benachrichtigungen" title="Benachrichtigungen">
|
<button className="icon-btn-top" aria-label="Benachrichtigungen" title="Benachrichtigungen" onClick={() => console.log('Benachrichtigungen clicked')}>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<button className="icon-btn-top" aria-label="Einstellungen" title="Einstellungen" onClick={onOpenSettings}>
|
<button className="icon-btn-top" aria-label="Einstellungen" title="Einstellungen" onClick={onOpenSettings}>
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ export interface TopbarProps {
|
|||||||
onThemeToggle: () => void;
|
onThemeToggle: () => void;
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
onOpenSettings?: () => void;
|
onOpenSettings?: () => void;
|
||||||
|
onOpenLeftDrawer?: () => void;
|
||||||
|
onNavigateBack?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SettingsModalProps {
|
export interface SettingsModalProps {
|
||||||
@@ -241,4 +243,6 @@ export interface MobileDrawersProps {
|
|||||||
onCloseLeft: () => void;
|
onCloseLeft: () => void;
|
||||||
onCloseRight: () => void;
|
onCloseRight: () => void;
|
||||||
onRightTabChange: (tab: DrawerTab) => void;
|
onRightTabChange: (tab: DrawerTab) => void;
|
||||||
|
leftContent?: React.ReactNode;
|
||||||
|
rightContent?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# Test Report — Mobile UI Fix
|
||||||
|
|
||||||
|
**Task:** Fix Mobile UI — Sidebars, Drawers, Tab-Bar, Button Handlers
|
||||||
|
**Date:** 2026-06-28
|
||||||
|
|
||||||
|
## Changes Summary
|
||||||
|
|
||||||
|
### Files Modified
|
||||||
|
1. `src/types/ui.types.ts` — Added `onOpenLeftDrawer` and `onNavigateBack` to `TopbarProps`; added `leftContent` and `rightContent` to `MobileDrawersProps`
|
||||||
|
2. `src/components/Topbar.tsx` — Added `onOpenLeftDrawer` and `onNavigateBack` to destructuring; wired `onClick` on hamburger button (→ `onOpenLeftDrawer`), project name button (→ `onNavigateBack`), Versionen/Teilen/Hilfe/Benachrichtigungen buttons (→ `console.log` placeholders)
|
||||||
|
3. `src/components/MobileDrawers.tsx` — Added `leftContent`/`rightContent` to destructuring; rendered `{leftContent}` and `{rightContent}` in drawer bodies replacing empty comments
|
||||||
|
4. `src/App.tsx` — Added `rightTabItems` constant array; passed `onOpenLeftDrawer` and `onNavigateBack` props to Topbar; rendered `<div className="right-tab-bar">` between StatusBar and MobileDrawers; passed `LeftSidebar` as `leftContent` and `RightSidebar` as `rightContent` to MobileDrawers
|
||||||
|
|
||||||
|
## Test Results
|
||||||
|
|
||||||
|
### TypeScript Check (`npx tsc --noEmit`)
|
||||||
|
```
|
||||||
|
EXIT_CODE=0
|
||||||
|
```
|
||||||
|
✅ Zero errors — clean type check
|
||||||
|
|
||||||
|
### Unit Tests (`npx vitest run`)
|
||||||
|
```
|
||||||
|
Test Files 13 passed (13)
|
||||||
|
Tests 343 passed (343)
|
||||||
|
Duration 19.10s
|
||||||
|
```
|
||||||
|
✅ 343/343 tests passed — no regressions
|
||||||
|
|
||||||
|
### Production Build (`npm run build`)
|
||||||
|
```
|
||||||
|
vite v5.4.21 building for production...
|
||||||
|
✓ 337 modules transformed.
|
||||||
|
dist/index.html 0.37 kB │ gzip: 0.27 kB
|
||||||
|
dist/assets/index-f2DS1W3w.css 46.87 kB │ gzip: 8.33 kB
|
||||||
|
dist/assets/index-Ch0HMxp1.js 922.38 kB │ gzip: 316.96 kB
|
||||||
|
✓ built in 6.98s
|
||||||
|
```
|
||||||
|
✅ Build succeeded
|
||||||
|
|
||||||
|
## Bug Fixes Implemented
|
||||||
|
|
||||||
|
| Bug | Description | Status |
|
||||||
|
|-----|-------------|--------|
|
||||||
|
| BUG 1 | Hamburger button has no onClick | ✅ Fixed — wired to `onOpenLeftDrawer` |
|
||||||
|
| BUG 2 | Right vertical tab bar not rendered | ✅ Fixed — `right-tab-bar` div rendered with tab buttons |
|
||||||
|
| BUG 3 | Drawer bodies are empty | ✅ Fixed — `leftContent`/`rightContent` rendered in drawer bodies |
|
||||||
|
| BUG 4 | Topbar buttons without onClick | ✅ Fixed — all buttons have onClick handlers |
|
||||||
|
|
||||||
|
## Smoke Test
|
||||||
|
- App builds and starts without runtime errors
|
||||||
|
- Hamburger button opens left drawer (onClick wired to `setMobileLeftOpen(true)`)
|
||||||
|
- Right-tab-bar buttons open right drawer and set active tab (onClick wired to `setActiveDrawerTab` + `setMobileRightOpen(true)`)
|
||||||
|
- Left drawer renders LeftSidebar content (tools)
|
||||||
|
- Right drawer renders RightSidebar content (layer/library/ki panels)
|
||||||
|
- Project name button navigates back to dashboard (onClick wired to `onNavigateBack`)
|
||||||
Reference in New Issue
Block a user