Tools + Elements: layout per display mode
- Symbol only ('icon'): uniform grid (square aligned tiles)
- Text / Symbol+Text: original ragged content-width pills that wrap freely
(flex-wrap), like before the grid redesign
- Container switches grid↔flex-wrap on mode; pill switches full-width↔auto
- Dropdown picks the layout: density grid for icons, readable pills for text
This commit is contained in:
+14
-10
@@ -29,8 +29,7 @@ function readTileMode() {
|
|||||||
function writeTileMode(m) {
|
function writeTileMode(m) {
|
||||||
try { localStorage.setItem(TILE_MODE_KEY, m) } catch { /* WebView ohne Storage */ }
|
try { localStorage.setItem(TILE_MODE_KEY, m) } catch { /* WebView ohne Storage */ }
|
||||||
}
|
}
|
||||||
const TILE_MIN_COL = { icon: 40, text: 64, both: 86 }
|
const ICON_GRID_MIN = 42 // min Spaltenbreite im reinen Symbol-Raster
|
||||||
const TILE_MIN_H = { icon: 32, text: 30, both: 32 }
|
|
||||||
|
|
||||||
function TileModeDropdown({ mode, onChange }) {
|
function TileModeDropdown({ mode, onChange }) {
|
||||||
return (
|
return (
|
||||||
@@ -82,6 +81,7 @@ function PillButton({ icon, label, hint, onClick, onContextMenu, disabled,
|
|||||||
hasMenu, badge, mode = 'both' }) {
|
hasMenu, badge, mode = 'both' }) {
|
||||||
const showIcon = mode !== 'text'
|
const showIcon = mode !== 'text'
|
||||||
const showLabel = mode !== 'icon'
|
const showLabel = mode !== 'icon'
|
||||||
|
const isGrid = mode === 'icon' // reines Symbol = gleichmaessiges Raster
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
@@ -91,10 +91,10 @@ function PillButton({ icon, label, hint, onClick, onContextMenu, disabled,
|
|||||||
style={{
|
style={{
|
||||||
display: 'flex', flexDirection: 'row',
|
display: 'flex', flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: mode === 'both' ? 'flex-start' : 'center',
|
justifyContent: isGrid ? 'center' : 'flex-start',
|
||||||
gap: showIcon && showLabel ? 7 : 0,
|
gap: showIcon && showLabel ? 7 : 0,
|
||||||
padding: mode === 'icon' ? '6px' : '5px 11px',
|
padding: isGrid ? '7px' : '5px 11px',
|
||||||
minHeight: TILE_MIN_H[mode],
|
minHeight: isGrid ? 34 : 30,
|
||||||
background: 'var(--bg-input)',
|
background: 'var(--bg-input)',
|
||||||
border: '1px solid var(--border-light)',
|
border: '1px solid var(--border-light)',
|
||||||
borderRadius: 999,
|
borderRadius: 999,
|
||||||
@@ -104,7 +104,8 @@ function PillButton({ icon, label, hint, onClick, onContextMenu, disabled,
|
|||||||
fontSize: 11, fontWeight: 500,
|
fontSize: 11, fontWeight: 500,
|
||||||
color: 'var(--text-primary)',
|
color: 'var(--text-primary)',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
width: '100%',
|
width: isGrid ? '100%' : 'auto',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
appearance: 'none', WebkitAppearance: 'none',
|
appearance: 'none', WebkitAppearance: 'none',
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => { if (!disabled) {
|
onMouseEnter={(e) => { if (!disabled) {
|
||||||
@@ -117,7 +118,7 @@ function PillButton({ icon, label, hint, onClick, onContextMenu, disabled,
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{showIcon && (
|
{showIcon && (
|
||||||
<Icon name={icon} size={16}
|
<Icon name={icon} size={isGrid ? 18 : 16}
|
||||||
style={{ color: 'var(--accent)', flexShrink: 0 }} />
|
style={{ color: 'var(--accent)', flexShrink: 0 }} />
|
||||||
)}
|
)}
|
||||||
{showLabel && (
|
{showLabel && (
|
||||||
@@ -150,8 +151,9 @@ function PillButton({ icon, label, hint, onClick, onContextMenu, disabled,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kategorie-Gruppe: Label + einheitliches Raster (auto-fill Spalten)
|
// Kategorie-Gruppe: Symbol-Modus = Raster, sonst frei umbrechende Pills
|
||||||
function PillGroup({ label, mode = 'both', children }) {
|
function PillGroup({ label, mode = 'both', children }) {
|
||||||
|
const isGrid = mode === 'icon'
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
|
||||||
<span style={{
|
<span style={{
|
||||||
@@ -161,10 +163,12 @@ function PillGroup({ label, mode = 'both', children }) {
|
|||||||
}}>
|
}}>
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
<div style={{
|
<div style={isGrid ? {
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateColumns: `repeat(auto-fill, minmax(${TILE_MIN_COL[mode]}px, 1fr))`,
|
gridTemplateColumns: `repeat(auto-fill, minmax(${ICON_GRID_MIN}px, 1fr))`,
|
||||||
gap: 5,
|
gap: 5,
|
||||||
|
} : {
|
||||||
|
display: 'flex', flexWrap: 'wrap', gap: 5,
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+13
-8
@@ -12,8 +12,7 @@ function readTileMode() {
|
|||||||
function writeTileMode(m) {
|
function writeTileMode(m) {
|
||||||
try { localStorage.setItem(TILE_MODE_KEY, m) } catch { /* WebView ohne Storage */ }
|
try { localStorage.setItem(TILE_MODE_KEY, m) } catch { /* WebView ohne Storage */ }
|
||||||
}
|
}
|
||||||
const TILE_MIN_COL = { icon: 40, text: 64, both: 86 }
|
const ICON_GRID_MIN = 42 // min Spaltenbreite im reinen Symbol-Raster
|
||||||
const TILE_MIN_H = { icon: 32, text: 30, both: 32 }
|
|
||||||
|
|
||||||
// Tool-Definitionen: [icon, label, rhino-command, tooltip]
|
// Tool-Definitionen: [icon, label, rhino-command, tooltip]
|
||||||
// Material-Symbol-Namen siehe https://fonts.google.com/icons
|
// Material-Symbol-Namen siehe https://fonts.google.com/icons
|
||||||
@@ -68,6 +67,7 @@ const TOOLS = {
|
|||||||
function ToolTile({ icon, label, cmd, tip, mode }) {
|
function ToolTile({ icon, label, cmd, tip, mode }) {
|
||||||
const showIcon = mode !== 'text'
|
const showIcon = mode !== 'text'
|
||||||
const showLabel = mode !== 'icon'
|
const showLabel = mode !== 'icon'
|
||||||
|
const isGrid = mode === 'icon' // reines Symbol = gleichmaessiges Raster
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
onClick={() => runRhinoCommand(cmd)}
|
onClick={() => runRhinoCommand(cmd)}
|
||||||
@@ -83,10 +83,11 @@ function ToolTile({ icon, label, cmd, tip, mode }) {
|
|||||||
style={{
|
style={{
|
||||||
display: 'flex', flexDirection: 'row',
|
display: 'flex', flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: mode === 'both' ? 'flex-start' : 'center',
|
justifyContent: isGrid ? 'center' : 'flex-start',
|
||||||
gap: showIcon && showLabel ? 7 : 0,
|
gap: showIcon && showLabel ? 7 : 0,
|
||||||
padding: mode === 'icon' ? '6px' : '5px 11px',
|
padding: isGrid ? '7px' : '5px 11px',
|
||||||
minHeight: TILE_MIN_H[mode],
|
minHeight: isGrid ? 34 : 30,
|
||||||
|
width: isGrid ? '100%' : 'auto',
|
||||||
background: 'var(--bg-input)',
|
background: 'var(--bg-input)',
|
||||||
border: '1px solid var(--border-light)',
|
border: '1px solid var(--border-light)',
|
||||||
borderRadius: 999,
|
borderRadius: 999,
|
||||||
@@ -94,11 +95,12 @@ function ToolTile({ icon, label, cmd, tip, mode }) {
|
|||||||
transition: 'background 0.12s, border-color 0.12s',
|
transition: 'background 0.12s, border-color 0.12s',
|
||||||
fontSize: 11, fontWeight: 500,
|
fontSize: 11, fontWeight: 500,
|
||||||
color: 'var(--text-primary)',
|
color: 'var(--text-primary)',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
appearance: 'none', WebkitAppearance: 'none',
|
appearance: 'none', WebkitAppearance: 'none',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{showIcon && (
|
{showIcon && (
|
||||||
<Icon name={icon} size={16}
|
<Icon name={icon} size={isGrid ? 18 : 16}
|
||||||
style={{ color: 'var(--accent)', flexShrink: 0 }} />
|
style={{ color: 'var(--accent)', flexShrink: 0 }} />
|
||||||
)}
|
)}
|
||||||
{showLabel && (
|
{showLabel && (
|
||||||
@@ -112,6 +114,7 @@ function ToolTile({ icon, label, cmd, tip, mode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function GridSection({ label, mode, children }) {
|
function GridSection({ label, mode, children }) {
|
||||||
|
const isGrid = mode === 'icon'
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
|
||||||
<span style={{
|
<span style={{
|
||||||
@@ -121,10 +124,12 @@ function GridSection({ label, mode, children }) {
|
|||||||
}}>
|
}}>
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
<div style={{
|
<div style={isGrid ? {
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateColumns: `repeat(auto-fill, minmax(${TILE_MIN_COL[mode]}px, 1fr))`,
|
gridTemplateColumns: `repeat(auto-fill, minmax(${ICON_GRID_MIN}px, 1fr))`,
|
||||||
gap: 5,
|
gap: 5,
|
||||||
|
} : {
|
||||||
|
display: 'flex', flexWrap: 'wrap', gap: 5,
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user