Sidebar tree: stack parents above children, compact rows, icons
The tree reused .sidebar__page-item's flex ROW from the flat list, so the nested children <ul> sat BESIDE the parent row and align-items: center made the parent float vertically centered next to its subtree. Stack the two in tree view instead: parent first, children indented below (about two characters per level). Rows get compacter (smaller font, tighter padding) so a deep imported vault fits on screen, and folder pages now read differently from leaf pages at a glance: lucide Folder/FolderOpen vs FileText, with the caret glyph upgraded to a ChevronRight that keeps the existing CSS rotation. Caret button, classes, and aria-labels stay untouched for the e2e contract (#101 convention: no page title in the caret label). Fixes #122 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fb2VzvcoBPHkjh8bZ6PzQn
This commit is contained in:
parent
b8546eb249
commit
d4fb2a3c51
@ -8,6 +8,7 @@ import type {
|
|||||||
} from '@dorfteich/shared';
|
} from '@dorfteich/shared';
|
||||||
import { buildTree, collectSubtreeIds, labelDepth } from '@dorfteich/shared';
|
import { buildTree, collectSubtreeIds, labelDepth } from '@dorfteich/shared';
|
||||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
|
import { ChevronRight, FileText, Folder, FolderOpen } from 'lucide-react';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
@ -527,11 +528,14 @@ function PageTreeLevel(props: PageTreeLevelProps): React.JSX.Element {
|
|||||||
)}
|
)}
|
||||||
onClick={() => onToggleCollapsed(node.id)}
|
onClick={() => onToggleCollapsed(node.id)}
|
||||||
>
|
>
|
||||||
▸
|
<ChevronRight aria-hidden />
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<span className="sidebar__caret sidebar__caret--leaf" aria-hidden />
|
<span className="sidebar__caret sidebar__caret--leaf" aria-hidden />
|
||||||
)}
|
)}
|
||||||
|
<span className="sidebar__page-icon" aria-hidden>
|
||||||
|
{hasChildren ? isCollapsed ? <Folder /> : <FolderOpen /> : <FileText />}
|
||||||
|
</span>
|
||||||
<PageLink page={node} pondSlug={pondSlug} pageSlug={pageSlug} />
|
<PageLink page={node} pondSlug={pondSlug} pageSlug={pageSlug} />
|
||||||
{canReorder && (
|
{canReorder && (
|
||||||
<span className="sidebar__reorder">
|
<span className="sidebar__reorder">
|
||||||
|
|||||||
@ -198,23 +198,40 @@ button {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In the tree, the nested children <ul> is a SECOND flex item of the
|
||||||
|
.sidebar__page-item <li>. Stack it below the parent row (#122) — the
|
||||||
|
base rule's flex row centered the parent vertically BESIDE its children. */
|
||||||
|
.sidebar__pages--tree .sidebar__page-item {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar__tree-children {
|
.sidebar__tree-children {
|
||||||
margin: 0 0 0 var(--space-3);
|
/* Per-level indent: about two characters is plenty (#122). */
|
||||||
|
margin: 0 0 0 1.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__caret {
|
.sidebar__caret {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
border: 0;
|
border: 0;
|
||||||
background: none;
|
background: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: var(--color-text-muted);
|
color: var(--color-text-muted);
|
||||||
font-size: 0.7rem;
|
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
transition: transform 0.12s ease;
|
transition: transform 0.12s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar__caret svg {
|
||||||
|
width: 0.9rem;
|
||||||
|
height: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar__caret--collapsed {
|
.sidebar__caret--collapsed {
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
}
|
}
|
||||||
@ -223,6 +240,19 @@ button {
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Folder pages vs. leaf pages read differently at a glance (#122). */
|
||||||
|
.sidebar__page-icon {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar__page-icon svg {
|
||||||
|
width: 0.875rem;
|
||||||
|
height: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* Label view (issue #108): pages grouped under the label tree. */
|
/* Label view (issue #108): pages grouped under the label tree. */
|
||||||
.sidebar__label-group {
|
.sidebar__label-group {
|
||||||
margin-bottom: var(--space-2);
|
margin-bottom: var(--space-2);
|
||||||
@ -322,11 +352,12 @@ button {
|
|||||||
|
|
||||||
.sidebar__page {
|
.sidebar__page {
|
||||||
display: block;
|
display: block;
|
||||||
padding: var(--space-1) var(--space-2);
|
/* Compact rows (#122): deep imported trees need to fit on one screen. */
|
||||||
|
padding: 0.125rem var(--space-2);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 0.95rem;
|
font-size: 0.875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__page:hover {
|
.sidebar__page:hover {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user