From c3aaa42060ecf27b0c937a4e5ca8be6f45b12332 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Wed, 4 Feb 2026 00:32:47 +0100
Subject: [PATCH 01/91] fix: invalid link attribute
---
app/components/Tag/Link.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Tag/Link.vue b/app/components/Tag/Link.vue
index 48a1aba5c..ed36f342c 100644
--- a/app/components/Tag/Link.vue
+++ b/app/components/Tag/Link.vue
@@ -1,7 +1,7 @@
+
+
+
+
diff --git a/app/components/Button/Link.vue b/app/components/Button/Link.vue
new file mode 100644
index 000000000..50626fd68
--- /dev/null
+++ b/app/components/Button/Link.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/components/ColumnPicker.vue b/app/components/ColumnPicker.vue
index 6b8c8ea14..37c64e256 100644
--- a/app/components/ColumnPicker.vue
+++ b/app/components/ColumnPicker.vue
@@ -65,10 +65,9 @@ function handleReset() {
-
+
{{ error?.message ?? $t('org.page.failed_to_load') }}
- {{ $t('common.go_back_home') }}
+ {{ $t('common.go_back_home') }}
diff --git a/app/pages/package-code/[...path].vue b/app/pages/package-code/[...path].vue
index 9ef07ae6a..2338432bd 100644
--- a/app/pages/package-code/[...path].vue
+++ b/app/pages/package-code/[...path].vue
@@ -359,7 +359,7 @@ defineOgImageComponent('Default', {
{{ $t('code.version_required') }}
-
{{ $t('code.go_to_package') }}
+
{{ $t('code.go_to_package') }}
@@ -371,7 +371,7 @@ defineOgImageComponent('Default', {
{{ $t('code.failed_to_load_tree') }}
-
{{ $t('code.back_to_package') }}
+
{{ $t('code.back_to_package') }}
@@ -472,15 +472,15 @@ defineOgImageComponent('Default', {
{{ $t('code.file_size_warning', { size: formatBytes(currentNode?.size ?? 0) }) }}
-
{{ $t('code.view_raw') }}
-
+
@@ -526,15 +526,15 @@ defineOgImageComponent('Default', {
{{ $t('code.failed_to_load') }}
{{ $t('code.unavailable_hint') }}
-
{{ $t('code.view_raw') }}
-
+
diff --git a/app/pages/package/[...package].vue b/app/pages/package/[...package].vue
index 108bb5fc8..d48ed343c 100644
--- a/app/pages/package/[...package].vue
+++ b/app/pages/package/[...package].vue
@@ -1151,7 +1151,7 @@ defineOgImageComponent('Package', {
{{ error?.message ?? $t('package.not_found_message') }}
- {{ $t('common.go_back_home') }}
+ {{ $t('common.go_back_home') }}
diff --git a/app/pages/~[username]/index.vue b/app/pages/~[username]/index.vue
index 7139d5cda..545d51c98 100644
--- a/app/pages/~[username]/index.vue
+++ b/app/pages/~[username]/index.vue
@@ -224,7 +224,7 @@ defineOgImageComponent('Default', {
{{ error?.message ?? $t('user.page.failed_to_load') }}
- {{ $t('common.go_back_home') }}
+ {{ $t('common.go_back_home') }}
diff --git a/app/pages/~[username]/orgs.vue b/app/pages/~[username]/orgs.vue
index 5cad2bba4..7d355e595 100644
--- a/app/pages/~[username]/orgs.vue
+++ b/app/pages/~[username]/orgs.vue
@@ -81,6 +81,8 @@ async function loadOrgs() {
}
}
+error.value = $t('header.orgs_dropdown.error')
+
// Load on mount and when connection status changes
watch(isOwnProfile, loadOrgs, { immediate: true })
@@ -154,9 +156,9 @@ defineOgImageComponent('Default', {
{{ $t('user.orgs_page.own_orgs_only') }}
-
{{
+ {{
$t('user.orgs_page.view_your_orgs')
- }}
+ }}
@@ -165,7 +167,7 @@ defineOgImageComponent('Default', {
{{ error }}
-
+
{{ $t('common.try_again') }}
From a2872d6b92a3b0dd14f59c49a1006e1461c1f04c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Wed, 4 Feb 2026 01:16:17 +0100
Subject: [PATCH 04/91] refactor: remove uno btn shortcut
---
app/components/Button/Base.vue | 2 +-
app/components/Button/Link.vue | 2 +-
uno.config.ts | 10 ----------
3 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index 919082a5e..4f3a8b01e 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -19,7 +19,7 @@ defineExpose({
{{ $t('code.failed_to_load') }}
{{ $t('code.unavailable_hint') }}
{{ error?.message ?? $t('package.not_found_message') }}
- {{ $t('common.go_back_home') }}
+ {{ $t('common.go_back_home') }}
diff --git a/app/pages/~[username]/index.vue b/app/pages/~[username]/index.vue
index 867151ec0..53369754b 100644
--- a/app/pages/~[username]/index.vue
+++ b/app/pages/~[username]/index.vue
@@ -224,7 +224,7 @@ defineOgImageComponent('Default', {
{{ error?.message ?? $t('user.page.failed_to_load') }}
- {{ $t('common.go_back_home') }}
+ {{ $t('common.go_back_home') }}
diff --git a/app/pages/~[username]/orgs.vue b/app/pages/~[username]/orgs.vue
index f070fd86e..cb50663b7 100644
--- a/app/pages/~[username]/orgs.vue
+++ b/app/pages/~[username]/orgs.vue
@@ -156,7 +156,7 @@ defineOgImageComponent('Default', {
{{ $t('user.orgs_page.own_orgs_only') }}
-
{{
+ {{
$t('user.orgs_page.view_your_orgs')
}}
From 205c937806586f823865d99c7d6f03a918c26435 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Thu, 5 Feb 2026 14:41:49 +0100
Subject: [PATCH 19/91] refactor: replace links with component
---
app/app.vue | 14 +---
app/components/AppFooter.vue | 46 +++----------
app/components/AppHeader.vue | 27 ++++----
app/components/Header/AccountMenu.client.vue | 4 +-
app/components/Link/Base.vue | 16 +++--
app/pages/about.vue | 68 ++++++--------------
app/pages/index.vue | 8 +--
uno.config.ts | 5 --
8 files changed, 64 insertions(+), 124 deletions(-)
diff --git a/app/app.vue b/app/app.vue
index e8103f513..258c433a3 100644
--- a/app/app.vue
+++ b/app/app.vue
@@ -117,7 +117,9 @@ if (import.meta.client) {
-
{{ $t('common.skip_link') }}
+
{{
+ $t('common.skip_link')
+ }}
@@ -136,19 +138,9 @@ if (import.meta.client) {
.skip-link {
position: fixed;
top: -100%;
- inset-inline-start: 0;
- padding: 0.5rem 1rem;
- background: var(--fg);
- color: var(--bg);
- font-size: 0.875rem;
z-index: 100;
- transition: top 0.2s ease;
}
-.skip-link:hover {
- color: var(--bg);
- text-decoration: underline;
-}
.skip-link:focus {
top: 0;
}
diff --git a/app/components/AppFooter.vue b/app/components/AppFooter.vue
index 80565e73d..1bf7e1cf1 100644
--- a/app/components/AppFooter.vue
+++ b/app/components/AppFooter.vue
@@ -15,51 +15,25 @@ const isHome = computed(() => route.name === 'index')
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index 05ebffb81..62156087a 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -151,34 +151,36 @@ onKeyStroke(
-
{{ $t('nav.compare') }}
c
-
+
-
{{ $t('nav.settings') }}
,
-
+
@@ -186,14 +188,15 @@ onKeyStroke(
-
-
+
diff --git a/app/components/Header/AccountMenu.client.vue b/app/components/Header/AccountMenu.client.vue
index 82c0fde1c..823a6e17e 100644
--- a/app/components/Header/AccountMenu.client.vue
+++ b/app/components/Header/AccountMenu.client.vue
@@ -57,7 +57,7 @@ function openAuthModal() {
-
{{ operationCount }}
-
+
> | Required>) &
NuxtLinkProps
>(),
- { variant: 'button-secondary' },
+ { variant: 'link' },
)
{{ $t('about.what_we_are.better_ux_dx') }}
- JSRJSR
@@ -112,58 +108,34 @@ const { data: contributors, status: contributorsStatus } = useFetch
{{ $t('about.what_we_are_not.words.already') }}
- {{ $t('about.what_we_are_not.words.people') }}
+ {{
+ $t('about.what_we_are_not.words.people')
+ }}
- {{ $t('about.what_we_are_not.words.building') }}
+ {{
+ $t('about.what_we_are_not.words.building')
+ }}
- {{ $t('about.what_we_are_not.words.really') }}
+ {{
+ $t('about.what_we_are_not.words.really')
+ }}
- {{ $t('about.what_we_are_not.words.cool') }}
+ {{
+ $t('about.what_we_are_not.words.cool')
+ }}
- {{ $t('about.what_we_are_not.words.package') }}
+ {{
+ $t('about.what_we_are_not.words.package')
+ }}
- {{ $t('about.what_we_are_not.words.managers') }}
+ {{
+ $t('about.what_we_are_not.words.managers')
+ }}
diff --git a/app/pages/index.vue b/app/pages/index.vue
index 12cc879b7..596b4c477 100644
--- a/app/pages/index.vue
+++ b/app/pages/index.vue
@@ -98,7 +98,7 @@ defineOgImageComponent('Default', {
-
+
{{ $t('search.button') }}
@@ -118,15 +118,15 @@ defineOgImageComponent('Default', {
>
-
-
{{ framework.name }}
-
+
diff --git a/uno.config.ts b/uno.config.ts
index 34ec5b7ce..a7a529e72 100644
--- a/uno.config.ts
+++ b/uno.config.ts
@@ -126,11 +126,6 @@ export default defineConfig({
// Focus states - subtle but accessible
['focus-ring', 'outline-none focus-visible:(ring-2 ring-fg/50 ring-offset-2)'],
- // Links
- [
- 'link',
- 'text-fg underline-offset-4 decoration-border hover:(decoration-fg underline) transition-colors duration-200 focus-ring',
- ],
['link-subtle', 'text-fg-muted hover:text-fg transition-colors duration-200 focus-ring'],
// badges
From 4974d56c628662f8dd1d0253cb1a914a8c2002f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Thu, 5 Feb 2026 15:02:42 +0100
Subject: [PATCH 20/91] fix: remove exclamation mark accidentally added
---
app/components/Tag/Static.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Tag/Static.vue b/app/components/Tag/Static.vue
index 3e8a38d5d..e1afe90f1 100644
--- a/app/components/Tag/Static.vue
+++ b/app/components/Tag/Static.vue
@@ -11,6 +11,6 @@ const props = withDefaults(
class="bg-bg-muted text-fg-muted inline-flex gap-x-1 items-center justify-center font-mono border border-transparent rounded-md text-xs px-2 py-0.5"
:class="{ 'opacity-40': variant === 'disabled' }"
>
- !
+
From 80bcd90392cf25a97ea6217ddf4897712fb7ac80 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 02:52:57 +0100
Subject: [PATCH 21/91] refactor: replace (almost) all links on package page
---
app/components/Link/Base.vue | 4 +-
app/pages/package/[...package].vue | 168 ++++++++++++++---------------
2 files changed, 83 insertions(+), 89 deletions(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index ba47c167e..6cda7467a 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -39,9 +39,9 @@ const props = withDefaults(
-
+
@{{ orgName }}
-
+
/
{{ orgName ? pkg.name.replace(`@${orgName}/`, '') : pkg.name }}
@@ -557,11 +552,11 @@ onKeyStroke(
- {{ resolvedVersion }}{{ resolvedVersion }}
v{{ resolvedVersion }}
@@ -576,13 +571,13 @@ onKeyStroke(
"
position="bottom"
>
-
-
+
-
-
{{ $t('package.links.docs') }}
d
-
-
+
{{ $t('package.links.code') }}
.
-
-
+
{{ $t('package.links.compare') }}
c
-
+
@@ -715,127 +710,124 @@ onKeyStroke(
-
-
{{ formatCompactNumber(stars, { decimals: 1 }) }}
-
+
-
{{ formatCompactNumber(forks, { decimals: 1 }) }}
-
+
-
{{ $t('package.links.homepage') }}
-
+
-
{{ $t('package.links.issues') }}
-
+
-
npm
-
+
-
{{ $t('package.links.jsr') }}
-
+
-
{{ $t('package.links.fund') }}
-
+
-
+
{{ $t('package.links.docs') }}
-
+
-
{{ $t('package.links.code') }}
-
+
-
{{ $t('package.links.compare') }}
-
+
@@ -905,29 +897,31 @@ onKeyStroke(
-
-
- {{ $t('package.stats.view_dependency_graph') }}
-
-
-
-
- {{ $t('package.stats.inspect_dependency_tree') }}
-
+
+
+
+ {{ $t('package.stats.view_dependency_graph') }}
+
+
+
+
+ {{ $t('package.stats.inspect_dependency_tree') }}
+
+
From 260be921125084b44ad20278a9487b2d09740a5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 03:10:12 +0100
Subject: [PATCH 22/91] feat: unifyied keyshort cut system
---
app/components/AppHeader.vue | 17 +++--------------
app/components/Button/Base.vue | 22 ++++++++++++++++++----
app/components/Link/Base.vue | 22 +++++++++++++++++++---
app/pages/package/[...package].vue | 30 ++++--------------------------
4 files changed, 44 insertions(+), 47 deletions(-)
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index 62156087a..13a7b24d9 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -1,4 +1,5 @@
@@ -11,6 +16,7 @@ const props = withDefaults(
class="bg-bg-muted text-fg-muted inline-flex gap-x-1 items-center justify-center font-mono border border-transparent rounded-md text-xs px-2 py-0.5"
:class="{ 'opacity-40': variant === 'disabled' }"
>
+
diff --git a/app/pages/index.vue b/app/pages/index.vue
index 596b4c477..78a272f69 100644
--- a/app/pages/index.vue
+++ b/app/pages/index.vue
@@ -96,9 +96,12 @@ defineOgImageComponent('Default', {
@input="handleInput"
/>
-
-
-
+
{{ $t('search.button') }}
diff --git a/app/pages/package/[...package].vue b/app/pages/package/[...package].vue
index 2e6b20042..138a682dd 100644
--- a/app/pages/package/[...package].vue
+++ b/app/pages/package/[...package].vue
@@ -576,9 +576,8 @@ onKeyStroke(
variant="tag"
href="#provenance"
:aria-label="$t('package.provenance_section.view_more_details')"
- >
-
-
+ classicon="i-lucide-shield-check"
+ />
-
-
+
{{ $t('package.links.docs') }}
-
{{ $t('package.links.code') }}
-
{{ $t('package.links.compare') }}
@@ -695,8 +699,8 @@ onKeyStroke(
:href="repositoryUrl"
target="_blank"
rel="noopener noreferrer"
+ :classicon="repoProviderIcon"
>
-
{{ repoRef.owner }}/{{ repoRef.repo }}
@@ -709,8 +713,8 @@ onKeyStroke(
:href="starsLink"
target="_blank"
rel="noopener noreferrer"
+ classicon="i-carbon:star"
>
-
{{ formatCompactNumber(stars, { decimals: 1 }) }}
@@ -720,8 +724,8 @@ onKeyStroke(
:href="forksLink"
target="_blank"
rel="noopener noreferrer"
+ classicon="i-carbon:fork"
>
-
{{ formatCompactNumber(forks, { decimals: 1 }) }}
@@ -731,8 +735,8 @@ onKeyStroke(
:href="homepageUrl"
target="_blank"
rel="noopener noreferrer"
+ classicon="i-carbon:link"
>
-
{{ $t('package.links.homepage') }}
@@ -742,8 +746,8 @@ onKeyStroke(
:href="displayVersion.bugs.url"
target="_blank"
rel="noopener noreferrer"
+ classicon="i-carbon:warning"
>
-
{{ $t('package.links.issues') }}
@@ -754,8 +758,8 @@ onKeyStroke(
target="_blank"
rel="noopener noreferrer"
:title="$t('common.view_on_npm')"
+ classicon="i-carbon:logo-npm"
>
-
npm
@@ -766,8 +770,8 @@ onKeyStroke(
target="_blank"
rel="noopener noreferrer"
:title="$t('badges.jsr.title')"
+ classicon="i-simple-icons:jsr"
>
-
{{ $t('package.links.jsr') }}
@@ -777,15 +781,14 @@ onKeyStroke(
:href="fundingUrl"
target="_blank"
rel="noopener noreferrer"
+ classicon="i-carbon:favorite"
>
-
{{ $t('package.links.fund') }}
-
-
+
{{ $t('package.links.docs') }}
@@ -793,8 +796,8 @@ onKeyStroke(
-
{{ $t('package.links.code') }}
@@ -802,8 +805,8 @@ onKeyStroke(
-
{{ $t('package.links.compare') }}
@@ -883,8 +886,8 @@ onKeyStroke(
target="_blank"
rel="noopener noreferrer"
:title="$t('package.stats.view_dependency_graph')"
+ classicon="i-carbon:network-3"
>
-
{{ $t('package.stats.view_dependency_graph') }}
@@ -895,8 +898,8 @@ onKeyStroke(
target="_blank"
rel="noopener noreferrer"
:title="$t('package.stats.inspect_dependency_tree')"
+ classicon="i-carbon:tree-view"
>
-
{{ $t('package.stats.inspect_dependency_tree') }}
From 886c60ea313b26e6ce1542644dcaf57b1ec77528 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 03:36:14 +0100
Subject: [PATCH 24/91] feat: automatically show external link icon
---
app/components/AppFooter.vue | 4 ----
app/components/Link/Base.vue | 6 ++++--
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/app/components/AppFooter.vue b/app/components/AppFooter.vue
index 1bf7e1cf1..0f64319eb 100644
--- a/app/components/AppFooter.vue
+++ b/app/components/AppFooter.vue
@@ -20,19 +20,15 @@ const isHome = computed(() => route.name === 'index')
{{ $t('footer.docs') }}
-
{{ $t('footer.source') }}
-
{{ $t('footer.social') }}
-
{{ $t('footer.chat') }}
-
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 802434fec..0848bb54d 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -47,11 +47,11 @@ const props = withDefaults(
/>
+
+
Date: Fri, 6 Feb 2026 03:44:44 +0100
Subject: [PATCH 25/91] feat: add button group
---
app/components/Button/Group.vue | 7 +++++++
app/pages/package/[...package].vue | 6 +++---
2 files changed, 10 insertions(+), 3 deletions(-)
create mode 100644 app/components/Button/Group.vue
diff --git a/app/components/Button/Group.vue b/app/components/Button/Group.vue
new file mode 100644
index 000000000..3af927c71
--- /dev/null
+++ b/app/components/Button/Group.vue
@@ -0,0 +1,7 @@
+
+
+
diff --git a/app/pages/package/[...package].vue b/app/pages/package/[...package].vue
index 138a682dd..18596b799 100644
--- a/app/pages/package/[...package].vue
+++ b/app/pages/package/[...package].vue
@@ -644,10 +644,10 @@ onKeyStroke(
-
+
From bf06a1e6f7e1cb5190c72ccb2bce1f2cf899b7cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 03:57:34 +0100
Subject: [PATCH 26/91] feat: automatically open all external links in new
window
---
app/components/AppFooter.vue | 8 ++--
app/components/Link/Base.vue | 12 ++++++
app/pages/about.vue | 16 ++++----
app/pages/package-code/[...path].vue | 6 ---
app/pages/package/[...package].vue | 55 ++++------------------------
5 files changed, 30 insertions(+), 67 deletions(-)
diff --git a/app/components/AppFooter.vue b/app/components/AppFooter.vue
index 0f64319eb..5ec73499e 100644
--- a/app/components/AppFooter.vue
+++ b/app/components/AppFooter.vue
@@ -18,16 +18,16 @@ const isHome = computed(() => route.name === 'index')
{{ $t('footer.about') }}
-
+
{{ $t('footer.docs') }}
-
+
{{ $t('footer.source') }}
-
+
{{ $t('footer.social') }}
-
+
{{ $t('footer.chat') }}
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 0848bb54d..02e6c08bc 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -21,6 +21,16 @@ const props = withDefaults(
*/
'aria-keyshortcuts'?: never
+ /**
+ * Don't use this directly. This will automatically be set to `_blank` if `href` for external links.
+ */
+ 'target'?: never
+
+ /**
+ * Don't use this directly. This will automatically be set to `_blank` if `href` for external links.
+ */
+ 'rel'?: never
+
'classicon'?: string
} &
/** This makes sure the link always has either `to` or `href` */
@@ -62,6 +72,8 @@ const props = withDefaults(
:to="to"
:href="href"
:aria-keyshortcuts="keyshortcut"
+ :target="href ? '_blank' : undefined"
+ :rel="href ? 'noopener noreferrer' : undefined"
>
{{ $t('about.what_we_are.better_ux_dx') }}
- JSR
+ JSR
@@ -108,32 +106,32 @@ const { data: contributors, status: contributorsStatus } = useFetch
{{ $t('about.what_we_are_not.words.already') }}
- {{
+ {{
$t('about.what_we_are_not.words.people')
}}
- {{
+ {{
$t('about.what_we_are_not.words.building')
}}
- {{
+ {{
$t('about.what_we_are_not.words.really')
}}
- {{
+ {{
$t('about.what_we_are_not.words.cool')
}}
- {{
+ {{
$t('about.what_we_are_not.words.package')
}}
- {{
+ {{
$t('about.what_we_are_not.words.managers')
}}
diff --git a/app/pages/package-code/[...path].vue b/app/pages/package-code/[...path].vue
index 1ed20fdba..b64b32f81 100644
--- a/app/pages/package-code/[...path].vue
+++ b/app/pages/package-code/[...path].vue
@@ -493,12 +493,9 @@ defineOgImageComponent('Default', {
{{ $t('code.view_raw') }}
-
@@ -548,12 +545,9 @@ defineOgImageComponent('Default', {
{{ $t('code.view_raw') }}
-
diff --git a/app/pages/package/[...package].vue b/app/pages/package/[...package].vue
index 18596b799..815b64f60 100644
--- a/app/pages/package/[...package].vue
+++ b/app/pages/package/[...package].vue
@@ -697,8 +697,6 @@ onKeyStroke(
@@ -708,35 +706,17 @@ onKeyStroke(
-
+
{{ formatCompactNumber(stars, { decimals: 1 }) }}
-
+
{{ formatCompactNumber(forks, { decimals: 1 }) }}
-
+
{{ $t('package.links.homepage') }}
@@ -744,8 +724,6 @@ onKeyStroke(
{{ $t('package.links.issues') }}
@@ -755,8 +733,6 @@ onKeyStroke(
@@ -767,8 +743,6 @@ onKeyStroke(
@@ -776,13 +750,7 @@ onKeyStroke(
-
+
{{ $t('package.links.fund') }}
@@ -883,8 +851,6 @@ onKeyStroke(
variant="tag"
v-if="getDependencyCount(displayVersion) > 0"
:href="`https://npmgraph.js.org/?q=${pkg.name}`"
- target="_blank"
- rel="noopener noreferrer"
:title="$t('package.stats.view_dependency_graph')"
classicon="i-carbon:network-3"
>
@@ -895,8 +861,6 @@ onKeyStroke(
variant="tag"
v-if="getDependencyCount(displayVersion) > 0"
:href="`https://node-modules.dev/grid/depth#install=${pkg.name}${resolvedVersion ? `@${resolvedVersion}` : ''}`"
- target="_blank"
- rel="noopener noreferrer"
:title="$t('package.stats.inspect_dependency_tree')"
classicon="i-carbon:tree-view"
>
@@ -1122,14 +1086,9 @@ onKeyStroke(
{{ $t('package.readme.no_readme') }}
- {{ $t('package.readme.view_on_github') }}
+ {{
+ $t('package.readme.view_on_github')
+ }}
Date: Fri, 6 Feb 2026 04:19:53 +0100
Subject: [PATCH 27/91] fix: layout
---
app/pages/package/[...package].vue | 55 ++++++++++++++++--------------
1 file changed, 29 insertions(+), 26 deletions(-)
diff --git a/app/pages/package/[...package].vue b/app/pages/package/[...package].vue
index 815b64f60..b9049f4a4 100644
--- a/app/pages/package/[...package].vue
+++ b/app/pages/package/[...package].vue
@@ -818,35 +818,38 @@ onKeyStroke(
{{ $t('package.stats.deps') }}
-
-
- {{ getDependencyCount(displayVersion) }}
+
+
+
+ {{ getDependencyCount(displayVersion) }}
-
-
- /
+
+
+ /
-
-
+
-
- {{ totalDepsCount }}
- -
-
- -
-
-
-
+ v-if="
+ vulnTreeStatus === 'pending' ||
+ (installSizeStatus === 'pending' && !vulnTree)
+ "
+ class="inline-flex items-center gap-1 text-fg-subtle"
+ >
+
+
+ {{ totalDepsCount }}
+ -
+
+ -
+
+
+
+
-
+
{{ $t('package.stats.inspect_dependency_tree') }}
-
+
From 1bfa878a047af7d2361977ad2c0061d568d13709 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 04:37:10 +0100
Subject: [PATCH 28/91] refactor: use design components for package sidebar
---
app/components/Link/Base.vue | 2 +-
app/components/Package/Dependencies.vue | 60 ++++------
app/components/Package/InstallScripts.vue | 4 +-
app/components/Package/Maintainers.vue | 37 +++---
app/components/Package/Versions.vue | 110 ++++++------------
.../Package/WeeklyDownloadStats.vue | 6 +-
6 files changed, 83 insertions(+), 136 deletions(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 02e6c08bc..c6fbeb5a1 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -59,7 +59,7 @@ const props = withDefaults(
v-else
class="group inline-flex gap-x-1 items-center justify-center"
:class="{
- 'text-fg underline-offset-4 underline decoration-1 decoration-fg/50 hover:(no-underline text-fg/80) transition-colors duration-200':
+ 'text-fg underline-offset-[0.2rem] underline decoration-1 decoration-fg/50 hover:(no-underline text-fg/80) transition-colors duration-200':
variant === 'link',
'gap-x-1 font-mono border border-border rounded-md transition-all duration-200 aria-current:(bg-fg text-bg border-fg hover:enabled:(text-bg/50))':
variant !== 'link',
diff --git a/app/components/Package/Dependencies.vue b/app/components/Package/Dependencies.vue
index 965a67712..41a56ac65 100644
--- a/app/components/Package/Dependencies.vue
+++ b/app/components/Package/Dependencies.vue
@@ -81,12 +81,9 @@ const sortedOptionalDependencies = computed(() => {
:key="dep"
class="flex items-center justify-between py-1 text-sm gap-2"
>
-
+
{{ dep }}
-
+
{
>
-
-
{{ $t('package.dependencies.view_vulnerabilities') }}
-
-
+
-
{{ $t('package.deprecated.label') }}
-
-
+
{{ version }}
-
+
({{ getOutdatedTooltip(outdatedDeps[dep], $t) }})
@@ -173,33 +170,29 @@ const sortedOptionalDependencies = computed(() => {
class="flex items-center justify-between py-1 text-sm gap-1 min-w-0"
>
-
{{ peer.name }}
-
-
+
+
{{ $t('package.dependencies.optional') }}
-
+
-
{{ peer.version }}
-
+
{
:key="dep"
class="flex items-center justify-between py-1 text-sm gap-2"
>
-
+
{{ dep }}
-
-
+
{{ version }}
-
+
{{
diff --git a/app/components/Package/InstallScripts.vue b/app/components/Package/InstallScripts.vue
index dde493782..492a202da 100644
--- a/app/components/Package/InstallScripts.vue
+++ b/app/components/Package/InstallScripts.vue
@@ -72,12 +72,12 @@ const isExpanded = shallowRef(false)
:key="dep"
class="flex items-center justify-between py-0.5 text-sm gap-2"
>
-
{{ dep }}
-
+
-
~{{ maintainer.name }}
-
+
{{ maintainer.email }}
@@ -214,10 +214,10 @@ watch(
-
-
+
-
{{
@@ -244,7 +242,7 @@ watch(
count: hiddenMaintainersCount,
})
}}
-
+
@@ -262,31 +260,24 @@ watch(
v-bind="noCorrect"
class="flex-1 px-2 py-1 font-mono text-sm bg-bg-subtle border border-border rounded text-fg placeholder:text-fg-subtle transition-colors duration-200 focus:border-border-hover focus-visible:outline-accent/70"
/>
-
+
{{ isAdding ? '…' : $t('package.maintainers.add_button') }}
-
-
+
-
-
+ iconclass="i-carbon-close"
+ />
-
{{ $t('package.maintainers.add_owner') }}
-
+
diff --git a/app/components/Package/Versions.vue b/app/components/Package/Versions.vue
index 9461da3d8..e114ebc45 100644
--- a/app/components/Package/Versions.vue
+++ b/app/components/Package/Versions.vue
@@ -307,16 +307,14 @@ function getTagVersions(tag: string): VersionDisplay[] {
id="versions"
>
-
-
{{ $t('package.downloads.community_distribution') }}
-
+
@@ -360,13 +358,11 @@ function getTagVersions(tag: string): VersionDisplay[] {
-
-
{{ row.primaryVersion.version }}
-
+
-
-
{{ v.version }}
-
+
-
-
{{ row.primaryVersion.version }}
-
+
-
-
{{ group.versions[0]?.version }}
-
+
-
-
{{ group.versions[0]?.version }}
-
+
-
-
{{ v.version }}
-
+
{
-
-
{{ $t('package.downloads.analyze') }}
-
+
From 930a25e3703d6ef4534eaeb711d45bc5b706c709 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 04:38:27 +0100
Subject: [PATCH 29/91] refactor: use design components in footer build infos
---
app/components/BuildEnvironment.vue | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)
diff --git a/app/components/BuildEnvironment.vue b/app/components/BuildEnvironment.vue
index 6482f2bb9..0483627ef 100644
--- a/app/components/BuildEnvironment.vue
+++ b/app/components/BuildEnvironment.vue
@@ -17,27 +17,19 @@ const buildInfo = useAppConfig().buildInfo
·
-
v{{ buildInfo.version }}
-
+
{{ buildInfo.env }}
·
-
+
{{ buildInfo.shortCommit }}
-
+
From 1a8ba38f700d69d0a16c1224c5b1ba48f3c2784b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 04:48:12 +0100
Subject: [PATCH 30/91] style: use accent colors for button and links
---
app/components/AppHeader.vue | 5 ++---
app/components/Button/Base.vue | 6 +++---
app/components/Header/AccountMenu.client.vue | 1 -
app/components/Link/Base.vue | 8 ++++----
4 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index 13a7b24d9..8cf600be8 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -183,9 +183,8 @@ onKeyStroke(
:aria-label="$t('nav.open_menu')"
:aria-expanded="showMobileMenu"
@click="showMobileMenu = !showMobileMenu"
- >
-
-
+ iconclass="i-carbon:menu"
+ />
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index e391310c9..44d8b7c7c 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -33,9 +33,9 @@ defineExpose({
:class="{
'text-sm px-4 py-2': variant !== 'tag',
'text-xs px-2 py-0.5': variant === 'tag',
- 'bg-bg-muted text-fg-muted hover:enabled:(text-fg border-border-hover)': variant === 'tag',
- 'text-bg bg-fg hover:enabled:(bg-fg/90)': variant === 'primary',
- 'bg-transparent text-fg hover:enabled:(bg-fg text-bg border-fg)': variant === 'secondary',
+ 'bg-transparent text-fg hover:enabled:(bg-accent/30 border-fg)':
+ variant === 'tag' || variant === 'secondary',
+ 'text-bg bg-accent hover:enabled:(bg-accent/50)': variant === 'primary',
}"
:type="props.type"
:disabled="disabled ? true : undefined"
diff --git a/app/components/Header/AccountMenu.client.vue b/app/components/Header/AccountMenu.client.vue
index b13b73dea..46ad71383 100644
--- a/app/components/Header/AccountMenu.client.vue
+++ b/app/components/Header/AccountMenu.client.vue
@@ -59,7 +59,6 @@ function openAuthModal() {
Date: Fri, 6 Feb 2026 04:51:00 +0100
Subject: [PATCH 31/91] style: re-add unified focus style
---
app/assets/main.css | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/app/assets/main.css b/app/assets/main.css
index 267f1c794..8d2fc03c2 100644
--- a/app/assets/main.css
+++ b/app/assets/main.css
@@ -181,6 +181,12 @@ body {
line-height: 1.6;
}
+*:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+ border-radius: 2px;
+}
+
/* Reset dd margin (browser default is margin-left: 40px) */
dd {
margin: 0;
From f0cc773f67ddacad5e1f52ac009306b020811ec7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 04:52:54 +0100
Subject: [PATCH 32/91] style: improve focus style
---
app/components/Button/Base.vue | 5 +++--
app/components/Link/Base.vue | 7 ++++---
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index 44d8b7c7c..e6ad62f5e 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -33,9 +33,10 @@ defineExpose({
:class="{
'text-sm px-4 py-2': variant !== 'tag',
'text-xs px-2 py-0.5': variant === 'tag',
- 'bg-transparent text-fg hover:enabled:(bg-accent/30 border-fg)':
+ 'bg-transparent text-fg hover:enabled:(bg-accent/30 border-fg) focus-visible:enabled:(bg-accent/30 border-fg)':
variant === 'tag' || variant === 'secondary',
- 'text-bg bg-accent hover:enabled:(bg-accent/50)': variant === 'primary',
+ 'text-bg bg-accent hover:enabled:(bg-accent/50) focus-visible:enabled:(bg-accent/50)':
+ variant === 'primary',
}"
:type="props.type"
:disabled="disabled ? true : undefined"
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index dccd88cd5..57892dd87 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -59,15 +59,16 @@ const props = withDefaults(
v-else
class="group inline-flex gap-x-1 items-center justify-center"
:class="{
- 'text-fg underline-offset-[0.2rem] underline decoration-1 decoration-fg/50 hover:(no-underline text-accent) transition-colors duration-200':
+ 'text-fg underline-offset-[0.2rem] underline decoration-1 decoration-fg/50 hover:(no-underline text-accent) focus-visible:(no-underline text-accent) transition-colors duration-200':
variant === 'link',
'gap-x-1 font-mono border border-border rounded-md transition-all duration-200 aria-current:(bg-fg text-bg border-fg hover:enabled:(text-bg/50))':
variant !== 'link',
'text-sm px-4 py-2': variant !== 'tag' && variant !== 'link',
'text-xs px-2 py-0.5': variant === 'tag',
- 'bg-transparent text-fg hover:(bg-accent/30 border-fg)':
+ 'bg-transparent text-fg hover:(bg-accent/30 border-fg) focus-visible:(bg-accent/30 border-fg)':
variant === 'tag' || variant === 'button-secondary',
- 'text-bg bg-fg hover:(bg-accent/90)': variant === 'button-primary',
+ 'text-bg bg-fg hover:(bg-accent/90) focus-visible:(bg-accent/90)':
+ variant === 'button-primary',
}"
:to="to"
:href="href"
From 1a73f88661e2a8dc03325ed832d1b4f8e6188544 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 05:18:02 +0100
Subject: [PATCH 33/91] style: make buttons and links look clickable
---
app/components/Button/Base.vue | 6 +++---
app/components/Link/Base.vue | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index e6ad62f5e..8600564ca 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -29,13 +29,13 @@ defineExpose({
Date: Fri, 6 Feb 2026 05:30:26 +0100
Subject: [PATCH 34/91] fix: minor fixes
---
app/components/AppHeader.vue | 14 ++------------
app/pages/index.vue | 2 +-
2 files changed, 3 insertions(+), 13 deletions(-)
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index 8cf600be8..043089038 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -152,22 +152,12 @@ onKeyStroke(
-
+
{{ $t('nav.compare') }}
-
+
{{ $t('nav.settings') }}
diff --git a/app/pages/index.vue b/app/pages/index.vue
index 78a272f69..a36a9710a 100644
--- a/app/pages/index.vue
+++ b/app/pages/index.vue
@@ -123,7 +123,7 @@ defineOgImageComponent('Default', {
Date: Fri, 6 Feb 2026 05:30:38 +0100
Subject: [PATCH 35/91] fix: l-to-r
---
app/components/Button/Group.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Button/Group.vue b/app/components/Button/Group.vue
index 3af927c71..1ea6a808c 100644
--- a/app/components/Button/Group.vue
+++ b/app/components/Button/Group.vue
@@ -1,6 +1,6 @@
From f65280b9c76ce529902cf6fa2704cfab53d66741 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 05:42:08 +0100
Subject: [PATCH 36/91] feat: add automatic anchor link design
---
app/components/Link/Base.vue | 30 ++++++++++++++++++++++++++----
app/pages/package/[...package].vue | 22 ++++------------------
2 files changed, 30 insertions(+), 22 deletions(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 53a3648d0..7cceb4e77 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -39,6 +39,17 @@ const props = withDefaults(
>(),
{ variant: 'link' },
)
+
+const isLinkExternal = computed(
+ () =>
+ !!props.href &&
+ typeof props.href === 'string' &&
+ !props.href.startsWith('/') &&
+ !props.href.startsWith('#'),
+)
+const isLinkAnchor = computed(
+ () => !!props.href && typeof props.href === 'string' && props.href.startsWith('#'),
+)
@@ -59,7 +70,9 @@ const props = withDefaults(
v-else
class="group inline-flex gap-x-1 items-center justify-center"
:class="{
- 'text-fg underline-offset-[0.2rem] underline decoration-1 decoration-fg/50 hover:(no-underline text-accent) focus-visible:(no-underline text-accent) transition-colors duration-200':
+ 'underline-offset-[0.2rem] underline decoration-1 decoration-fg/50':
+ !isLinkAnchor && variant === 'link',
+ 'text-fg hover:(no-underline text-accent) focus-visible:(no-underline text-accent) transition-colors duration-200':
variant === 'link',
'font-mono border border-border rounded-md transition-all duration-200 aria-current:(bg-fg text-bg border-fg hover:(text-bg/50)) bg-gradient-to-t dark:bg-gradient-to-b':
variant !== 'link',
@@ -73,8 +86,8 @@ const props = withDefaults(
:to="to"
:href="href"
:aria-keyshortcuts="keyshortcut"
- :target="href ? '_blank' : undefined"
- :rel="href ? 'noopener noreferrer' : undefined"
+ :target="isLinkExternal ? '_blank' : undefined"
+ :rel="isLinkExternal ? 'noopener noreferrer' : undefined"
>
-
+
+
-
+
{{ $t('package.get_started.title') }}
-
-
+
@@ -1064,16 +1057,9 @@ onKeyStroke(
From 3654cd482a38f78e3558518be0659c9c054cf837 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 06:09:57 +0100
Subject: [PATCH 43/91] fix: remove stale reference
---
app/components/Link/Base.vue | 2 --
1 file changed, 2 deletions(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 6ac9d5770..97b9cf005 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -8,8 +8,6 @@ const props = withDefaults(
'disabled'?: boolean
/**
* `type` should never be used, because this will always be a link.
- *
- * If you want a button use `TagButton` instead.
* */
'type'?: never
'variant'?: 'button-primary' | 'button-secondary' | 'tag' | 'link'
From 1d2d1ba018322fa267f112d889f746d94dda3f58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 06:15:42 +0100
Subject: [PATCH 44/91] refactor: streamline link props and change how external
links are recognized
---
app/app.vue | 2 +-
app/components/AppFooter.vue | 8 ++++----
app/components/BuildEnvironment.vue | 4 ++--
app/components/Link/Base.vue | 16 +++++++++-------
app/components/Package/Versions.vue | 2 +-
app/pages/about.vue | 14 +++++++-------
app/pages/package-code/[...path].vue | 4 ++--
app/pages/package/[...package].vue | 26 +++++++++++++-------------
test/nuxt/a11y.spec.ts | 12 ++++++------
9 files changed, 45 insertions(+), 43 deletions(-)
diff --git a/app/app.vue b/app/app.vue
index 8e85ccfcc..d5d23ab1b 100644
--- a/app/app.vue
+++ b/app/app.vue
@@ -121,7 +121,7 @@ if (import.meta.client) {
- {{
+ {{
$t('common.skip_link')
}}
diff --git a/app/components/AppFooter.vue b/app/components/AppFooter.vue
index 5ec73499e..346c33ef6 100644
--- a/app/components/AppFooter.vue
+++ b/app/components/AppFooter.vue
@@ -18,16 +18,16 @@ const isHome = computed(() => route.name === 'index')
{{ $t('footer.about') }}
-
+
{{ $t('footer.docs') }}
-
+
{{ $t('footer.source') }}
-
+
{{ $t('footer.social') }}
-
+
{{ $t('footer.chat') }}
diff --git a/app/components/BuildEnvironment.vue b/app/components/BuildEnvironment.vue
index 0483627ef..1ca80c517 100644
--- a/app/components/BuildEnvironment.vue
+++ b/app/components/BuildEnvironment.vue
@@ -19,7 +19,7 @@ const buildInfo = useAppConfig().buildInfo
·
v{{ buildInfo.version }}
@@ -27,7 +27,7 @@ const buildInfo = useAppConfig().buildInfo
·
-
+
{{ buildInfo.shortCommit }}
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 97b9cf005..d5a9bded6 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -32,7 +32,9 @@ const props = withDefaults(
'classicon'?: string
'to'?: NuxtLinkProps['to']
- 'href'?: NuxtLinkProps['href']
+
+ /** always use `to` instead of `href` */
+ 'href'?: never
} & NuxtLinkProps
>(),
{ variant: 'link' },
@@ -40,13 +42,12 @@ const props = withDefaults(
const isLinkExternal = computed(
() =>
- !!props.href &&
- typeof props.href === 'string' &&
- !props.href.startsWith('/') &&
- !props.href.startsWith('#'),
+ !!props.to &&
+ typeof props.to === 'string' &&
+ (props.to.startsWith('http:') || props.to.startsWith('https:') || props.to.startsWith('//')),
)
const isLinkAnchor = computed(
- () => !!props.href && typeof props.href === 'string' && props.href.startsWith('#'),
+ () => !!props.to && typeof props.to === 'string' && props.to.startsWith('#'),
)
@@ -82,7 +83,8 @@ const isLinkAnchor = computed(
variant === 'button-primary',
}"
:to="to"
- :href="href"
+ :href="to"
+ :external="isLinkExternal"
:aria-keyshortcuts="keyshortcut"
:target="isLinkExternal ? '_blank' : undefined"
:rel="isLinkExternal ? 'noopener noreferrer' : undefined"
diff --git a/app/components/Package/Versions.vue b/app/components/Package/Versions.vue
index e114ebc45..cb0e7cd56 100644
--- a/app/components/Package/Versions.vue
+++ b/app/components/Package/Versions.vue
@@ -309,7 +309,7 @@ function getTagVersions(tag: string): VersionDisplay[] {
diff --git a/app/pages/about.vue b/app/pages/about.vue
index 36f95ccd8..21435aab3 100644
--- a/app/pages/about.vue
+++ b/app/pages/about.vue
@@ -74,7 +74,7 @@ const { data: contributors, status: contributorsStatus } = useFetch{{ $t('about.what_we_are.better_ux_dx') }}
- JSR
+ JSR
@@ -106,32 +106,32 @@ const { data: contributors, status: contributorsStatus } = useFetch
{{ $t('about.what_we_are_not.words.already') }}
- {{
+ {{
$t('about.what_we_are_not.words.people')
}}
- {{
+ {{
$t('about.what_we_are_not.words.building')
}}
- {{
+ {{
$t('about.what_we_are_not.words.really')
}}
- {{
+ {{
$t('about.what_we_are_not.words.cool')
}}
- {{
+ {{
$t('about.what_we_are_not.words.package')
}}
- {{
+ {{
$t('about.what_we_are_not.words.managers')
}}
diff --git a/app/pages/package-code/[...path].vue b/app/pages/package-code/[...path].vue
index b64b32f81..893c1d3d1 100644
--- a/app/pages/package-code/[...path].vue
+++ b/app/pages/package-code/[...path].vue
@@ -492,7 +492,7 @@ defineOgImageComponent('Default', {
{{ $t('code.view_raw') }}
@@ -544,7 +544,7 @@ defineOgImageComponent('Default', {
{{ $t('code.unavailable_hint') }}
{{ $t('code.view_raw') }}
diff --git a/app/pages/package/[...package].vue b/app/pages/package/[...package].vue
index 3a2907010..d364ae80f 100644
--- a/app/pages/package/[...package].vue
+++ b/app/pages/package/[...package].vue
@@ -574,7 +574,7 @@ onKeyStroke(
>
@@ -696,7 +696,7 @@ onKeyStroke(
@@ -706,24 +706,24 @@ onKeyStroke(
-
+
{{ formatCompactNumber(stars, { decimals: 1 }) }}
-
+
{{ formatCompactNumber(forks, { decimals: 1 }) }}
-
+
{{ $t('package.links.homepage') }}
{{ $t('package.links.issues') }}
@@ -732,7 +732,7 @@ onKeyStroke(
@@ -742,7 +742,7 @@ onKeyStroke(
@@ -750,7 +750,7 @@ onKeyStroke(
-
+
{{ $t('package.links.fund') }}
@@ -853,7 +853,7 @@ onKeyStroke(
@@ -863,7 +863,7 @@ onKeyStroke(
@@ -1011,7 +1011,7 @@ onKeyStroke(
id="get-started-heading"
class="group text-xs text-fg-subtle uppercase tracking-wider"
>
-
+
{{ $t('package.get_started.title') }}
@@ -1057,7 +1057,7 @@ onKeyStroke(
-
+
{{ $t('package.readme.title') }}
diff --git a/test/nuxt/a11y.spec.ts b/test/nuxt/a11y.spec.ts
index 21427c326..8e4d2a2d5 100644
--- a/test/nuxt/a11y.spec.ts
+++ b/test/nuxt/a11y.spec.ts
@@ -330,7 +330,7 @@ describe('component accessibility audits', () => {
describe('LinkBase', () => {
it('should have no accessibility violations', async () => {
const component = await mountSuspended(LinkBase, {
- props: { href: 'http://example.com' },
+ props: { to: 'http://example.com' },
slots: { default: 'Button link content' },
})
const results = await runAxe(component)
@@ -339,7 +339,7 @@ describe('component accessibility audits', () => {
it("should have no accessibility violations when it's the current link", async () => {
const component = await mountSuspended(LinkBase, {
- props: { href: 'http://example.com', current: true },
+ props: { to: 'http://example.com', current: true },
slots: { default: 'Button link content' },
})
const results = await runAxe(component)
@@ -348,7 +348,7 @@ describe('component accessibility audits', () => {
it('should have no accessibility violations when disabled (plain text)', async () => {
const component = await mountSuspended(LinkBase, {
- props: { href: 'http://example.com', disabled: true },
+ props: { to: 'http://example.com', disabled: true },
slots: { default: 'Button link content' },
})
const results = await runAxe(component)
@@ -357,7 +357,7 @@ describe('component accessibility audits', () => {
it('should have no accessibility violations as secondary button', async () => {
const component = await mountSuspended(LinkBase, {
- props: { href: 'http://example.com', disabled: true, variant: 'button-secondary' },
+ props: { to: 'http://example.com', disabled: true, variant: 'button-secondary' },
slots: { default: 'Button link content' },
})
const results = await runAxe(component)
@@ -366,7 +366,7 @@ describe('component accessibility audits', () => {
it('should have no accessibility violations as primary button', async () => {
const component = await mountSuspended(LinkBase, {
- props: { href: 'http://example.com', disabled: true, variant: 'button-primary' },
+ props: { to: 'http://example.com', disabled: true, variant: 'button-primary' },
slots: { default: 'Button link content' },
})
const results = await runAxe(component)
@@ -375,7 +375,7 @@ describe('component accessibility audits', () => {
it('should have no accessibility violations as tag', async () => {
const component = await mountSuspended(LinkBase, {
- props: { href: 'http://example.com', disabled: true, variant: 'tag' },
+ props: { to: 'http://example.com', disabled: true, variant: 'tag' },
slots: { default: 'Button link content' },
})
const results = await runAxe(component)
From 8992ed528d421f81b10f7ca7eb4ada5cf52c17f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 06:17:44 +0100
Subject: [PATCH 45/91] fix: prop name
---
app/components/AppHeader.vue | 2 +-
app/components/Package/Dependencies.vue | 4 ++--
app/components/Package/Maintainers.vue | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index 043089038..8ced7b309 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -173,7 +173,7 @@ onKeyStroke(
:aria-label="$t('nav.open_menu')"
:aria-expanded="showMobileMenu"
@click="showMobileMenu = !showMobileMenu"
- iconclass="i-carbon:menu"
+ classicon="i-carbon:menu"
/>
diff --git a/app/components/Package/Dependencies.vue b/app/components/Package/Dependencies.vue
index 41a56ac65..f18a415c1 100644
--- a/app/components/Package/Dependencies.vue
+++ b/app/components/Package/Dependencies.vue
@@ -103,7 +103,7 @@ const sortedOptionalDependencies = computed(() => {
class="shrink-0"
:class="SEVERITY_TEXT_COLORS[getHighestSeverity(getVulnerableDepInfo(dep)!.counts)]"
:title="`${getVulnerableDepInfo(dep)!.counts.total} vulnerabilities`"
- iconclass="i-carbon:security"
+ classicon="i-carbon:security"
>
{{ $t('package.dependencies.view_vulnerabilities') }}
@@ -115,7 +115,7 @@ const sortedOptionalDependencies = computed(() => {
}"
class="shrink-0 text-purple-500"
:title="getDeprecatedDepInfo(dep)!.message"
- iconclass="i-carbon:warning-hex"
+ classicon="i-carbon:warning-hex"
>
{{ $t('package.deprecated.label') }}
diff --git a/app/components/Package/Maintainers.vue b/app/components/Package/Maintainers.vue
index b222eab80..68a5f1d75 100644
--- a/app/components/Package/Maintainers.vue
+++ b/app/components/Package/Maintainers.vue
@@ -266,7 +266,7 @@ watch(
From e70ef85f8aea0ab31b5a3c2e1894df3bca68f7c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 06:18:27 +0100
Subject: [PATCH 46/91] fix: remove unnecessary class
---
app/components/Package/Maintainers.vue | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/app/components/Package/Maintainers.vue b/app/components/Package/Maintainers.vue
index 68a5f1d75..5c7928cec 100644
--- a/app/components/Package/Maintainers.vue
+++ b/app/components/Package/Maintainers.vue
@@ -270,12 +270,7 @@ watch(
/>
-
+
{{ $t('package.maintainers.add_owner') }}
From ff7a8b6d88625b2a4716d994f54c84e3c5a1eb64 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 06:29:48 +0100
Subject: [PATCH 47/91] fix: app header menu on mobile
---
app/components/AppHeader.vue | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index 8ced7b309..c6b7e8c00 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -150,7 +150,7 @@ onKeyStroke(
-
+
{{ $t('nav.compare') }}
@@ -161,21 +161,18 @@ onKeyStroke(
{{ $t('nav.settings') }}
-
-
-
-
-
-
-
+
+
+
+
From 5d23f56fef7a4489d0043fa405ed9549592a6521 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 06:33:15 +0100
Subject: [PATCH 48/91] style: move menu to button group
---
app/components/AppHeader.vue | 4 ++--
app/components/Header/AccountMenu.client.vue | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index c6b7e8c00..a43416eb7 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -150,7 +150,7 @@ onKeyStroke(
-
+
{{ $t('nav.compare') }}
@@ -162,7 +162,7 @@ onKeyStroke(
-
+
Date: Fri, 6 Feb 2026 10:11:10 +0100
Subject: [PATCH 49/91] test: ignore button group for a11y tests
---
test/unit/a11y-component-coverage.spec.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/test/unit/a11y-component-coverage.spec.ts b/test/unit/a11y-component-coverage.spec.ts
index 42502bc41..0cc0e40e5 100644
--- a/test/unit/a11y-component-coverage.spec.ts
+++ b/test/unit/a11y-component-coverage.spec.ts
@@ -43,6 +43,7 @@ const SKIPPED_COMPONENTS: Record = {
'UserCombobox.vue': 'Unused component - intended for future admin features',
'SkeletonBlock.vue': 'Already covered indirectly via other component tests',
'SkeletonInline.vue': 'Already covered indirectly via other component tests',
+ 'Button/Group.vue': "Wrapper component, tests wouldn't make much sense here",
}
/**
From 45fdd7155a143897792fcee48b6eb27e8956687b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 10:25:36 +0100
Subject: [PATCH 50/91] fix: wrong element type
---
app/components/AppHeader.vue | 2 +-
app/components/Button/Group.vue | 11 +++++++++--
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index a43416eb7..7bd4d98f1 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -150,7 +150,7 @@ onKeyStroke(
-
+
{{ $t('nav.compare') }}
diff --git a/app/components/Button/Group.vue b/app/components/Button/Group.vue
index 1ea6a808c..166e7b403 100644
--- a/app/components/Button/Group.vue
+++ b/app/components/Button/Group.vue
@@ -1,7 +1,14 @@
+
+
-
+
From edc4e21d393362c94ee8acf386df4b30d4c19c96 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 12:53:32 +0100
Subject: [PATCH 51/91] refactoring
Co-authored-by: Robin
---
app/components/Button/Base.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index f5668bdb4..65fa78ab4 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -19,7 +19,7 @@ const props = withDefaults(
},
)
-const el = ref(null)
+const el = useTemplateRef('el')
defineExpose({
focus: () => el.value?.focus(),
From 54b044bc3ba6e8dad5937152fa1d1669b504cbb2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 13:14:32 +0100
Subject: [PATCH 52/91] style: change package links back to link style
---
app/pages/package/[[org]]/[name].vue | 32 ++++++++++------------------
1 file changed, 11 insertions(+), 21 deletions(-)
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index 5ec2de0df..06d29d65c 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -692,13 +692,9 @@ onKeyStroke(
-
+
-
-
+
{{ repoRef.owner }}/{{ repoRef.repo }}
@@ -706,32 +702,27 @@ onKeyStroke(
-
-
+
{{ formatCompactNumber(stars, { decimals: 1 }) }}
-
-
+
{{ formatCompactNumber(forks, { decimals: 1 }) }}
-
-
+
{{ $t('package.links.homepage') }}
-
-
+
{{ $t('package.links.issues') }}
-
-
-
-
+
{{ $t('package.links.fund') }}
-
-
+
{{ $t('package.links.docs') }}
-
@@ -771,7 +760,6 @@ onKeyStroke(
-
@@ -1189,7 +1177,9 @@ onKeyStroke(
{{ error?.message ?? $t('package.not_found_message') }}
- {{ $t('common.go_back_home') }}
+ {{
+ $t('common.go_back_home')
+ }}
From e84b59c430079798ac920ebd93d642bd9317279b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 13:18:57 +0100
Subject: [PATCH 53/91] test: fix copy-paste error with test props
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---
test/nuxt/a11y.spec.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/nuxt/a11y.spec.ts b/test/nuxt/a11y.spec.ts
index b6747cfff..5bd100b2f 100644
--- a/test/nuxt/a11y.spec.ts
+++ b/test/nuxt/a11y.spec.ts
@@ -310,7 +310,7 @@ describe('component accessibility audits', () => {
it('should have no accessibility violations as primary button', async () => {
const component = await mountSuspended(ButtonBase, {
- props: { disabled: true, variant: 'primary' },
+ props: { variant: 'primary' },
slots: { default: 'Button content' },
})
const results = await runAxe(component)
@@ -319,7 +319,7 @@ describe('component accessibility audits', () => {
it('should have no accessibility violations as tag', async () => {
const component = await mountSuspended(ButtonBase, {
- props: { disabled: true, variant: 'tag' },
+ props: { variant: 'tag' },
slots: { default: 'Button content' },
})
const results = await runAxe(component)
From e96ae1a6ae57a2168aa5501825b9e6dc12dfcc16 Mon Sep 17 00:00:00 2001
From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com>
Date: Fri, 6 Feb 2026 12:19:54 +0000
Subject: [PATCH 54/91] [autofix.ci] apply automated fixes
---
app/components/Package/Dependencies.vue | 11 ++---------
app/pages/index.vue | 5 +----
app/pages/org/[org].vue | 4 +++-
app/pages/package-code/[...path].vue | 4 ----
app/pages/~[username]/index.vue | 4 +++-
app/pages/~[username]/orgs.vue | 3 ++-
6 files changed, 11 insertions(+), 20 deletions(-)
diff --git a/app/components/Package/Dependencies.vue b/app/components/Package/Dependencies.vue
index e9b80c152..6ccf43a6c 100644
--- a/app/components/Package/Dependencies.vue
+++ b/app/components/Package/Dependencies.vue
@@ -161,10 +161,7 @@ const sortedOptionalDependencies = computed(() => {
class="flex items-center justify-between py-1 text-sm gap-1 min-w-0"
>
-
+
{{ peer.name }}
@@ -219,11 +216,7 @@ const sortedOptionalDependencies = computed(() => {
{{ dep }}
-
+
{{ version }}
diff --git a/app/pages/index.vue b/app/pages/index.vue
index 35521d0d1..87323a933 100644
--- a/app/pages/index.vue
+++ b/app/pages/index.vue
@@ -121,10 +121,7 @@ defineOgImageComponent('Default', {
>
-
-
+
diff --git a/app/pages/org/[org].vue b/app/pages/org/[org].vue
index c56340423..08739fd43 100644
--- a/app/pages/org/[org].vue
+++ b/app/pages/org/[org].vue
@@ -244,7 +244,9 @@ defineOgImageComponent('Default', {
{{ error?.message ?? $t('org.page.failed_to_load') }}
- {{ $t('common.go_back_home') }}
+ {{
+ $t('common.go_back_home')
+ }}
diff --git a/app/pages/package-code/[...path].vue b/app/pages/package-code/[...path].vue
index 7a255cfe3..b9d4885dd 100644
--- a/app/pages/package-code/[...path].vue
+++ b/app/pages/package-code/[...path].vue
@@ -371,9 +371,7 @@ defineOgImageComponent('Default', {
{{ $t('code.version_required') }}
{{
-
$t('code.go_to_package')
-
}}
@@ -387,9 +385,7 @@ defineOgImageComponent('Default', {
{{ $t('code.failed_to_load_tree') }}
{{
-
$t('code.back_to_package')
-
}}
diff --git a/app/pages/~[username]/index.vue b/app/pages/~[username]/index.vue
index 27cd363b0..c4cab4920 100644
--- a/app/pages/~[username]/index.vue
+++ b/app/pages/~[username]/index.vue
@@ -228,7 +228,9 @@ defineOgImageComponent('Default', {
{{ error?.message ?? $t('user.page.failed_to_load') }}
- {{ $t('common.go_back_home') }}
+ {{
+ $t('common.go_back_home')
+ }}
diff --git a/app/pages/~[username]/orgs.vue b/app/pages/~[username]/orgs.vue
index c29fd52ba..06c7f6ad2 100644
--- a/app/pages/~[username]/orgs.vue
+++ b/app/pages/~[username]/orgs.vue
@@ -160,7 +160,8 @@ defineOgImageComponent('Default', {
{{ $t('user.orgs_page.own_orgs_only') }}
-
{{ $t('user.orgs_page.view_your_orgs') }}
Date: Fri, 6 Feb 2026 13:21:10 +0100
Subject: [PATCH 55/91] fix: footer links
---
app/components/AppFooter.vue | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/components/AppFooter.vue b/app/components/AppFooter.vue
index 315746d04..8f53430a0 100644
--- a/app/components/AppFooter.vue
+++ b/app/components/AppFooter.vue
@@ -15,9 +15,12 @@ const isHome = computed(() => route.name === 'index')
-
+
{{ $t('footer.about') }}
+
+ {{ $t('privacy_policy.title') }}
+
{{ $t('footer.docs') }}
From 952a695192297416ae1cfd738648b6e6c011e27e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 13:30:42 +0100
Subject: [PATCH 56/91] docs: add comment explaining explicit attr
---
app/components/Button/Base.vue | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index 65fa78ab4..927c6a8b9 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -39,7 +39,15 @@ defineExpose({
variant === 'primary',
}"
:type="props.type"
- :disabled="disabled ? true : undefined"
+ :disabled="
+ /**
+ * Unfortunately Vue _sometimes_ doesn't handle `disabled` correct,
+ * resulting in an invalid `disabled=false` attribute in the final HTML.
+ *
+ * This fixes this.
+ */
+ disabled ? true : undefined
+ "
:aria-keyshortcuts="keyshortcut"
>
Date: Fri, 6 Feb 2026 13:32:35 +0100
Subject: [PATCH 57/91] refactor: rename tag variant
---
app/components/Package/MetricsBadges.vue | 6 +++---
app/components/Tag/Static.vue | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/app/components/Package/MetricsBadges.vue b/app/components/Package/MetricsBadges.vue
index d325c92d9..1f547ef17 100644
--- a/app/components/Package/MetricsBadges.vue
+++ b/app/components/Package/MetricsBadges.vue
@@ -63,7 +63,7 @@ const typesHref = computed(() => {
(),
@@ -14,7 +14,7 @@ const props = withDefaults(
From c8420d252cd469ae40cb5b3bb7fbe4060dde1ce7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 13:47:55 +0100
Subject: [PATCH 58/91] refactor: change props for buttons and links
---
app/components/Button/Base.vue | 12 ++++----
app/components/Filter/Panel.vue | 2 +-
app/components/Link/Base.vue | 35 ++++++++++++++----------
app/components/Package/Card.vue | 2 +-
app/components/Package/Keywords.vue | 6 +++-
app/components/Package/MetricsBadges.vue | 8 +++++-
app/components/Package/TableRow.vue | 2 +-
app/pages/package/[[org]]/[name].vue | 11 +++++---
test/nuxt/a11y.spec.ts | 13 ++++++---
9 files changed, 58 insertions(+), 33 deletions(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index 927c6a8b9..accc4ca73 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -3,7 +3,8 @@ const props = withDefaults(
defineProps<{
'disabled'?: boolean
'type'?: 'button' | 'submit'
- 'variant'?: 'primary' | 'secondary' | 'tag'
+ 'variant'?: 'primary' | 'secondary'
+ 'size'?: 'small' | 'medium'
'keyshortcut'?: string
/**
@@ -16,6 +17,7 @@ const props = withDefaults(
{
type: 'button',
variant: 'secondary',
+ size: 'medium',
},
)
@@ -31,10 +33,10 @@ defineExpose({
ref="el"
class="group cursor-pointer inline-flex gap-x-1 items-center justify-center font-mono border border-border rounded-md transition-all duration-200 disabled:(opacity-40 cursor-not-allowed border-transparent) aria-pressed:(bg-fg text-bg border-fg hover:enabled:(text-bg/50)) bg-gradient-to-t dark:bg-gradient-to-b"
:class="{
- 'text-sm px-4 py-2': variant !== 'tag',
- 'text-xs px-2 py-0.5': variant === 'tag',
+ 'text-sm px-4 py-2': size === 'medium',
+ 'text-xs px-2 py-0.5': size === 'small',
'from-fg/10 via-transparent to-transparent text-fg hover:enabled:(bg-accent/20 border-accent) focus-visible:enabled:(bg-accent/20 border-accent)':
- variant === 'tag' || variant === 'secondary',
+ variant === 'secondary',
'text-black from-accent via-accent to-accent/30 hover:enabled:(bg-accent/50) focus-visible:enabled:(bg-accent/50)':
variant === 'primary',
}"
@@ -52,7 +54,7 @@ defineExpose({
>
diff --git a/app/components/Filter/Panel.vue b/app/components/Filter/Panel.vue
index a824dcd28..3d3a1bdb1 100644
--- a/app/components/Filter/Panel.vue
+++ b/app/components/Filter/Panel.vue
@@ -310,7 +310,7 @@ const hasActiveFilters = computed(() => !!filterSummary.value)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index d5a9bded6..f246ec636 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -10,7 +10,8 @@ const props = withDefaults(
* `type` should never be used, because this will always be a link.
* */
'type'?: never
- 'variant'?: 'button-primary' | 'button-secondary' | 'tag' | 'link'
+ 'variant'?: 'button-primary' | 'button-secondary' | 'link'
+ 'size'?: 'small' | 'medium'
'keyshortcut'?: string
@@ -37,7 +38,7 @@ const props = withDefaults(
'href'?: never
} & NuxtLinkProps
>(),
- { variant: 'link' },
+ { variant: 'link', size: 'medium' },
)
const isLinkExternal = computed(
@@ -49,6 +50,12 @@ const isLinkExternal = computed(
const isLinkAnchor = computed(
() => !!props.to && typeof props.to === 'string' && props.to.startsWith('#'),
)
+
+/** size is only applicable for button like links */
+const isLink = computed(() => props.variant === 'link')
+const isButton = computed(() => props.variant !== 'link')
+const isButtonSmall = computed(() => props.size === 'small' && props.variant !== 'link')
+const isButtonMedium = computed(() => props.size === 'medium' && props.variant !== 'link')
@@ -56,10 +63,9 @@ const isLinkAnchor = computed(
v-if="disabled"
:class="{
'opacity-50 inline-flex gap-x-1 items-center justify-center font-mono border border-transparent rounded-md':
- variant !== 'link',
- 'text-sm px-4 py-2': variant !== 'tag' && variant !== 'link',
- 'text-xs px-2 py-0.5': variant === 'tag',
- 'bg-bg-muted text-fg-muted': variant === 'tag',
+ isButton,
+ 'text-sm px-4 py-2': isButtonMedium,
+ 'text-xs px-2 py-0.5': isButtonSmall,
'text-bg bg-fg': variant === 'button-primary',
'bg-transparent text-fg': variant === 'button-secondary',
}"
@@ -69,16 +75,15 @@ const isLinkAnchor = computed(
v-else
class="group inline-flex gap-x-1 items-center justify-center"
:class="{
- 'underline-offset-[0.2rem] underline decoration-1 decoration-fg/50':
- !isLinkAnchor && variant === 'link',
+ 'underline-offset-[0.2rem] underline decoration-1 decoration-fg/50': !isLinkAnchor && isLink,
'text-fg hover:(no-underline text-accent) focus-visible:(no-underline text-accent) transition-colors duration-200':
- variant === 'link',
+ isLink,
'font-mono border border-border rounded-md transition-all duration-200 aria-current:(bg-fg text-bg border-fg hover:(text-bg/50)) bg-gradient-to-t dark:bg-gradient-to-b':
- variant !== 'link',
- 'text-sm px-4 py-2': variant !== 'tag' && variant !== 'link',
- 'text-xs px-2 py-0.5': variant === 'tag',
+ isButton,
+ 'text-sm px-4 py-2': isButtonMedium,
+ 'text-xs px-2 py-0.5': isButtonSmall,
'from-fg/10 via-transparent to-transparent text-fg hover:(bg-accent/20 border-accent) focus-visible:(bg-accent/20 border-accent)':
- variant === 'tag' || variant === 'button-secondary',
+ variant === 'button-secondary',
'text-black from-accent via-accent to-accent/30 hover:(bg-accent/50) focus-visible:(bg-accent/50)':
variant === 'button-primary',
}"
@@ -91,7 +96,7 @@ const isLinkAnchor = computed(
>
@@ -102,7 +107,7 @@ const isLinkAnchor = computed(
aria-hidden="true"
/>
diff --git a/app/components/Package/Card.vue b/app/components/Package/Card.vue
index 4ab94e537..330792716 100644
--- a/app/components/Package/Card.vue
+++ b/app/components/Package/Card.vue
@@ -165,7 +165,7 @@ const pkgDescription = useMarkdown(() => ({
-
-
+
{{ keyword }}
diff --git a/app/components/Package/MetricsBadges.vue b/app/components/Package/MetricsBadges.vue
index 1f547ef17..356047315 100644
--- a/app/components/Package/MetricsBadges.vue
+++ b/app/components/Package/MetricsBadges.vue
@@ -58,7 +58,13 @@ const typesHref = computed(() => {
-
-
+
{{ $t('package.metrics.types_label') }}
{
{
expect(results.violations).toEqual([])
})
- it('should have no accessibility violations as tag', async () => {
+ it('should have no accessibility violations with size small', async () => {
const component = await mountSuspended(ButtonBase, {
- props: { variant: 'tag' },
+ props: { size: 'small' },
slots: { default: 'Button content' },
})
const results = await runAxe(component)
@@ -373,9 +373,14 @@ describe('component accessibility audits', () => {
expect(results.violations).toEqual([])
})
- it('should have no accessibility violations as tag', async () => {
+ it('should have no accessibility violations as small button', async () => {
const component = await mountSuspended(LinkBase, {
- props: { to: 'http://example.com', disabled: true, variant: 'tag' },
+ props: {
+ to: 'http://example.com',
+ disabled: true,
+ variant: 'button-secondary',
+ size: 'small',
+ },
slots: { default: 'Button link content' },
})
const results = await runAxe(component)
From 1fade1ee3a342c24ab491cdcbbf52148176c21e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 13:56:34 +0100
Subject: [PATCH 59/91] feat: remove non-working aria-current styling
---
app/components/Link/Base.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index f246ec636..abec440b8 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -78,7 +78,7 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
'underline-offset-[0.2rem] underline decoration-1 decoration-fg/50': !isLinkAnchor && isLink,
'text-fg hover:(no-underline text-accent) focus-visible:(no-underline text-accent) transition-colors duration-200':
isLink,
- 'font-mono border border-border rounded-md transition-all duration-200 aria-current:(bg-fg text-bg border-fg hover:(text-bg/50)) bg-gradient-to-t dark:bg-gradient-to-b':
+ 'font-mono border border-border rounded-md transition-all duration-200 bg-gradient-to-t dark:bg-gradient-to-b':
isButton,
'text-sm px-4 py-2': isButtonMedium,
'text-xs px-2 py-0.5': isButtonSmall,
From bed8f81a00cb4f82ad847d61e572343496c9e3cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 13:59:23 +0100
Subject: [PATCH 60/91] docs: update comment
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---
app/components/Link/Base.vue | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index abec440b8..ccc7a6dd3 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -21,12 +21,12 @@ const props = withDefaults(
'aria-keyshortcuts'?: never
/**
- * Don't use this directly. This will automatically be set to `_blank` if `href` for external links.
+ * Don't use this directly. This will automatically be set to `_blank` for external links passed via `to`.
*/
'target'?: never
/**
- * Don't use this directly. This will automatically be set to `_blank` if `href` for external links.
+ * Don't use this directly. This will automatically be set for external links passed via `to`.
*/
'rel'?: never
From c0967c9622c2b6419e542e90af16ed1a7d52191d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 14:18:28 +0100
Subject: [PATCH 61/91] style: remove highlight border from buttons
---
app/components/Button/Base.vue | 2 +-
app/components/Link/Base.vue | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index accc4ca73..8e3045f86 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -35,7 +35,7 @@ defineExpose({
:class="{
'text-sm px-4 py-2': size === 'medium',
'text-xs px-2 py-0.5': size === 'small',
- 'from-fg/10 via-transparent to-transparent text-fg hover:enabled:(bg-accent/20 border-accent) focus-visible:enabled:(bg-accent/20 border-accent)':
+ 'from-fg/10 via-transparent to-transparent text-fg hover:enabled:(bg-accent/20) focus-visible:enabled:(bg-accent/20)':
variant === 'secondary',
'text-black from-accent via-accent to-accent/30 hover:enabled:(bg-accent/50) focus-visible:enabled:(bg-accent/50)':
variant === 'primary',
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index ccc7a6dd3..959748a18 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -82,7 +82,7 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
isButton,
'text-sm px-4 py-2': isButtonMedium,
'text-xs px-2 py-0.5': isButtonSmall,
- 'from-fg/10 via-transparent to-transparent text-fg hover:(bg-accent/20 border-accent) focus-visible:(bg-accent/20 border-accent)':
+ 'from-fg/10 via-transparent to-transparent text-fg hover:(bg-accent/20) focus-visible:(bg-accent/20)':
variant === 'button-secondary',
'text-black from-accent via-accent to-accent/30 hover:(bg-accent/50) focus-visible:(bg-accent/50)':
variant === 'button-primary',
From f5689dd97732eac0a9a6eef74d6418c59bca274f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 14:22:23 +0100
Subject: [PATCH 62/91] style: remove accent from links and buttons
---
app/components/Button/Base.vue | 6 +++---
app/components/Link/Base.vue | 10 ++++------
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index 8e3045f86..41004a714 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -31,13 +31,13 @@ defineExpose({
props.size === 'medium' && props.variant !
class="group inline-flex gap-x-1 items-center justify-center"
:class="{
'underline-offset-[0.2rem] underline decoration-1 decoration-fg/50': !isLinkAnchor && isLink,
- 'text-fg hover:(no-underline text-accent) focus-visible:(no-underline text-accent) transition-colors duration-200':
+ 'text-fg hover:(no-underline text-fg/50) focus-visible:(no-underline text-fg/50) transition-colors duration-200':
isLink,
- 'font-mono border border-border rounded-md transition-all duration-200 bg-gradient-to-t dark:bg-gradient-to-b':
- isButton,
+ 'font-mono border border-border rounded-md transition-all duration-200': isButton,
'text-sm px-4 py-2': isButtonMedium,
'text-xs px-2 py-0.5': isButtonSmall,
- 'from-fg/10 via-transparent to-transparent text-fg hover:(bg-accent/20) focus-visible:(bg-accent/20)':
+ 'bg-transparent text-fg hover:(bg-fg/30) focus-visible:(bg-fg/30)':
variant === 'button-secondary',
- 'text-black from-accent via-accent to-accent/30 hover:(bg-accent/50) focus-visible:(bg-accent/50)':
- variant === 'button-primary',
+ 'text-black bg-fg hover:(bg-fg/50) focus-visible:(bg-fg/50)': variant === 'button-primary',
}"
:to="to"
:href="to"
From 77903fc1f0cc411ddc079d29e8e7015fccd5c007 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 16:50:39 +0100
Subject: [PATCH 63/91] fix: firefox bug
---
app/assets/main.css | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/app/assets/main.css b/app/assets/main.css
index 3717f74c0..e9d3d1fec 100644
--- a/app/assets/main.css
+++ b/app/assets/main.css
@@ -181,9 +181,13 @@ body {
line-height: 1.6;
}
-*:focus-visible {
- outline: 2px solid var(--accent);
- outline-offset: 2px;
+*:focus-visible,
+:-moz-focusring {
+ /* weird Firefox behavior makes it necessary to add `!important`
+ or otherwise the selector would need to be more specific,
+ which it explicitly should note be. */
+ outline: 2px solid var(--accent) !important;
+ outline-offset: 2px !important;
}
/* Reset dd margin (browser default is margin-left: 40px) */
From 2fce723df4f1cd6a098ff114b517dcca9b4dd79a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 19:57:24 +0100
Subject: [PATCH 64/91] refactor: simplify query
Co-authored-by: Nathan Knowler
---
app/assets/main.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/assets/main.css b/app/assets/main.css
index e9d3d1fec..3f24487f6 100644
--- a/app/assets/main.css
+++ b/app/assets/main.css
@@ -181,7 +181,7 @@ body {
line-height: 1.6;
}
-*:focus-visible,
+:focus-visible,
:-moz-focusring {
/* weird Firefox behavior makes it necessary to add `!important`
or otherwise the selector would need to be more specific,
From 62c88fca7ec0f97ea72ad06c86828f0196147476 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 21:10:06 +0100
Subject: [PATCH 65/91] refactor: change default element for button group
---
app/components/AppHeader.vue | 2 +-
app/components/Button/Group.vue | 2 +-
app/pages/package/[[org]]/[name].vue | 1 +
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index 74822272b..c3f947833 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -150,7 +150,7 @@ onKeyStroke(
-
+
{{ $t('nav.compare') }}
diff --git a/app/components/Button/Group.vue b/app/components/Button/Group.vue
index 166e7b403..f84d8653d 100644
--- a/app/components/Button/Group.vue
+++ b/app/components/Button/Group.vue
@@ -6,7 +6,7 @@ const props = defineProps<{
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index 118222710..2568ded49 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -649,6 +649,7 @@ onKeyStroke(
From 3a13fbfa8b799e6a0193bf432173d86c07ab55a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 21:12:16 +0100
Subject: [PATCH 66/91] docs: rephrase comment
---
app/components/Button/Base.vue | 2 +-
app/components/Link/Base.vue | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index 41004a714..aa84c6caf 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -8,7 +8,7 @@ const props = withDefaults(
'keyshortcut'?: string
/**
- * Don't use this directly, use `keyshortcut` instead. Correctly HTML will be automatically generated and the shortcut will automatically be displayed in the UI.
+ * Do not use this directly. Use keyshortcut instead; it generates the correct HTML and displays the shortcut in the UI.
*/
'aria-keyshortcuts'?: never
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index e35624699..6f848cb40 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -16,7 +16,7 @@ const props = withDefaults(
'keyshortcut'?: string
/**
- * Don't use this directly, use `keyshortcut` instead. Correctly HTML will be automatically generated and the shortcut will automatically be displayed in the UI.
+ * Do not use this directly. Use keyshortcut instead; it generates the correct HTML and displays the shortcut in the UI.
*/
'aria-keyshortcuts'?: never
From 899516f500c74ec7f1e6102d60d9d8ab79210b5f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 21:14:49 +0100
Subject: [PATCH 67/91] fix: primary button in light mode
---
app/components/Button/Base.vue | 2 +-
app/components/Link/Base.vue | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index aa84c6caf..1a8f600a6 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -37,7 +37,7 @@ defineExpose({
'text-xs px-2 py-0.5': size === 'small',
'bg-transparent text-fg hover:enabled:(bg-fg/30) focus-visible:enabled:(bg-fg/30)':
variant === 'secondary',
- 'text-black bg-fg hover:enabled:(bg-fg/50) focus-visible:enabled:(bg-fg/50)':
+ 'text-bg bg-fg hover:enabled:(bg-fg/50) focus-visible:enabled:(bg-fg/50)':
variant === 'primary',
}"
:type="props.type"
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 6f848cb40..269e6f424 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -83,7 +83,7 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
'text-xs px-2 py-0.5': isButtonSmall,
'bg-transparent text-fg hover:(bg-fg/30) focus-visible:(bg-fg/30)':
variant === 'button-secondary',
- 'text-black bg-fg hover:(bg-fg/50) focus-visible:(bg-fg/50)': variant === 'button-primary',
+ 'text-bg bg-fg hover:(bg-fg/50) focus-visible:(bg-fg/50)': variant === 'button-primary',
}"
:to="to"
:href="to"
From 917d2d47733cf951443a9680ee9e3ea841414f20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 21:19:09 +0100
Subject: [PATCH 68/91] fix: wrong element type
---
app/pages/package/[[org]]/[name].vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index 2568ded49..c554e70e5 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -649,7 +649,7 @@ onKeyStroke(
From a827403045fb6a7f46d3f17c2a65292455e202d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 22:15:11 +0100
Subject: [PATCH 69/91] WIP
---
app/pages/package/[[org]]/[name].vue | 14 ++++++++------
i18n/locales/de-DE.json | 2 +-
lunaria/files/de-DE.json | 2 +-
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index c554e70e5..3f80ee908 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -912,9 +912,10 @@ onKeyStroke(
-
- {{ $t('package.stats.vulns') }}
-
+
-
- {{ $t('package.stats.vulns') }}
-
+
-
diff --git a/i18n/locales/de-DE.json b/i18n/locales/de-DE.json
index 1a66ed171..8a3d86f38 100644
--- a/i18n/locales/de-DE.json
+++ b/i18n/locales/de-DE.json
@@ -152,7 +152,7 @@
"license": "Lizenz",
"deps": "Abhängigkeiten",
"install_size": "Installationsgröße",
- "vulns": "Sicherheitslücken",
+ "vulns": "Sicherheitslücken verfügungsgesetz",
"published": "Veröffentlicht",
"published_tooltip": "Datum, an dem {package}{'@'}{version} veröffentlicht wurde",
"skills": "Fähigkeiten",
diff --git a/lunaria/files/de-DE.json b/lunaria/files/de-DE.json
index 1a66ed171..8a3d86f38 100644
--- a/lunaria/files/de-DE.json
+++ b/lunaria/files/de-DE.json
@@ -152,7 +152,7 @@
"license": "Lizenz",
"deps": "Abhängigkeiten",
"install_size": "Installationsgröße",
- "vulns": "Sicherheitslücken",
+ "vulns": "Sicherheitslücken verfügungsgesetz",
"published": "Veröffentlicht",
"published_tooltip": "Datum, an dem {package}{'@'}{version} veröffentlicht wurde",
"skills": "Fähigkeiten",
From 0bceba2a3a9de9d2b94376a8a9fb7dd59649f062 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 23:01:58 +0100
Subject: [PATCH 70/91] Revert "WIP"
This reverts commit a827403045fb6a7f46d3f17c2a65292455e202d8.
---
app/pages/package/[[org]]/[name].vue | 14 ++++++--------
i18n/locales/de-DE.json | 2 +-
lunaria/files/de-DE.json | 2 +-
3 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index c4efd1683..58af0cf0a 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -918,10 +918,9 @@ onKeyStroke(
-
+
+ {{ $t('package.stats.vulns') }}
+
-
+
+ {{ $t('package.stats.vulns') }}
+
-
diff --git a/i18n/locales/de-DE.json b/i18n/locales/de-DE.json
index 15da26c32..683be5cb6 100644
--- a/i18n/locales/de-DE.json
+++ b/i18n/locales/de-DE.json
@@ -152,7 +152,7 @@
"license": "Lizenz",
"deps": "Abhängigkeiten",
"install_size": "Installationsgröße",
- "vulns": "Sicherheitslücken verfügungsgesetz",
+ "vulns": "Sicherheitslücken",
"published": "Veröffentlicht",
"published_tooltip": "Datum, an dem {package}{'@'}{version} veröffentlicht wurde",
"skills": "Fähigkeiten",
diff --git a/lunaria/files/de-DE.json b/lunaria/files/de-DE.json
index 15da26c32..683be5cb6 100644
--- a/lunaria/files/de-DE.json
+++ b/lunaria/files/de-DE.json
@@ -152,7 +152,7 @@
"license": "Lizenz",
"deps": "Abhängigkeiten",
"install_size": "Installationsgröße",
- "vulns": "Sicherheitslücken verfügungsgesetz",
+ "vulns": "Sicherheitslücken",
"published": "Veröffentlicht",
"published_tooltip": "Datum, an dem {package}{'@'}{version} veröffentlicht wurde",
"skills": "Fähigkeiten",
From 3255a0616849885c9fd20d7ead84a6c8294f8f63 Mon Sep 17 00:00:00 2001
From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com>
Date: Fri, 6 Feb 2026 22:03:05 +0000
Subject: [PATCH 71/91] [autofix.ci] apply automated fixes
---
app/pages/package/[[org]]/[name].vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index 58af0cf0a..a6d4d4a69 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -1061,7 +1061,7 @@ onKeyStroke(
{{ $t('package.readme.title') }}
-
+
Date: Fri, 6 Feb 2026 23:42:28 +0100
Subject: [PATCH 72/91] style: make links mono font again
---
app/components/Link/Base.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 269e6f424..ea3222fba 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -76,7 +76,7 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
class="group inline-flex gap-x-1 items-center justify-center"
:class="{
'underline-offset-[0.2rem] underline decoration-1 decoration-fg/50': !isLinkAnchor && isLink,
- 'text-fg hover:(no-underline text-fg/50) focus-visible:(no-underline text-fg/50) transition-colors duration-200':
+ 'font-mono text-fg hover:(no-underline text-fg/50) focus-visible:(no-underline text-fg/50) transition-colors duration-200':
isLink,
'font-mono border border-border rounded-md transition-all duration-200': isButton,
'text-sm px-4 py-2': isButtonMedium,
From 4901f0107416266a8508829c7990285c8b1915d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 23:43:15 +0100
Subject: [PATCH 73/91] style: mute link underline more
---
app/components/Link/Base.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index ea3222fba..7764b3184 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -75,7 +75,7 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
v-else
class="group inline-flex gap-x-1 items-center justify-center"
:class="{
- 'underline-offset-[0.2rem] underline decoration-1 decoration-fg/50': !isLinkAnchor && isLink,
+ 'underline-offset-[0.2rem] underline decoration-1 decoration-fg/30': !isLinkAnchor && isLink,
'font-mono text-fg hover:(no-underline text-fg/50) focus-visible:(no-underline text-fg/50) transition-colors duration-200':
isLink,
'font-mono border border-border rounded-md transition-all duration-200': isButton,
From 702bbe9410344591f73dfe10623589358fbdf932 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 23:45:16 +0100
Subject: [PATCH 74/91] style: reduce font size in footer
---
app/components/AppFooter.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/AppFooter.vue b/app/components/AppFooter.vue
index fee097ca3..83491bf70 100644
--- a/app/components/AppFooter.vue
+++ b/app/components/AppFooter.vue
@@ -14,7 +14,7 @@ const isHome = computed(() => route.name === 'index')
-
+
{{ $t('footer.about') }}
From 0d4680686b46d39afdcbf98314cf13def98d61f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 23:51:49 +0100
Subject: [PATCH 75/91] style: use accent color for link hover
---
app/components/Link/Base.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 7764b3184..80e13127e 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -76,7 +76,7 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
class="group inline-flex gap-x-1 items-center justify-center"
:class="{
'underline-offset-[0.2rem] underline decoration-1 decoration-fg/30': !isLinkAnchor && isLink,
- 'font-mono text-fg hover:(no-underline text-fg/50) focus-visible:(no-underline text-fg/50) transition-colors duration-200':
+ 'font-mono text-fg hover:(no-underline text-accent) focus-visible:(no-underline text-accent) transition-color duration-200':
isLink,
'font-mono border border-border rounded-md transition-all duration-200': isButton,
'text-sm px-4 py-2': isButtonMedium,
From 07127ebae2633b9a5c8ca3a6daae7b740d6c9874 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 23:57:00 +0100
Subject: [PATCH 76/91] refactor: use button icon for like button
---
app/pages/package/[[org]]/[name].vue | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index a6d4d4a69..ad877f77c 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -624,19 +624,13 @@ onKeyStroke(
likesData?.userHasLiked ? $t('package.likes.unlike') : $t('package.likes.like')
"
:aria-pressed="likesData?.userHasLiked"
+ :classicon="
+ likesData?.userHasLiked
+ ? 'i-lucide-heart-minus text-red-500'
+ : 'i-lucide-heart-plus'
+ "
>
-
- {{
- formatCompactNumber(likesData?.totalLikes ?? 0, { decimals: 1 })
- }}
+ {{ formatCompactNumber(likesData?.totalLikes ?? 0, { decimals: 1 }) }}
From c1352d2b49bf05963a85cda50e6d0ee65dfcbf63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Fri, 6 Feb 2026 23:59:26 +0100
Subject: [PATCH 77/91] style: remove external link indicator from links that
already have an icon
---
app/components/Link/Base.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 80e13127e..61a14df6e 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -100,7 +100,7 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
From ea5c9fa109697b57371db75af54bc9e971b80fdf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Sat, 7 Feb 2026 00:03:48 +0100
Subject: [PATCH 78/91] style: make deps info fit on single line
---
app/pages/package/[[org]]/[name].vue | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index ad877f77c..1cb806a99 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -17,6 +17,7 @@ import { useModal } from '~/composables/useModal'
import { useAtproto } from '~/composables/atproto/useAtproto'
import { togglePackageLike } from '~/utils/atproto/likes'
import { LinkBase } from '#components'
+import { isTemplateExpression } from 'typescript'
defineOgImageComponent('Package', {
name: () => packageName.value,
@@ -810,14 +811,14 @@ onKeyStroke(
{{ $t('package.stats.deps') }}
-
-
+
+
{{ getDependencyCount(displayVersion) }}
- /
+ /
-
-
+
{{ $t('package.stats.inspect_dependency_tree') }}
-
+
From a05c470ab15d32abd121f706b3ede15d8d2fa195 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Sat, 7 Feb 2026 00:06:56 +0100
Subject: [PATCH 79/91] style: temporarily re-add button cursor pointer, for
legacy buttons
---
app/assets/main.css | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/app/assets/main.css b/app/assets/main.css
index 945ce35eb..a733a58ac 100644
--- a/app/assets/main.css
+++ b/app/assets/main.css
@@ -200,6 +200,11 @@ dd {
margin: 0;
}
+/* Reset button styles */
+button {
+ cursor: pointer;
+}
+
/* Selection */
::selection {
background-color: var(--fg-muted);
From 0f9d174a200b2661fec1171b658779ba2003afa3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Sat, 7 Feb 2026 00:09:03 +0100
Subject: [PATCH 80/91] fix: fix close button for modal
---
app/components/Modal.client.vue | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/app/components/Modal.client.vue b/app/components/Modal.client.vue
index 4438f7001..6659b29ad 100644
--- a/app/components/Modal.client.vue
+++ b/app/components/Modal.client.vue
@@ -55,12 +55,10 @@ defineExpose({
-
-
+ classicon="i-carbon-close"
+ />
From 06d4847fa13cec9d4368c08075336e4c2396c240 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Sat, 7 Feb 2026 00:49:23 +0100
Subject: [PATCH 81/91] style: dont hide underline on hover
---
app/components/Link/Base.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 61a14df6e..1d9738408 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -76,7 +76,7 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
class="group inline-flex gap-x-1 items-center justify-center"
:class="{
'underline-offset-[0.2rem] underline decoration-1 decoration-fg/30': !isLinkAnchor && isLink,
- 'font-mono text-fg hover:(no-underline text-accent) focus-visible:(no-underline text-accent) transition-color duration-200':
+ 'font-mono text-fg hover:(decoration-accent text-accent) focus-visible:(decoration-accent text-accent) transition-colors duration-200':
isLink,
'font-mono border border-border rounded-md transition-all duration-200': isButton,
'text-sm px-4 py-2': isButtonMedium,
From cd9513966eed6ae6bdb0390b172f8542d23cad23 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Sat, 7 Feb 2026 00:54:03 +0100
Subject: [PATCH 82/91] style: reduce hover button contrast
---
app/components/Link/Base.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index 1d9738408..b105d3281 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -81,7 +81,7 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
'font-mono border border-border rounded-md transition-all duration-200': isButton,
'text-sm px-4 py-2': isButtonMedium,
'text-xs px-2 py-0.5': isButtonSmall,
- 'bg-transparent text-fg hover:(bg-fg/30) focus-visible:(bg-fg/30)':
+ 'bg-transparent text-fg hover:(bg-fg/10) focus-visible:(bg-fg/10)':
variant === 'button-secondary',
'text-bg bg-fg hover:(bg-fg/50) focus-visible:(bg-fg/50)': variant === 'button-primary',
}"
From 1ae2a621c45fa61e7ca6228b55d186ec5950b760 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Sat, 7 Feb 2026 01:06:16 +0100
Subject: [PATCH 83/91] docs: fix typo
---
app/assets/main.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/assets/main.css b/app/assets/main.css
index a733a58ac..290b71d3d 100644
--- a/app/assets/main.css
+++ b/app/assets/main.css
@@ -190,7 +190,7 @@ body {
:-moz-focusring {
/* weird Firefox behavior makes it necessary to add `!important`
or otherwise the selector would need to be more specific,
- which it explicitly should note be. */
+ which it explicitly should not be. */
outline: 2px solid var(--accent) !important;
outline-offset: 2px !important;
}
From e45e548a155f2cc69fcf7d8a438e788d4cd3d33f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Sat, 7 Feb 2026 01:06:56 +0100
Subject: [PATCH 84/91] fix: remove unused import
---
app/pages/package/[[org]]/[name].vue | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index 09a75b77f..3a5dacc58 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -17,7 +17,6 @@ import { useModal } from '~/composables/useModal'
import { useAtproto } from '~/composables/atproto/useAtproto'
import { togglePackageLike } from '~/utils/atproto/likes'
import { LinkBase } from '#components'
-import { isTemplateExpression } from 'typescript'
defineOgImageComponent('Package', {
name: () => packageName.value,
From 4765ef1a8f45a9994970dbaf4a26e8861b5eb44c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Sat, 7 Feb 2026 01:09:41 +0100
Subject: [PATCH 85/91] style: add spacing around keyboard shortcut
---
app/components/Button/Base.vue | 2 +-
app/components/Link/Base.vue | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index 9c07be56f..982e6af63 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -60,7 +60,7 @@ defineExpose({
{{ keyshortcut }}
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index b105d3281..d487bf4e6 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -111,7 +111,7 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
/>
{{ keyshortcut }}
From ecc87a33fe5257102db9852437ad7bb44e5be84d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Bl=C3=A4ttermann?=
Date: Sat, 7 Feb 2026 01:14:12 +0100
Subject: [PATCH 86/91] style: revert menu back to old design while using new
components
---
app/components/AppHeader.vue | 18 ++++++++++++++----
app/components/Header/AccountMenu.client.vue | 2 +-
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue
index f808e5caf..01390c82e 100644
--- a/app/components/AppHeader.vue
+++ b/app/components/AppHeader.vue
@@ -151,19 +151,29 @@ onKeyStroke(
-
+
-
+
{{ $t('nav.compare') }}
-
+
{{ $t('nav.settings') }}
-
+
Date: Sat, 7 Feb 2026 01:15:53 +0100
Subject: [PATCH 87/91] fix: improve conditional rendering
---
app/pages/package/[[org]]/[name].vue | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index 3a5dacc58..127c31787 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -857,11 +857,10 @@ onKeyStroke(
-
+
Date: Sat, 7 Feb 2026 01:31:38 +0100
Subject: [PATCH 88/91] fix: replace new button
---
app/components/Button/Base.vue | 6 +++---
app/pages/package/[[org]]/[name].vue | 16 ++++------------
2 files changed, 7 insertions(+), 15 deletions(-)
diff --git a/app/components/Button/Base.vue b/app/components/Button/Base.vue
index 982e6af63..5a0a39af1 100644
--- a/app/components/Button/Base.vue
+++ b/app/components/Button/Base.vue
@@ -31,13 +31,13 @@ defineExpose({
-
-
{{ copiedReadme ? $t('common.copied') : $t('common.copy') }}
-
+
Date: Sat, 7 Feb 2026 10:15:23 +0000
Subject: [PATCH 89/91] chore: fix comment location
---
app/assets/main.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/assets/main.css b/app/assets/main.css
index 290b71d3d..2ed934ff8 100644
--- a/app/assets/main.css
+++ b/app/assets/main.css
@@ -159,8 +159,8 @@ html {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
- scroll-padding-top: 5rem;
/* Offset for fixed header - otherwise anchor headers are cutted */
+ scroll-padding-top: 5rem;
scrollbar-gutter: stable;
}
From 19bfe20e8f420e3bb5722a02d2452282b9f29ac6 Mon Sep 17 00:00:00 2001
From: Daniel Roe
Date: Sat, 7 Feb 2026 10:19:50 +0000
Subject: [PATCH 90/91] fix: remove nuxtlink default values
---
app/components/Link/Base.vue | 3 ---
1 file changed, 3 deletions(-)
diff --git a/app/components/Link/Base.vue b/app/components/Link/Base.vue
index d487bf4e6..2c4521e24 100644
--- a/app/components/Link/Base.vue
+++ b/app/components/Link/Base.vue
@@ -86,11 +86,8 @@ const isButtonMedium = computed(() => props.size === 'medium' && props.variant !
'text-bg bg-fg hover:(bg-fg/50) focus-visible:(bg-fg/50)': variant === 'button-primary',
}"
:to="to"
- :href="to"
- :external="isLinkExternal"
:aria-keyshortcuts="keyshortcut"
:target="isLinkExternal ? '_blank' : undefined"
- :rel="isLinkExternal ? 'noopener noreferrer' : undefined"
>
Date: Sat, 7 Feb 2026 10:34:27 +0000
Subject: [PATCH 91/91] fix: update font size of links
---
app/pages/index.vue | 2 +-
app/pages/package/[[org]]/[name].vue | 8 +++++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/app/pages/index.vue b/app/pages/index.vue
index ae9ce1b01..88395fee5 100644
--- a/app/pages/index.vue
+++ b/app/pages/index.vue
@@ -121,7 +121,7 @@ defineOgImageComponent('Default', {
>
-
-
+
diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue
index 14b101cb2..7d0f735b5 100644
--- a/app/pages/package/[[org]]/[name].vue
+++ b/app/pages/package/[[org]]/[name].vue
@@ -713,7 +713,9 @@ onKeyStroke(
-
+
-
@@ -1070,7 +1072,7 @@ onKeyStroke(
-