prime8dev

prime8dev
git clone https://git.prime8.dev/prime8dev.git
Log | Files | Refs | README | LICENSE

commit f5bf54905913b50641f4e0c48d46e4c870761584
parent 4864fd7e6526d9d36d2cd9892218d06d0eb48862
Author: Damian Myrda <damian@prime8.dev>
Date:   Fri, 23 Oct 2026 00:52:52 +0000

web: jj-style graph rail, one line with a node per role

Diffstat:
Minternal/web/styles/experience.css | 81++++++++++++++++++++++++++++++++++++++-----------------------------------------
Minternal/web/templates/partials/experience.gohtml | 5++---
2 files changed, 41 insertions(+), 45 deletions(-)

diff --git a/internal/web/styles/experience.css b/internal/web/styles/experience.css @@ -65,7 +65,7 @@ /* sit beside the graph rail, never over it: start at the card's edge and line the lanes up with the card text */ padding: 12px 24px 8px; - margin: -4px 0 0 12ch; + margin: -4px 0 0 3ch; background: var(--bg); border-bottom: 1px solid var(--border); font-size: var(--fs-14); @@ -194,89 +194,86 @@ } /* - * Terminal graph rail, one segment per job: + * Graph rail, jj log style: one continuous line down the list with a node + * on each job's role line, newest first, and ~ under the oldest. * - * @ now <- end of the job (jj's working copy for the current one) - * │ <- .graph-rail: 1px line through the node's character cell - * + feb 2026 <- start of the job - * │ <- across the gap to the next (older) job - * * feb 2026 + * @ hark / ... + * │ + * ○ mandolin / ... + * │ + * ○ amplifier health / ... + * ~ * - * The active job's nodes and dates go accent, its line accent-dim. + * Dates live on the cards, so the rail carries only the shape. The active + * job lights its node and the line down to the job before it. */ .exp-timeline { --row: 1.5em; + --node-top: 46px; /* card border + padding + role line, beside the logo */ flex-shrink: 0; - width: 12ch; + width: 3ch; position: relative; - padding-top: 24px; font-size: var(--fs-14); line-height: 1.5; font-variant-ligatures: none; font-feature-settings: "liga" 0, "calt" 0; font-synthesis: none; - letter-spacing: 0; color: var(--fg-dim); cursor: default; user-select: none; } -.graph-head, -.graph-foot { - height: var(--row); - white-space: pre; +.exp-row:has(.logo-hark) .exp-timeline { + --node-top: 39px; } +.graph-node, .graph-foot { position: absolute; left: 0; - bottom: 24px; + width: 1ch; + height: var(--row); + text-align: center; } -.graph-node, -.graph-date { - color: var(--fg-dim); +.graph-node { + top: var(--node-top); transition: color 80ms linear; } -/* hairline through the node column */ -.graph-rail, +.graph-foot { + top: calc(var(--node-top) + var(--row)); +} + +/* hairline through the node column, broken around each node */ .exp-row + .exp-row .exp-timeline::before, .exp-row:not(:last-child) .exp-timeline::after { + content: ""; position: absolute; - /* centre of the node's character cell, so the line runs through it */ left: calc(0.5ch - 0.5px); width: 1px; background: var(--border); + transition: background-color 80ms linear; } -/* from under the end node to above the start node */ -.graph-rail { - top: calc(24px + var(--row)); - bottom: calc(24px + var(--row)); - transition: background-color 80ms linear; +/* from the previous job's line, across the gap, down to this node */ +.exp-row + .exp-row .exp-timeline::before { + top: -16px; + height: calc(16px + var(--node-top)); } -/* from under the start node to the bottom of the row */ +/* from under this node to the bottom of the row */ .exp-row:not(:last-child) .exp-timeline::after { - content: ""; + top: calc(var(--node-top) + var(--row)); bottom: 0; - height: 24px; -} - -/* across the gap between cards, down to the next node */ -.exp-row + .exp-row .exp-timeline::before { - content: ""; - top: -16px; - height: calc(16px + 24px); } -.exp-row.active .graph-node, -.exp-row.active .graph-date { +.exp-row.active .graph-node { color: var(--accent); } -.exp-row.active .graph-rail { +.exp-row.active .exp-timeline::after, +.exp-row.active + .exp-row .exp-timeline::before { background: var(--accent-dim); } @@ -284,8 +281,8 @@ .exp-card, .exp-bar, .graph-node, - .graph-date, - .graph-rail { + .exp-timeline::before, + .exp-timeline::after { transition: none; } } diff --git a/internal/web/templates/partials/experience.gohtml b/internal/web/templates/partials/experience.gohtml @@ -27,9 +27,8 @@ {{$on := or (eq $exp.ID $.SelectedExperienceID) (and (not $.SelectedExperienceID) (eq $index 0))}} <div class="exp-row{{if $on}} active{{end}}" data-index="{{$index}}" data-id="{{$exp.ID}}"> <div class="exp-timeline" aria-hidden="true"> - <div class="graph-head"><span class="graph-node">{{if $exp.Current}}@{{else}}*{{end}}</span> <span class="graph-date">{{if $exp.Current}}now{{else}}{{shortEndDate $exp.EndDate $exp.Current}}{{end}}</span></div> - <span class="graph-rail"></span> - <div class="graph-foot"><span class="graph-node">+</span> <span class="graph-date">{{shortMonthYear $exp.StartDate}}</span></div> + <span class="graph-node">{{if $exp.Current}}@{{else}}○{{end}}</span> + {{if eq (inc $index) (len $.Experience)}}<span class="graph-foot">~</span>{{end}} </div> <div class="exp-card" id="exp-{{$exp.ID}}" data-index="{{$index}}" data-id="{{$exp.ID}}">