[READ-ONLY] Mirror of https://github.com/SantaClaas/gigit. git client

Draw the commit graph master

The history is an ordinary list of buttons. Each row owns a small SVG for its lane segment, marked aria-hidden, over content that already reads correctly without it — a summary, an author, a <time>, and a short id. Row is a button because selecting a commit is an action and a button brings its own role, focus ring and Enter handling; that limits it to phrasing content, which is why ref badges are spans with a visually hidden word for what each one is. Ten lane colours come from one CSS rule rather than ten values: the lane index rotates an oklch hue, starting near the seed colour so the graph belongs to the same palette as everything else. Nothing about colour reaches the Rust side, and switching light to dark re-themes the whole graph without a re-render. Nothing here needs a virtual list. Rows arrive in batches as the end of the list nears the viewport, so the DOM only holds what has been scrolled to, and rows past the first forty get content-visibility so the browser skips laying out and painting the rest. `none` for the intrinsic width keeps an off-screen row from collapsing horizontally, which would make the scroll width jump on a wide graph. Which rows are deferred is decided by nth-child, so no JavaScript is involved. Wide graphs scroll rather than compress. A graph's width comes from the history — aspnetcore lays out 115 columns — so no window size makes it fit and capping would only hide branches. Two things caught while driving the real components in a browser: - Five arrow presses moved the selection one row. Solid 2 batches signal writes, so reading selected() to compute the next value goes stale when presses land in one batch. Now the update goes through the functional setter, which sees the pending value. - jsx-a11y assumes React's htmlFor, so Solid's plain `for` read as an unassociated label. Configured rather than worked around. Safari drops list semantics from a list styled with list-style: none, which Tailwind's preflight applies — and Tauri is WKWebView on macOS, so that is the default here. An empty-string marker renders nothing and leaves the list a list, which beats patching the role back with ARIA. Opening is a path field for now. A native folder picker needs the Tauri dialog plugin, which is a dependency this change does not need; the picker arrives with the repository-picker work. Infinite scrolling is not verified yet — IntersectionObserver does not run in a hidden document, and the browser pane available here cannot make one visible. The Playwright harness covers it next. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>