From c5c14267fe4f991654251437ed8523a43067f8ac Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 27 May 2026 21:50:05 +0300 Subject: showcase: grey out inactive projects in rank history SVG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inactive projects (avgCommitAge > 730 days AND last commit > 365 days ago, matching the gemtext inactivity notice) are now visually distinguished: Default state - Plot line: rendered as #555 grey at 0.3 opacity so it is visible but does not compete with active coloured lines. - Legend entry: dimmed to 0.35 opacity. On legend-entry hover - The line snaps to its project colour and is bolded (stroke-width 3) at full opacity — identical behaviour to active projects. - Other inactive lines remain at their grey resting state (not dimmed to 0.08 alongside active ones) so they stay readable. On leave - Both stroke colour and opacity are restored per-project: grey+0.3 for inactive, colour+0.55 for active. The inactivity flag is stored in the PROJECTS JSON (inactive:true/false) so all JS state transitions can consult it without touching the DOM attributes. Co-Authored-By: Claude Sonnet 4.6 --- internal/showcase/rank_history_svg.go | 84 ++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/internal/showcase/rank_history_svg.go b/internal/showcase/rank_history_svg.go index d932edc..a761f7f 100644 --- a/internal/showcase/rank_history_svg.go +++ b/internal/showcase/rank_history_svg.go @@ -5,6 +5,7 @@ import ( "fmt" "math" "strings" + "time" ) // SVG canvas and margin constants (pixels in viewBox coordinates). @@ -37,10 +38,15 @@ type svgTimePoint struct { } // svgProjectData carries per-project metadata used by the interactive JS layer. +// Inactive is true when the project's average commit age exceeds 730 days AND +// the last commit was over a year ago — matching the gemtext inactivity notice. +// Inactive projects are rendered as grey lines by default and only switch to +// their project colour when the user mouses over their legend entry. type svgProjectData struct { - Name string `json:"name"` - Color string `json:"color"` - Points []svgTimePoint `json:"points"` + Name string `json:"name"` + Color string `json:"color"` + Points []svgTimePoint `json:"points"` + Inactive bool `json:"inactive"` } // projectColor returns a visually distinct CSS hex color for project index i. @@ -201,10 +207,24 @@ func GenerateRankHistorySVG(summaries []ProjectSummary) string { continue // skip projects that have never appeared in any snapshot } + // Mirror the inactivity check from formatGemtext: avg commit age > 730 days + // AND the most recent commit was also over a year ago. Inactive projects + // are still drawn but as grey lines so they do not compete visually with + // active ones; they turn coloured only on legend-entry hover. + inactive := false + if s.Metadata != nil && s.Metadata.AvgCommitAge > 730 && s.Metadata.LastCommitDate != "" { + if last, err := time.Parse("2006-01-02", s.Metadata.LastCommitDate); err == nil { + if time.Since(last).Hours()/24 > 365 { + inactive = true + } + } + } + allProjects = append(allProjects, svgProjectData{ - Name: s.Name, - Color: projectColor(colorIdx), - Points: pts, + Name: s.Name, + Color: projectColor(colorIdx), + Points: pts, + Inactive: inactive, }) colorIdx++ } @@ -436,8 +456,25 @@ function rescale(){ window.addEventListener('resize',rescale); rescale(); +// Initialise inactive projects: grey plot line, dimmed legend entry. +// This runs once after DOM and rescale() are ready. +for(var i=0;i