Skip to content

Conversation

@vinnymac
Copy link
Contributor

@vinnymac vinnymac commented Feb 8, 2026

Built on the backs of @graphieros's vue-ui-xy and @NullVoxPopuli's majors to add a npmx themed version distributions feature.

image

Also added hide old here because that's something I personally wanted for this. Idk if anyone else was working on a related feature here, so if this crosses paths with some ongoing work, just let me know.

@vercel
Copy link

vercel bot commented Feb 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Feb 10, 2026 9:05pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Feb 10, 2026 9:05pm
npmx-lunaria Ignored Ignored Feb 10, 2026 9:05pm

Request Review

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

Lunaria Status Overview

🌕 This pull request will trigger status changes.

Learn more

By default, every PR changing files present in the Lunaria configuration's files property will be considered and trigger status changes accordingly.

You can change this by adding one of the keywords present in the ignoreKeywords property in your Lunaria configuration file in the PR's title (ignoring all files) or by including a tracker directive in the merged commit's description.

Tracked Files

File Note
lunaria/files/en-GB.json Localization changed, will be marked as complete. 🔄️
lunaria/files/en-US.json Source changed, localizations will be marked as outdated.
Warnings reference
Icon Description
🔄️ The source for this localization has been updated since the creation of this pull request, make sure all changes in the source have been applied.

@NullVoxPopuli
Copy link
Contributor

Oooo fancy !

@codecov
Copy link

codecov bot commented Feb 9, 2026

@vinnymac
Copy link
Contributor Author

vinnymac commented Feb 9, 2026

Need to change the title to feat(ui) oops

@danielroe danielroe changed the title feat(frontend): community version distribution feat(ui): community version distribution Feb 9, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a version download distribution feature: new VersionDistribution Vue component and a useVersionDistribution composable; server API route /api/registry/downloads/:slug/versions and server utils to group/filter per-version downloads; shared types and re-export added; Versions.vue now opens a modal and defers mounting the chart until the dialog transition finishes; ChartModal accepts a title prop and emits a transitioned event; WeeklyDownloadStats passes the modal title; Tooltip App/Base accept teleportTo and offset props; localisation keys added; VersionDistribution is skipped in a11y component coverage and tests updated.

Possibly related PRs

Suggested labels

idea

Suggested reviewers

  • danielroe
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The PR description is clearly related to the changeset, explaining the feature being added: a version distribution UI built on vue-ui-xy with major/minor grouping, date ranges, and version filtering options.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
server/api/registry/downloads/[...slug].get.ts (2)

83-89: totalDownloads is computed after filtering, which may not match expected semantics.

The totalDownloads on line 89 is calculated from data.downloads (all versions), but groups on line 83 has already been created from groupVersionDownloads. If the intention is for totalDownloads to represent the sum of the returned groups only (after threshold filtering on line 86), the current calculation is inconsistent.

Consider whether:

  1. totalDownloads should reflect the pre-filter total (current behaviour) — this is likely correct for percentage context.
  2. Or if it should match the sum of filtered groups.

If the current behaviour is intentional, a brief comment would clarify this.


116-117: Consider defensive access when reading versionData.versions.

The cast as { versions: string[] } assumes the external API always returns this shape. If the response structure changes or is malformed, accessing versionData.versions could throw or assign undefined.

🛡️ Suggested defensive access
-          const versionData = (await fastMetaResponse.json()) as { versions: string[] }
-          apiResponse.recentVersions = versionData.versions
+          const versionData = (await fastMetaResponse.json()) as { versions?: string[] }
+          if (Array.isArray(versionData.versions)) {
+            apiResponse.recentVersions = versionData.versions
+          }
app/components/Package/Versions.vue (1)

336-344: Remove inline focus-visible utility class from button.

The focus-visible:outline-accent/70 class on line 338 should be removed. Per project conventions, focus-visible styling for buttons is applied globally via main.css, and individual buttons should not use inline focus-visible utility classes.

♻️ Suggested fix
       <ButtonBase
         variant="secondary"
-        class="text-fg-subtle hover:text-fg transition-colors duration-200 inline-flex items-center justify-center min-w-6 min-h-6 -m-1 p-1 focus-visible:outline-accent/70 rounded"
+        class="text-fg-subtle hover:text-fg transition-colors duration-200 inline-flex items-center justify-center min-w-6 min-h-6 -m-1 p-1 rounded"
         :title="$t('package.downloads.community_distribution')"
         classicon="i-carbon:load-balancer-network"
         `@click`="openDistributionModal"

Based on learnings: "focus-visible styling for buttons and selects is applied globally via main.css... individual buttons or selects in Vue components should not rely on inline focus-visible utility classes".

server/utils/version-downloads.ts (1)

120-129: Comment is misleading — the grouping logic is identical for all versions.

The comment at lines 123-124 suggests special handling for 0.x versions, but the actual implementation groups all versions by major.minor uniformly. The comment should be updated to reflect that this function always groups by minor version, which happens to align with semver conventions where 0.x minor bumps are breaking changes.

📝 Suggested comment update
   // Group by major.minor
   const groups = new Map<string, ProcessedVersion[]>()
   for (const version of processed) {
-    // For 0.x versions, treat each minor as significant (0.9.x, 0.10.x are different)
-    // For 1.x+, group by major.minor normally
+    // Group all versions by major.minor (e.g., 1.2.x, 1.3.x)
+    // This aligns with semver conventions where 0.x minor bumps indicate breaking changes
     const groupKey = `${version.major}.${version.minor}`

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/components/Package/VersionDistribution.vue (1)

66-175: Split chartConfig into smaller helpers to keep functions manageable.

chartConfig is well over the guideline’s 50‑line threshold. Consider extracting sub-builders (e.g., grid/tooltip/zoom config) to keep the computed function focused and easier to test.

As per coding guidelines: Keep functions focused and manageable (generally under 50 lines).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/components/Package/VersionDistribution.vue (1)

66-175: Consider splitting chartConfig into smaller computed blocks.

This computed exceeds the “generally under 50 lines” guidance. Extract grid/tooltip/zoom config builders (or separate computeds) to keep the logic manageable.

As per coding guidelines, "Keep functions focused and manageable (generally under 50 lines)".

@NullVoxPopuli
Copy link
Contributor

It seems some logic is goofy with the 'old versions' toggle?

For example:
https://npmxdev-git-fork-vinnymac-vt-nullvoxpopuli-npmx.vercel.app/package/ember-source

Unchecked: i see 2.x and 6.x.
Checked: i see them all

Which seems backwards? Idk

Lookin' good so far!

@vinnymac
Copy link
Contributor Author

Unchecked: i see 2.x and 6.x. Checked: i see them all

Which seems backwards? Idk

Lookin' good so far!

Just tried this and it worked for me, have you opened this link before by any chance? I have fixed caching related bugs on this branch that may require you to clear your browser cache

@NullVoxPopuli
Copy link
Contributor

Hmm -- I experienced this in a private browser window 🤔

@vinnymac
Copy link
Contributor Author

vinnymac commented Feb 10, 2026

@NullVoxPopuli oh! I read your message wrong. I actually flipped this toggle from "hide" to "show" recently, so now it defaults to hiding the old versions, so what you described is expected.

By default it will show versions younger than 1 year ago (older ones are hidden), and checked the box reveals them (shows you more versions)

@NullVoxPopuli
Copy link
Contributor

It's time based?

I don't think that is as effective a signal, because in the example above, we had an enterprise client who hadn't upgraded in over a decade pay for a security fix, so now 2.x shows up even though most users aren't on 2.x

And the whole major-release schedule is every year and a half for this particular project - and some other ecosystems have even longer between majors - perhaps a current version to current version minus 5 or some other range could be used?

Was time chosen because of frequent major releasors? (Angular, Next, etc?)

@vinnymac
Copy link
Contributor Author

It's time based

Yea the old versions feature is time based. It defaults to hiding versions older than 1 years, and enabling the toggle displays those old versions. This was just something I wanted personally, but if you'd prefer it behave differently I am open to changing this / the defaults / etc.

@NullVoxPopuli
Copy link
Contributor

To me, it seems like 1 year only makes sense if the whole ecosystem is super on top of upgrades and every library is doing multiple majors per year -- which would be quite disruptive if it were the default, i think

@NullVoxPopuli
Copy link
Contributor

image

should the labels be more left-aligned -- closer to the toggles?
and should the tooltip be more descriptive?

<3

@vinnymac
Copy link
Contributor Author

Interesting, I didn't know they had tooltips on the toggles, I added my own to the labels instead when I first started this, not sure how new that is, but it definitely wasn't there before (maybe a bug fix?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants