UI-Konsistenz: shared BarControls + Tabellen-Look fuer Panels
Pill-basierte Toolbar-Primitiven aus OberleisteApp extrahiert nach src/components/BarControls.jsx — BarCombo (Dropdown), BarButton (Icon-Button), BarToggle (Label/Icon mit Active-State), BAR_H=22. OberleisteApp nutzt jetzt die geteilten Komponenten (Verhalten unveraendert). EbenenManager + GeschossManager: - Sichtbarkeits-Toolbar: native <select> + btn-icon-sm → BarCombo (mit visibility-Icon links) + BarButton add/settings. - GeschossManager Stift-Icon (edit) → Settings-Icon. - Zeilen-Layout: eckig statt Pill (margin 0, borderRadius 0, 3px Accent-Strip links fuer aktive Zeile), minHeight 24, gap 4, kompaktere Padding/Icon-Sizes — Vectorworks-naeher. DimensionenApp: - Welt/CPlane: 2x BarToggle statt btn-contained/outlined - Z-Selektor: 3x BarToggle (icon-only) - Drehen-Apply + 90°-CCW/CW: BarButton mit rotate_*-Icons (4 Preset-Buttons -90/-45/45/90 ersetzt durch 2 schnelle 90°-Buttons — passt besser in die schmale Sidebar) README aktualisiert: Runtime jetzt CPython 3.9, TextEntity-RTF-Limit dokumentiert, BarControls + text_editor/text_create erwaehnt. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useState } from 'react'
|
||||
import Icon from './Icon'
|
||||
import ContextMenu from './ContextMenu'
|
||||
import { BarCombo, BarButton } from './BarControls'
|
||||
import { openGeschossSettings, openGeschossDialog } from '../lib/rhinoBridge'
|
||||
|
||||
function GeschossBadge({ name }) {
|
||||
@@ -46,31 +47,32 @@ function ZeichnungsebeneRow({
|
||||
onClick={onClick}
|
||||
onContextMenu={onContextMenu}
|
||||
style={{
|
||||
display: 'flex', alignItems: 'center', gap: 6,
|
||||
padding: '4px 12px',
|
||||
margin: active ? '1px 6px' : '0',
|
||||
display: 'flex', alignItems: 'center', gap: 4,
|
||||
padding: '1px 12px',
|
||||
margin: 0,
|
||||
background: active ? 'var(--active-dim)' : 'var(--bg-item)',
|
||||
borderRadius: active ? 999 : 0,
|
||||
borderLeft: active ? 'none' : '3px solid transparent',
|
||||
borderBottom: active ? 'none' : '1px solid var(--border-light)',
|
||||
boxShadow: active ? 'inset 0 0 0 1px var(--active-light)' : 'none',
|
||||
borderRadius: 0,
|
||||
borderLeft: '3px solid ' + (active ? 'var(--accent)' : 'transparent'),
|
||||
borderBottom: '1px solid var(--border-light)',
|
||||
cursor: 'pointer',
|
||||
userSelect: 'none',
|
||||
minHeight: 24,
|
||||
}}
|
||||
>
|
||||
<button
|
||||
className={`btn-icon-sm ${eyeOn ? 'is-on' : ''}`}
|
||||
onClick={(ev) => { ev.stopPropagation(); onToggleVisible() }}
|
||||
title={eyeTitle}
|
||||
style={{ opacity: eyeOpacity }}
|
||||
><Icon name={eyeIcon} size={14} /></button>
|
||||
style={{ opacity: eyeOpacity, width: 16, height: 16 }}
|
||||
><Icon name={eyeIcon} size={12} /></button>
|
||||
|
||||
<span style={{
|
||||
fontWeight: active ? 700 : 500,
|
||||
fontSize: 12,
|
||||
fontSize: 11,
|
||||
color: active ? 'var(--active-light)' : 'var(--text-label)',
|
||||
flex: 1, minWidth: 0,
|
||||
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
||||
lineHeight: 1.2,
|
||||
}}>{z.name}</span>
|
||||
|
||||
{isGeschoss && (
|
||||
@@ -88,24 +90,25 @@ function ZeichnungsebeneRow({
|
||||
title={z.hasClipping
|
||||
? 'Clipping Plane ausschalten'
|
||||
: 'Clipping Plane einschalten (Schnitt auf Schnitthöhe)'}
|
||||
style={{ color: z.hasClipping ? 'var(--accent)' : undefined }}
|
||||
><Icon name="content_cut" size={12} /></button>
|
||||
style={{ color: z.hasClipping ? 'var(--accent)' : undefined, width: 14, height: 14 }}
|
||||
><Icon name="content_cut" size={11} /></button>
|
||||
) : (
|
||||
<span style={{ width: 18, flexShrink: 0 }} />
|
||||
<span style={{ width: 14, flexShrink: 0 }} />
|
||||
)}
|
||||
|
||||
<button
|
||||
className="btn-icon-xs"
|
||||
onClick={(ev) => { ev.stopPropagation(); onToggleLock() }}
|
||||
title={z.locked ? 'Entsperren' : 'Sperren'}
|
||||
style={{ color: z.locked ? 'var(--warn)' : undefined }}
|
||||
><Icon name={z.locked ? 'lock' : 'lock_open'} size={12} /></button>
|
||||
style={{ color: z.locked ? 'var(--warn)' : undefined, width: 14, height: 14 }}
|
||||
><Icon name={z.locked ? 'lock' : 'lock_open'} size={11} /></button>
|
||||
|
||||
<button
|
||||
className="btn-icon-xs"
|
||||
onClick={(ev) => { ev.stopPropagation(); onDelete() }}
|
||||
title="Löschen"
|
||||
><Icon name="close" size={12} /></button>
|
||||
style={{ width: 14, height: 14 }}
|
||||
><Icon name="close" size={11} /></button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -215,21 +218,20 @@ export default function GeschossManager({
|
||||
}}>
|
||||
<span className="label-xs">Sichtbarkeit</span>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<select
|
||||
value={mode}
|
||||
onChange={ev => onModeChange(ev.target.value)}
|
||||
style={{ flex: 1, minWidth: 0 }}
|
||||
>
|
||||
{MODES.map(m => (
|
||||
<option key={m.value} value={m.value}>{m.label}</option>
|
||||
))}
|
||||
</select>
|
||||
<button className="btn-icon-sm" onClick={addQuick} title="Zeichnungsebene hinzufügen">
|
||||
<Icon name="add" size={14} />
|
||||
</button>
|
||||
<button className="btn-icon-sm" onClick={() => openGeschossDialog(zeichnungsebenen)} title="Bearbeiten">
|
||||
<Icon name="edit" size={13} />
|
||||
</button>
|
||||
<div style={{ flex: 1, minWidth: 0, display: 'flex' }}>
|
||||
<BarCombo
|
||||
icon="visibility"
|
||||
value={mode}
|
||||
onChange={onModeChange}
|
||||
title="Sichtbarkeits-Modus"
|
||||
>
|
||||
{MODES.map(m => (
|
||||
<option key={m.value} value={m.value}>{m.label}</option>
|
||||
))}
|
||||
</BarCombo>
|
||||
</div>
|
||||
<BarButton icon="add" onClick={addQuick} title="Zeichnungsebene hinzufügen" />
|
||||
<BarButton icon="settings" onClick={() => openGeschossDialog(zeichnungsebenen)} title="Einstellungen" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user