- {/* ===== V2 TOOLS (Task A4.13/A4.14: Standard aktiv — Opt-out via VITE_TOOL_DISPATCHER=legacy) ===== */}
- {activeTab === 'canvas' && V2_TOOLS_ENABLED && (
-
- V2:
- {pluginRegistry.getToolsV2()
- .filter((tool) => uiMode === 'pro' || (tool.manifest.tags ?? []).includes('basic'))
- .map((tool) => {
- const isActive = onIsV2ToolActive?.(tool.manifest.id);
- return (
-
- );
- })}
-
- )}
{/* ===== START TAB ===== */}
{activeTab === 'start' && (
<>
-
+
-
Datei
-
-
-
onAction('undo')}>
-
- Undo
+
+ Rückgängig
onAction('redo')}>
-
- Redo
+
+ Wiederherstellen
onAction('copy')}>
-
+
Kopieren
onAction('paste')}>
-
+
Einfügen
onAction('group')}>
-
+
Gruppieren
onAction('ungroup')}>
-
+
Degruppieren
@@ -139,198 +147,72 @@ const RibbonBar: React.FC
= ({
>
)}
- {/* ===== INSERT TAB ===== */}
- {activeTab === 'insert' && (
- <>
-
-
-
onAction('insert-line')}>
-
- Linie
-
-
onAction('insert-rect')}>
-
- Rechteck
-
-
onAction('insert-circle')}>
-
- Kreis
-
-
onAction('insert-text')}>
-
- Text
-
-
onAction('insert-freehand')}>
-
- Freihand
-
-
-
Formen
-
-
-
-
-
-
-
onAction('background-import')}>
-
- Hintergrund
-
-
onAction('insert-image')}>
-
- Bild
-
-
-
Objekt
-
- >
+ {/* ===== ZEICHNEN TAB ===== */}
+ {activeTab === 'draw' && V2_TOOLS_ENABLED && (
+
+ {renderV2Group('canvas')}
+ {renderV2Group('format')}
+ {renderV2Group('insert')}
+
)}
- {/* ===== FORMAT TAB ===== */}
- {activeTab === 'format' && (
- <>
-
-
-
onAction('format-stroke-width')}>
-
- Linienstärke
-
-
onAction('format-stroke-color')}>
-
- Linienfarbe
-
-
onAction('format-fill-color')}>
-
- Füllfarbe
-
-
onAction('format-stroke-style')}>
-
- Linientyp
-
-
-
Stil
-
-
-
-
-
-
- onAction('format-align-left')}>
-
- Links
-
- onAction('format-align-center')}>
-
- Zentriert
-
- onAction('format-align-right')}>
-
- Rechts
-
-
-
Ausrichtung
-
- >
- )}
-
- {/* ===== VIEW TAB ===== */}
+ {/* ===== ANSICHT TAB ===== */}
{activeTab === 'view' && (
<>
onAction('zoom-fit')}>
-
+
Zoom Fit
onAction('zoom-100')}>
-
100%
-
onAction('grid')}>
-
- Grid
+ onAction('grid')}>
+
+ Raster
onAction('layer')}>
-
+
Layer
Ansicht
- >
- )}
-
- {/* ===== CANVAS TAB ===== */}
- {activeTab === 'canvas' && (
- <>
-
-
- onCanvasBgColorChange?.(e.target.value)}
- />
-
-
Hintergrund
-
-
-
- onGridColorChange?.(e.target.value)}
- />
-
-
Gitter
-
+
onAction('background-import')}>
+
+ Hintergrund
+
+
onAction('insert-image')}>
+
+ Bild
+
-
Farben
+
Hintergrund
-
-
-
- >
- )}
-
- {/* ===== TOOLS TAB ===== */}
- {activeTab === 'tools' && (
- <>
-
onAction('measure')}>
-
- Messen
-
-
onAction('plugins')}>
-
- Plugins
-
-
onAction('history')}>
-
+ onAction('history')}>
+
Historie
onAction('guests')}>
-
+
Gäste
@@ -344,18 +226,9 @@ const RibbonBar: React.FC
= ({
<>
-
onAction('ki')}>
-
- KI Copilot
-
-
onAction('ki-draw')}>
-
- KI Zeichnen
-
-
onAction('ki-analyze')}>
-
- KI Analysieren
-
+
+ KI Copilot — Befehle über die Befehlszeile unten (Strg+K)
+
Künstliche Intelligenz
diff --git a/frontend/src/styles.css b/frontend/src/styles.css
index eac729a..ae5c1e7 100644
--- a/frontend/src/styles.css
+++ b/frontend/src/styles.css
@@ -3077,3 +3077,46 @@ body.drawer-open { overflow: hidden; }
color: #fff;
border-color: rgba(255, 255, 255, 0.3);
}
+
+/* ─── CAD-10: Zeichnen-Tab V2-Buttons ─── */
+.ribbon-draw-content {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 4px;
+ padding: 4px 0;
+ width: 100%;
+}
+.ribbon-v2-btn {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 2px;
+ min-width: 52px;
+ padding: 6px 8px;
+ background: transparent;
+ border: 1px solid transparent;
+ border-radius: 6px;
+ cursor: pointer;
+ color: var(--color-text, #d0d0d0);
+}
+.ribbon-v2-btn:hover {
+ background: rgba(255, 255, 255, 0.06);
+ border-color: rgba(255, 255, 255, 0.12);
+}
+.ribbon-v2-btn.active {
+ background: rgba(74, 144, 217, 0.15);
+ border-color: rgba(74, 144, 217, 0.5);
+}
+.ribbon-v2-icon {
+ font-size: 14px;
+ line-height: 1;
+}
+.ribbon-v2-label {
+ font-size: 9px;
+ color: var(--color-text-secondary, #9aa0a6);
+ text-align: center;
+ white-space: nowrap;
+}
+.ribbon-v2-btn.active .ribbon-v2-label {
+ color: #4a90d9;
+}
diff --git a/frontend/src/types/ui.types.ts b/frontend/src/types/ui.types.ts
index 00e189a..7a707c5 100644
--- a/frontend/src/types/ui.types.ts
+++ b/frontend/src/types/ui.types.ts
@@ -9,7 +9,7 @@ import type { UserCursor } from '../crdt';
import type { UnitType } from '../utils/format';
export type ViewMode = '2d' | 'iso' | 'front' | 'top';
-export type RibbonTab = 'start' | 'insert' | 'format' | 'view' | 'canvas' | 'tools' | 'ki';
+export type RibbonTab = 'start' | 'draw' | 'view' | 'ki';
export type RightPanel = 'tool' | 'layer' | 'library' | 'ki';
export type Theme = 'light' | 'dark';
export type DrawerTab = 'tool' | 'layer' | 'library' | 'ki';
diff --git a/frontend/tests/Components.test.tsx b/frontend/tests/Components.test.tsx
index a9e906c..095598b 100644
--- a/frontend/tests/Components.test.tsx
+++ b/frontend/tests/Components.test.tsx
@@ -59,9 +59,9 @@ describe('RibbonBar', () => {
it('should call onTabChange when clicking a tab', () => {
const onTabChange = vi.fn();
render( {}} />);
- // Click the 'Format' tab (unique text)
- fireEvent.click(screen.getByText('Format'));
- expect(onTabChange).toHaveBeenCalledWith('format');
+ // CAD-10: Klick auf 'Zeichnen'
+ fireEvent.click(screen.getByText('Zeichnen'));
+ expect(onTabChange).toHaveBeenCalledWith('draw');
});
it('should call onAction when clicking an action button', () => {
diff --git a/frontend/tests/uiMode.test.tsx b/frontend/tests/uiMode.test.tsx
index 9ecdf26..57c0674 100644
--- a/frontend/tests/uiMode.test.tsx
+++ b/frontend/tests/uiMode.test.tsx
@@ -70,12 +70,12 @@ describe('H1: RibbonBar simple-Filter', () => {
registerBuiltinPlugins();
pluginRegistry.initDefaults();
const RibbonBar = (await import('../src/components/RibbonBar')).default;
- render( {}} onAction={() => {}} />);
+ render( {}} onAction={() => {}} />);
const all = screen.getAllByRole('button').length;
expect(all).toBeGreaterThan(10);
cleanup();
setUIMode('simple');
- render( {}} onAction={() => {}} />);
+ render( {}} onAction={() => {}} />);
const simpleCount = screen.getAllByRole('button').length;
expect(simpleCount).toBeLessThan(all);
expect(simpleCount).toBeGreaterThan(0);
@@ -88,7 +88,7 @@ describe('H1: RibbonBar simple-Filter', () => {
registerBuiltinPlugins();
pluginRegistry.initDefaults();
const RibbonBar = (await import('../src/components/RibbonBar')).default;
- render( {}} onAction={() => {}} />);
+ render( {}} onAction={() => {}} />);
const html = document.body.innerHTML;
expect(html).toContain('data-v2tool="line"');
expect(html).not.toContain('data-v2tool="rotate"');