Skip to content

Commit 17dfb26

Browse files
authored
Merge branch 'main' into fix-search
2 parents 89b4c2e + 91df60a commit 17dfb26

File tree

85 files changed

+4918
-979
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+4918
-979
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,8 @@ jobs:
235235

236236
- name: 🌐 Check for missing or dynamic i18n keys
237237
run: pnpm i18n:report
238+
239+
- name: 🌐 Check i18n schema is up to date
240+
run: |
241+
pnpm i18n:schema
242+
git diff --exit-code i18n/schema.json

app/components/AppFooter.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ const showModal = () => modalRef.value?.showModal?.()
1414
>
1515
<div>
1616
<p class="font-mono text-balance m-0 hidden sm:block">{{ $t('tagline') }}</p>
17-
<BuildEnvironment v-if="!isHome" footer />
1817
</div>
1918
<!-- Desktop: Show all links. Mobile: Links are in MobileMenu -->
2019
<div class="hidden sm:flex items-center gap-6 min-h-11 text-xs">
@@ -105,6 +104,7 @@ const showModal = () => modalRef.value?.showModal?.()
105104
</Modal>
106105
</div>
107106
</div>
107+
<BuildEnvironment v-if="!isHome" footer />
108108
<p class="text-xs text-fg-muted text-center sm:text-start m-0">
109109
<span class="sm:hidden">{{ $t('non_affiliation_disclaimer') }}</span>
110110
<span class="hidden sm:inline">{{ $t('trademark_disclaimer') }}</span>

app/components/AppHeader.vue

Lines changed: 119 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
22
import { LinkBase } from '#components'
3+
import type { NavigationConfig, NavigationConfigWithGroups } from '~/types'
34
import { isEditableElement } from '~/utils/input'
45
56
withDefaults(
@@ -13,6 +14,106 @@ withDefaults(
1314
1415
const { isConnected, npmUser } = useConnector()
1516
17+
const desktopLinks = computed<NavigationConfig>(() => [
18+
{
19+
name: 'Compare',
20+
label: $t('nav.compare'),
21+
to: { name: 'compare' },
22+
keyshortcut: 'c',
23+
type: 'link',
24+
external: false,
25+
iconClass: 'i-carbon:compare',
26+
},
27+
{
28+
name: 'Settings',
29+
label: $t('nav.settings'),
30+
to: { name: 'settings' },
31+
keyshortcut: ',',
32+
type: 'link',
33+
external: false,
34+
iconClass: 'i-carbon:settings',
35+
},
36+
])
37+
38+
const mobileLinks = computed<NavigationConfigWithGroups>(() => [
39+
{
40+
name: 'Desktop Links',
41+
type: 'group',
42+
items: [...desktopLinks.value],
43+
},
44+
{
45+
type: 'separator',
46+
},
47+
{
48+
name: 'About & Policies',
49+
type: 'group',
50+
items: [
51+
{
52+
name: 'About',
53+
label: $t('footer.about'),
54+
to: { name: 'about' },
55+
type: 'link',
56+
external: false,
57+
iconClass: 'i-carbon:information',
58+
},
59+
{
60+
name: 'Privacy Policy',
61+
label: $t('privacy_policy.title'),
62+
to: { name: 'privacy' },
63+
type: 'link',
64+
external: false,
65+
iconClass: 'i-carbon:security',
66+
},
67+
],
68+
},
69+
{
70+
type: 'separator',
71+
},
72+
{
73+
name: 'External Links',
74+
type: 'group',
75+
label: $t('nav.links'),
76+
items: [
77+
{
78+
name: 'Docs',
79+
label: $t('footer.docs'),
80+
href: 'https://docs.npmx.dev',
81+
target: '_blank',
82+
type: 'link',
83+
external: true,
84+
iconClass: 'i-carbon:document',
85+
},
86+
{
87+
name: 'Source',
88+
label: $t('footer.source'),
89+
href: 'https://repo.npmx.dev',
90+
target: '_blank',
91+
type: 'link',
92+
external: true,
93+
iconClass: 'i-carbon:logo-github',
94+
},
95+
{
96+
name: 'Social',
97+
label: $t('footer.social'),
98+
href: 'https://social.npmx.dev',
99+
target: '_blank',
100+
type: 'link',
101+
external: true,
102+
iconClass: 'i-simple-icons:bluesky',
103+
},
104+
{
105+
name: 'Chat',
106+
label: $t('footer.chat'),
107+
href: 'https://chat.npmx.dev',
108+
target: '_blank',
109+
type: 'link',
110+
external: true,
111+
iconClass: 'i-carbon:chat',
112+
},
113+
],
114+
},
115+
])
116+
16117
const showFullSearch = shallowRef(false)
17118
const showMobileMenu = shallowRef(false)
18119
@@ -63,23 +164,18 @@ function handleSearchFocus() {
63164
}
64165
65166
onKeyStroke(
66-
e => isKeyWithoutModifiers(e, ',') && !isEditableElement(e.target),
67167
e => {
68-
e.preventDefault()
69-
navigateTo({ name: 'settings' })
70-
},
71-
{ dedupe: true },
72-
)
168+
if (isEditableElement(e.target)) {
169+
return
170+
}
73171
74-
onKeyStroke(
75-
e =>
76-
isKeyWithoutModifiers(e, 'c') &&
77-
!isEditableElement(e.target) &&
78-
// Allow more specific handlers to take precedence
79-
!e.defaultPrevented,
80-
e => {
81-
e.preventDefault()
82-
navigateTo({ name: 'compare' })
172+
for (const link of desktopLinks.value) {
173+
if (link.to && link.keyshortcut && isKeyWithoutModifiers(e, link.keyshortcut)) {
174+
e.preventDefault()
175+
navigateTo(link.to.name)
176+
break
177+
}
178+
}
83179
},
84180
{ dedupe: true },
85181
)
@@ -156,24 +252,16 @@ onKeyStroke(
156252

157253
<!-- End: Desktop nav items + Mobile menu button -->
158254
<div class="hidden sm:flex flex-shrink-0">
159-
<!-- Desktop: Compare link -->
160-
<LinkBase
161-
class="border-none"
162-
variant="button-secondary"
163-
:to="{ name: 'compare' }"
164-
keyshortcut="c"
165-
>
166-
{{ $t('nav.compare') }}
167-
</LinkBase>
168-
169-
<!-- Desktop: Settings link -->
255+
<!-- Desktop: Explore link -->
170256
<LinkBase
257+
v-for="link in desktopLinks"
258+
:key="link.name"
171259
class="border-none"
172260
variant="button-secondary"
173-
:to="{ name: 'settings' }"
174-
keyshortcut=","
261+
:to="link.to"
262+
:aria-keyshortcuts="link.keyshortcut"
175263
>
176-
{{ $t('nav.settings') }}
264+
{{ link.label }}
177265
</LinkBase>
178266

179267
<HeaderAccountMenu />
@@ -182,7 +270,7 @@ onKeyStroke(
182270
<!-- Mobile: Menu button (always visible, click to open menu) -->
183271
<ButtonBase
184272
type="button"
185-
class="sm:hidden flex"
273+
class="sm:hidden"
186274
:aria-label="$t('nav.open_menu')"
187275
:aria-expanded="showMobileMenu"
188276
@click="showMobileMenu = !showMobileMenu"
@@ -191,6 +279,6 @@ onKeyStroke(
191279
</nav>
192280

193281
<!-- Mobile menu -->
194-
<HeaderMobileMenu v-model:open="showMobileMenu" />
282+
<HeaderMobileMenu :links="mobileLinks" v-model:open="showMobileMenu" />
195283
</header>
196284
</template>

app/components/BuildEnvironment.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
<script setup lang="ts">
2-
defineProps<{
2+
import type { BuildInfo } from '#shared/types'
3+
4+
const { footer = false, buildInfo: buildInfoProp } = defineProps<{
35
footer?: boolean
6+
buildInfo?: BuildInfo
47
}>()
58
69
const { locale } = useI18n()
7-
const buildInfo = useAppConfig().buildInfo
10+
const appConfig = useAppConfig()
11+
const buildInfo = computed(() => buildInfoProp || appConfig.buildInfo)
812
</script>
913

1014
<template>
1115
<div
1216
class="font-mono text-xs text-fg-muted flex items-center gap-2 motion-safe:animate-fade-in motion-safe:animate-fill-both"
13-
:class="footer ? 'mt-4 justify-start' : 'mb-8 justify-center'"
17+
:class="footer ? 'my-1 justify-center sm:justify-start' : 'mb-8 justify-center'"
1418
style="animation-delay: 0.05s"
1519
>
1620
<i18n-t keypath="built_at" scope="global">

app/components/Button/Base.vue

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
<script setup lang="ts">
22
const props = withDefaults(
33
defineProps<{
4-
'disabled'?: boolean
5-
'type'?: 'button' | 'submit'
6-
'variant'?: 'primary' | 'secondary'
7-
'size'?: 'small' | 'medium'
8-
'keyshortcut'?: string
4+
disabled?: boolean
5+
type?: 'button' | 'submit'
6+
variant?: 'primary' | 'secondary'
7+
size?: 'small' | 'medium'
8+
ariaKeyshortcuts?: string
9+
block?: boolean
910
10-
/**
11-
* Do not use this directly. Use keyshortcut instead; it generates the correct HTML and displays the shortcut in the UI.
12-
*/
13-
'aria-keyshortcuts'?: never
14-
15-
'classicon'?: string
11+
classicon?: string
1612
}>(),
1713
{
1814
type: 'button',
@@ -32,11 +28,13 @@ defineExpose({
3228
<template>
3329
<button
3430
ref="el"
35-
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)"
31+
class="group cursor-pointer 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)"
3632
:class="{
33+
'inline-flex': !block,
34+
'flex': block,
3735
'text-sm px-4 py-2': size === 'medium',
3836
'text-xs px-2 py-0.5': size === 'small',
39-
'bg-transparent text-fg hover:enabled:(bg-fg/10) focus-visible:enabled:(bg-fg/10) aria-pressed:(bg-fg text-bg border-fg hover:enabled:(bg-fg text-bg/50))':
37+
'bg-transparent text-fg hover:enabled:(bg-fg/10) focus-visible:enabled:(bg-fg/10) aria-pressed:(bg-fg/10 border-fg/20 hover:enabled:(bg-fg/20 text-fg/50))':
4038
variant === 'secondary',
4139
'text-bg bg-fg hover:enabled:(bg-fg/50) focus-visible:enabled:(bg-fg/50) aria-pressed:(bg-fg text-bg border-fg hover:enabled:(text-bg/50))':
4240
variant === 'primary',
@@ -51,20 +49,16 @@ defineExpose({
5149
*/
5250
disabled ? true : undefined
5351
"
54-
:aria-keyshortcuts="keyshortcut"
52+
:aria-keyshortcuts="ariaKeyshortcuts"
5553
>
56-
<span
57-
v-if="classicon"
58-
:class="[size === 'small' ? 'size-3' : 'size-4', classicon]"
59-
aria-hidden="true"
60-
/>
54+
<span v-if="classicon" class="size-[1em]" :class="classicon" aria-hidden="true" />
6155
<slot />
6256
<kbd
63-
v-if="keyshortcut"
57+
v-if="ariaKeyshortcuts"
6458
class="ms-2 inline-flex items-center justify-center w-4 h-4 text-xs text-fg bg-bg-muted border border-border rounded no-underline"
6559
aria-hidden="true"
6660
>
67-
{{ keyshortcut }}
61+
{{ ariaKeyshortcuts }}
6862
</kbd>
6963
</button>
7064
</template>

app/components/Code/DirectoryListing.vue

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,14 @@ const bytesFormatter = useBytesFormatter()
7676
class="border-b border-border hover:bg-bg-subtle transition-colors"
7777
>
7878
<td colspan="2">
79-
<NuxtLink
79+
<LinkBase
8080
:to="getCodeRoute(parentPath || undefined)"
81-
class="flex items-center gap-2 py-2 px-4 font-mono text-sm text-fg-muted hover:text-fg transition-colors"
81+
class="py-2 px-4 font-mono text-sm w-full"
82+
no-underline
83+
classicon="i-carbon:folder text-yellow-600"
8284
>
83-
<span class="i-carbon:folder w-4 h-4 text-yellow-600" />
84-
<span>..</span>
85-
</NuxtLink>
85+
<span class="w-full flex justify-self-stretch items-center gap-2"> .. </span>
86+
</LinkBase>
8687
</td>
8788
</tr>
8889

@@ -93,24 +94,26 @@ const bytesFormatter = useBytesFormatter()
9394
class="border-b border-border hover:bg-bg-subtle transition-colors"
9495
>
9596
<td colspan="2">
96-
<NuxtLink
97+
<LinkBase
9798
:to="getCodeRoute(node.path)"
98-
class="flex items-center gap-2 py-2 px-4 font-mono text-sm hover:text-fg transition-colors"
99-
:class="node.type === 'directory' ? 'text-fg' : 'text-fg-muted'"
99+
class="py-2 px-4 font-mono text-sm w-full"
100+
no-underline
101+
:classicon="
102+
node.type === 'directory'
103+
? 'i-carbon:folder text-yellow-600'
104+
: getFileIcon(node.name)
105+
"
100106
>
101-
<span
102-
v-if="node.type === 'directory'"
103-
class="i-carbon:folder w-4 h-4 text-yellow-600"
104-
/>
105-
<span v-else class="w-4 h-4" :class="getFileIcon(node.name)" />
106-
<span class="flex-1">{{ node.name }}</span>
107-
<span
108-
v-if="node.type === 'file' && node.size"
109-
class="text-end font-mono text-xs text-fg-subtle"
110-
>
111-
{{ bytesFormatter.format(node.size) }}
107+
<span class="w-full flex justify-self-stretch items-center gap-2">
108+
<span class="flex-1">{{ node.name }}</span>
109+
<span
110+
v-if="node.type === 'file' && node.size"
111+
class="text-end text-xs text-fg-subtle"
112+
>
113+
{{ bytesFormatter.format(node.size) }}
114+
</span>
112115
</span>
113-
</NuxtLink>
116+
</LinkBase>
114117
</td>
115118
</tr>
116119
</tbody>

0 commit comments

Comments
 (0)