Tools + Elements: smaller tiles, display-mode dropdown, dark pill look
- Tiles shrunk (minHeight 46/38/30 per mode, tighter padding, smaller icons) - Add display-mode dropdown (Symbol / Text / Symbol+Text) at top of each panel; choice persists in localStorage under 'dossier_tile_mode' and is shared between both panels - Grid column min-width adapts per mode (icon 40 / text 66 / both 58) - Restore dark pill look: --bg-input background + border-light, full border-radius — tiles read as distinct chips again - Icon-only mode shows a small corner chevron on dropdown tiles (Treppe/Stuetze/Traeger) so the right-click menu stays discoverable
This commit is contained in:
+59
-21
@@ -1,9 +1,20 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// Copyright (C) 2026 Karim Gabriele Varano
|
||||
import { useEffect } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import Icon from './components/Icon'
|
||||
import { notifyReady, runRhinoCommand } from './lib/rhinoBridge'
|
||||
|
||||
// Anzeige-Modus der Kacheln, geteilt mit Elemente-Panel via localStorage.
|
||||
const TILE_MODE_KEY = 'dossier_tile_mode' // 'both' | 'icon' | 'text'
|
||||
function readTileMode() {
|
||||
try { return localStorage.getItem(TILE_MODE_KEY) || 'both' } catch { return 'both' }
|
||||
}
|
||||
function writeTileMode(m) {
|
||||
try { localStorage.setItem(TILE_MODE_KEY, m) } catch { /* WebView ohne Storage */ }
|
||||
}
|
||||
const TILE_MIN_COL = { icon: 40, text: 66, both: 58 }
|
||||
const TILE_MIN_H = { icon: 38, text: 30, both: 46 }
|
||||
|
||||
// Tool-Definitionen: [icon, label, rhino-command, tooltip]
|
||||
// Material-Symbol-Namen siehe https://fonts.google.com/icons
|
||||
const TOOLS = {
|
||||
@@ -54,7 +65,9 @@ const TOOLS = {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function ToolTile({ icon, label, cmd, tip }) {
|
||||
function ToolTile({ icon, label, cmd, tip, mode }) {
|
||||
const showIcon = mode !== 'text'
|
||||
const showLabel = mode !== 'icon'
|
||||
return (
|
||||
<button
|
||||
onClick={() => runRhinoCommand(cmd)}
|
||||
@@ -64,17 +77,17 @@ function ToolTile({ icon, label, cmd, tip }) {
|
||||
e.currentTarget.style.background = 'var(--bg-item-hover)'
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.borderColor = 'transparent'
|
||||
e.currentTarget.style.background = 'var(--bg-item)'
|
||||
e.currentTarget.style.borderColor = 'var(--border-light)'
|
||||
e.currentTarget.style.background = 'var(--bg-input)'
|
||||
}}
|
||||
style={{
|
||||
display: 'flex', flexDirection: 'column',
|
||||
alignItems: 'center', justifyContent: 'center', gap: 6,
|
||||
padding: '10px 4px',
|
||||
minHeight: 56,
|
||||
background: 'var(--bg-item)',
|
||||
border: '1px solid transparent',
|
||||
borderRadius: 10,
|
||||
alignItems: 'center', justifyContent: 'center', gap: 4,
|
||||
padding: '6px 4px',
|
||||
minHeight: TILE_MIN_H[mode],
|
||||
background: 'var(--bg-input)',
|
||||
border: '1px solid var(--border-light)',
|
||||
borderRadius: 999,
|
||||
cursor: 'pointer',
|
||||
transition: 'background 0.12s, border-color 0.12s',
|
||||
fontSize: 10, fontWeight: 500,
|
||||
@@ -82,18 +95,23 @@ function ToolTile({ icon, label, cmd, tip }) {
|
||||
appearance: 'none', WebkitAppearance: 'none',
|
||||
}}
|
||||
>
|
||||
<Icon name={icon} size={19} style={{ color: 'var(--accent)', flexShrink: 0 }} />
|
||||
<span style={{
|
||||
maxWidth: '100%', overflow: 'hidden',
|
||||
textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
||||
}}>{label}</span>
|
||||
{showIcon && (
|
||||
<Icon name={icon} size={mode === 'icon' ? 18 : 16}
|
||||
style={{ color: 'var(--accent)', flexShrink: 0 }} />
|
||||
)}
|
||||
{showLabel && (
|
||||
<span style={{
|
||||
maxWidth: '100%', overflow: 'hidden',
|
||||
textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
||||
}}>{label}</span>
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
function GridSection({ label, children }) {
|
||||
function GridSection({ label, mode, children }) {
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
|
||||
<span style={{
|
||||
fontSize: 9, color: 'var(--text-muted)',
|
||||
letterSpacing: '0.08em', textTransform: 'uppercase',
|
||||
@@ -103,8 +121,8 @@ function GridSection({ label, children }) {
|
||||
</span>
|
||||
<div style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fill, minmax(68px, 1fr))',
|
||||
gap: 6,
|
||||
gridTemplateColumns: `repeat(auto-fill, minmax(${TILE_MIN_COL[mode]}px, 1fr))`,
|
||||
gap: 5,
|
||||
}}>
|
||||
{children}
|
||||
</div>
|
||||
@@ -112,11 +130,28 @@ function GridSection({ label, children }) {
|
||||
)
|
||||
}
|
||||
|
||||
function TileModeDropdown({ mode, onChange }) {
|
||||
return (
|
||||
<select
|
||||
value={mode}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
title="Anzeige: Symbol / Text / Symbol + Text"
|
||||
style={{ fontSize: 10, padding: '3px 6px', maxWidth: 130 }}
|
||||
>
|
||||
<option value="icon">Symbol</option>
|
||||
<option value="text">Text</option>
|
||||
<option value="both">Symbol + Text</option>
|
||||
</select>
|
||||
)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export default function WerkzeugeApp() {
|
||||
const [mode, setMode] = useState(readTileMode)
|
||||
useEffect(() => { notifyReady() }, [])
|
||||
|
||||
const changeMode = (m) => { setMode(m); writeTileMode(m) }
|
||||
const groups = Object.entries(TOOLS)
|
||||
|
||||
return (
|
||||
@@ -129,10 +164,13 @@ export default function WerkzeugeApp() {
|
||||
boxSizing: 'border-box',
|
||||
overflowY: 'auto', overflowX: 'hidden',
|
||||
}}>
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<TileModeDropdown mode={mode} onChange={changeMode} />
|
||||
</div>
|
||||
{groups.map(([title, items]) => (
|
||||
<GridSection key={title} label={title}>
|
||||
<GridSection key={title} label={title} mode={mode}>
|
||||
{items.map(([icon, label, cmd, tip]) => (
|
||||
<ToolTile key={cmd} icon={icon} label={label} cmd={cmd} tip={tip} />
|
||||
<ToolTile key={cmd} icon={icon} label={label} cmd={cmd} tip={tip} mode={mode} />
|
||||
))}
|
||||
</GridSection>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user