Skip to content

Commit 1368775

Browse files
committed
Enhance visual hierarchy in ElementHierarchyTree with increased indentation and basic tree lines
1 parent 5117e4b commit 1368775

1 file changed

Lines changed: 57 additions & 6 deletions

File tree

src/components/HybridEditor/ElementHierarchyTree.tsx

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,53 @@ import { PatternLibraryElement } from '../../models/listingFlow';
3535
import { arePathsEqual } from '../../utils/pathUtils';
3636
import { getSubElements } from '../../context/EditorContext'; // Importiere getSubElements
3737

38-
const TreeItem = styled(ListItem)<{ depth: number; isSelected: boolean }>`
39-
padding-left: ${props => props.depth * 16 + 8}px;
38+
const LINE_COLOR = 'rgba(0, 0, 0, 0.23)'; // Farbe für die Verbindungslinien, ähnlich wie Divider
39+
40+
const TreeItem = styled(ListItem)<{ depth: number; isSelected: boolean; isLastChild?: boolean; hasChildren?: boolean }>`
41+
padding-left: ${props => props.depth * 20 + 8}px; // Erhöhte Einrückung
4042
background-color: ${props => props.isSelected ? 'rgba(0, 159, 100, 0.1)' : 'transparent'};
4143
border-left: ${props => props.isSelected ? '3px solid #009F64' : '3px solid transparent'};
44+
position: relative; // Für Pseudoelemente
45+
46+
// Vertikale Linie von oben zum aktuellen Element
47+
&::before {
48+
content: '';
49+
position: absolute;
50+
left: ${props => props.depth * 20 - 10}px; // Positioniert auf der Höhe des Einzugs-Icons
51+
top: 0;
52+
bottom: 0;
53+
width: 1px;
54+
background-color: ${LINE_COLOR};
55+
// Verstecke die Linie für das erste Element auf jeder Ebene, wenn es keine Geschwister darüber hat
56+
// oder wenn depth === 0 (oberste Ebene)
57+
display: ${props => props.depth === 0 ? 'none' : 'block'};
58+
height: ${props => props.isLastChild ? 'calc(50% - 0px)' : '100%'}; // Linie bis zur Mitte, wenn letztes Kind
59+
}
60+
61+
// Horizontale Linie vom vertikalen Strich zum Inhalt (oder zum Aufklapp-Icon)
62+
// Diese Linie wird vor dem Aufklapp-Icon platziert
63+
.MuiIconButton-root:first-of-type::before {
64+
content: '';
65+
position: absolute;
66+
left: -10px; // Von der Mitte des Icons nach links
67+
top: 50%;
68+
width: 10px;
69+
height: 1px;
70+
background-color: ${LINE_COLOR};
71+
display: ${props => props.depth === 0 ? 'none' : 'block'};
72+
}
73+
74+
// Spezielle Anpassung für den Platzhalter-Box, wenn keine Kinder da sind, um die Linie zu zeichnen
75+
.placeholder-for-line::before {
76+
content: '';
77+
position: absolute;
78+
left: -10px;
79+
top: 50%;
80+
width: 10px;
81+
height: 1px;
82+
background-color: ${LINE_COLOR};
83+
display: ${props => props.depth === 0 ? 'none' : 'block'};
84+
}
4285
4386
&:hover {
4487
background-color: ${props => props.isSelected ? 'rgba(0, 159, 100, 0.15)' : 'rgba(0, 159, 100, 0.05)'};
@@ -118,14 +161,16 @@ const TreeNode: React.FC<{
118161
onSelectElement: (path: number[]) => void;
119162
onDrillDown: (path: number[]) => void;
120163
currentPath: number[];
164+
isLastChildInLevel: boolean; // Neue Prop
121165
}> = ({
122166
element,
123167
path,
124168
depth,
125169
selectedPath,
126170
onSelectElement,
127171
onDrillDown,
128-
currentPath
172+
currentPath,
173+
isLastChildInLevel
129174
}) => {
130175
const [expanded, setExpanded] = useState(false);
131176
const isSelected = arePathsEqual(path, selectedPath);
@@ -194,12 +239,15 @@ const TreeNode: React.FC<{
194239
<TreeItem
195240
depth={depth}
196241
isSelected={isSelected}
242+
isLastChild={isLastChildInLevel} // Prop für Styling der Linie
243+
hasChildren={hasActualChildren} // Prop für Styling der Linie
197244
onClick={() => onSelectElement(path)}
198245
>
199246
<TreeItemContent>
200247
{hasActualChildren ? (
201248
<IconButton
202249
size="small"
250+
sx={{ position: 'relative' }} // Für ::before Pseudoelement
203251
onClick={(e) => {
204252
e.stopPropagation();
205253
setExpanded(!expanded);
@@ -208,7 +256,8 @@ const TreeNode: React.FC<{
208256
{expanded ? <ExpandLessIcon fontSize="small" /> : <ExpandMoreIcon fontSize="small" />}
209257
</IconButton>
210258
) : (
211-
<Box sx={{ width: 28 }} /> // Platzhalter für konsistenten Einzug
259+
// Platzhalter-Box, wenn keine Kinder, aber Linie benötigt wird
260+
<Box className="placeholder-for-line" sx={{ width: 28, position: 'relative' }} />
212261
)}
213262

214263
<ListItemIcon sx={{ minWidth: 36 }}>
@@ -271,14 +320,15 @@ const TreeNode: React.FC<{
271320
<List component="div" disablePadding>
272321
{children.map((child: PatternLibraryElement, index: number) => ( // Verwende children
273322
<TreeNode
274-
key={child.element.uuid || index} // Verwende UUID falls vorhanden, sonst Index
323+
key={child.element.uuid || index}
275324
element={child}
276325
path={[...path, index]}
277326
depth={depth + 1}
278327
selectedPath={selectedPath}
279328
onSelectElement={onSelectElement}
280329
onDrillDown={onDrillDown}
281330
currentPath={currentPath}
331+
isLastChildInLevel={index === children.length - 1} // Übergebe isLastChild
282332
/>
283333
))}
284334
</List>
@@ -299,14 +349,15 @@ const ElementHierarchyTree: React.FC<ElementHierarchyTreeProps> = ({
299349
<List component="nav" aria-label="element hierarchy" dense sx={{ p: 0 }}>
300350
{elements.map((element, index) => (
301351
<TreeNode
302-
key={index}
352+
key={element.element.uuid || index}
303353
element={element}
304354
path={[index]}
305355
depth={0}
306356
selectedPath={selectedPath}
307357
onSelectElement={onSelectElement}
308358
onDrillDown={onDrillDown}
309359
currentPath={currentPath}
360+
isLastChildInLevel={index === elements.length - 1} // Übergebe isLastChild für Top-Level
310361
/>
311362
))}
312363
</List>

0 commit comments

Comments
 (0)