feat: sidebar tree navigation — toggle chevrons + drag & drop
- Add sort_order column to pages table for drag & drop reordering
- Rewrite _sidebar_data with recursive _build_page_tree for nested hierarchy
- Add tree toggle buttons (▶ collapsed / ▼ expanded) on parent items
- Alpine.js expandedNodes state with toggleTreeNode() for expand/collapse
- Jinja2 recursive macro render_tree_item for proper nesting + indentation
- SortableJS integration on .sidebar-items for drag & drop repositioning
- New PUT /board/api/pages/{id}/move API for persisting moves
- Auto-set sort_order on page creation (max+1 for same parent)
- CSS: .tree-toggle, .tree-toggle-placeholder, grab cursor on page-icon
- 28/28 tests pass, all endpoints healthy
This commit is contained in:
+47
-4
@@ -311,11 +311,58 @@ input, select, textarea { font-family: inherit; color: inherit; }
|
||||
background: var(--bg-active);
|
||||
}
|
||||
|
||||
/* Tree toggle button (▶/▼ chevron) */
|
||||
.tree-toggle {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--text-secondary);
|
||||
font-size: 9px;
|
||||
flex-shrink: 0;
|
||||
transition: transform 0.15s ease, background var(--transition);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.tree-toggle:hover {
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.tree-toggle.expanded {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.tree-toggle-placeholder {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Tree children wrapper */
|
||||
.tree-children-wrapper {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.tree-children-wrapper .sidebar-items {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.sidebar-item .page-icon {
|
||||
font-size: 14px;
|
||||
width: 18px;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.sidebar-item:active .page-icon {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.sidebar-item .page-name {
|
||||
@@ -353,10 +400,6 @@ input, select, textarea { font-family: inherit; color: inherit; }
|
||||
background: var(--bg-tertiary);
|
||||
}
|
||||
|
||||
/* Indented sub-items */
|
||||
.sidebar-item.indent-1 { padding-left: 24px; }
|
||||
.sidebar-item.indent-2 { padding-left: 40px; }
|
||||
|
||||
/* Sidebar footer */
|
||||
.sidebar-footer {
|
||||
margin-top: auto;
|
||||
|
||||
Reference in New Issue
Block a user