UI/UX Refinements - Spec Detail & List Views
Status: ✅ Complete · Priority: Medium · Created: 2025-11-20 · Tags: ui, ux, lessons-learned
Project: lean-spec
Team: Core Development
Overview
This spec documents the refinements made to the Spec Detail page and Specs List/Board views to improve navigation, readability, and layout flexibility. The changes focus on Table of Contents (TOC) accessibility, precise anchor navigation, and enhanced list management controls.
Key Improvements
- Responsive TOC Layout: Replaced the floating button with a persistent sidebar on large screens.
- Precise Anchor Navigation: Fixed offset issues caused by sticky headers.
- Visual Polish: Implemented auto-hiding scrollbars to reduce visual clutter.
- Specs List Enhancements: Added "Wide Mode" toggle and improved filter layout.
Current State
1. Hybrid TOC Layout (Spec Detail)
- Desktop (≥1280px): A sticky right sidebar displays the TOC. This utilizes the available screen real estate and allows users to scan the document structure without clicking a button.
- Mobile/Tablet (<1280px): Retains the floating action button (FAB) to open the TOC in a dialog, preserving screen space for content.
2. Dynamic Scroll Padding (Spec Detail)
- Problem: Sticky headers obscured section titles when navigating to anchors.
- Solution: Implemented dynamic
scroll-padding-topcalculation inSpecDetailClient.- Calculates the exact height of the sticky header (navbar + spec header).
- Applies this value to
document.documentElement.style.scrollPaddingTop. - Updates on window resize and content changes.
- Fine-tuning: Adjusted the offset (Header Height - 12px) to align the text baseline perfectly, accounting for heading margins.
3. Auto-Hiding Scrollbars
- Problem: The TOC sidebar introduced a second vertical scrollbar next to the main page scrollbar, creating visual noise.
- Solution: Created a
.scrollbar-auto-hideutility class.- The scrollbar is invisible by default.
- A thin, subtle thumb appears only on hover.
- Applied to the TOC sidebar container.
4. Specs List & Board Enhancements
- Wide Mode Toggle: Added a maximize/minimize button to toggle the container width between
max-w-7xlandw-full. This is particularly useful for the Kanban board view with many columns. - Improved Header Layout:
- Reorganized filters and search into a scrollable row for better mobile responsiveness.
- Updated View Switcher (List/Board) to a segmented control style.
- View Persistence: View mode preference (List vs Board) is now persisted in
localStorageand synchronized with the URL.
Lessons Learned
Sticky Headers & Anchor Navigation
scroll-padding-topvsscroll-margin-top:scroll-margin-topon individual headings is brittle when header heights change (e.g., wrapping tags).scroll-padding-topon the<html>element is superior as it can be dynamically updated via JavaScript to match the exact current header height.
- Navigation Method:
element.scrollIntoView({ behavior: 'smooth', block: 'start' })respectsscroll-padding-topautomatically.- Manual
window.scrollTocalculations are error-prone and should be avoided when native APIs suffice.
Visual Refinements
- Scrollbar UX: "Double scrollbars" are a common UI smell in sidebars. Auto-hiding them is a clean pattern that maintains functionality without clutter.
- Offset Tuning: Mathematical exactness (Header Height + Padding) doesn't always equal visual correctness. Small adjustments (e.g.,
-12px) are often needed to account for line-heights and margins.
Implementation Details
Files Modified
packages/ui/src/components/spec-detail-client.tsx: Layout changes, scroll padding logic.packages/ui/src/components/table-of-contents.tsx: Refactored to support both Sidebar and Dialog modes.packages/ui/src/app/globals.css: Added.scrollbar-auto-hideutility.packages/ui/src/app/specs/specs-client.tsx: Added Wide Mode, updated header layout, view persistence.
Code Snippet: Dynamic Scroll Padding
// Handle scroll padding for sticky header
React.useEffect(() => {
const updateScrollPadding = () => {
const navbarHeight = 56;
let offset = navbarHeight;
if (window.innerWidth >= 1024 && headerRef.current) {
offset += headerRef.current.offsetHeight;
// Reduce offset slightly to avoid visual gap due to heading margins
offset -= 12;
}
document.documentElement.style.scrollPaddingTop = `${offset}px`;
};
// ... observers and event listeners
}, [spec, tags]);
Plan
- Refactor
TableOfContentsto support sidebar mode - Update
SpecDetailClientlayout for desktop sidebar - Implement dynamic
scroll-padding-toplogic - Add auto-hiding scrollbar styles
- Implement Wide Mode in
SpecsClient - Refine Specs List header layout
- Verify navigation precision
Test
- Desktop View: TOC appears as sidebar.
- Mobile View: TOC appears as floating button.
- Anchor Click: Page scrolls smoothly to section.
- Alignment: Section title is not obscured by header and has correct visual spacing.
- Scrollbar: Sidebar scrollbar is hidden until hovered.
- Wide Mode: Toggling expands the container to full width.
- View Persistence: Refreshing the page remembers the last selected view (List/Board).