Skip to content

Commit be5150c

Browse files
authored
Merge branch 'main' into main
2 parents 6de88de + f01da04 commit be5150c

17 files changed

Lines changed: 529 additions & 485 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
browser:
6262
runs-on: ubuntu-latest
6363
container:
64-
image: mcr.microsoft.com/playwright:v1.57.0-noble
64+
image: mcr.microsoft.com/playwright:v1.58.0-noble
6565

6666
steps:
6767
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

app/assets/main.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,14 @@ input[type='search'] {
525525
appearance: none;
526526
}
527527

528+
@media screen and (max-width: 767px) {
529+
input,
530+
select,
531+
textarea {
532+
font-size: 16px !important;
533+
}
534+
}
535+
528536
input[type='search']::-webkit-search-decoration,
529537
input[type='search']::-webkit-search-cancel-button,
530538
input[type='search']::-webkit-search-results-button,

app/components/SearchBox.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<script setup lang="ts">
22
import { debounce } from 'perfect-debounce'
33
4+
const isMobile = useIsMobile()
5+
46
withDefaults(
57
defineProps<{
68
inputClass?: string
@@ -84,7 +86,7 @@ function handleSearchFocus() {
8486

8587
<input
8688
id="header-search"
87-
autofocus
89+
:autofocus="!isMobile"
8890
v-model="searchQuery"
8991
type="search"
9092
name="q"

app/composables/useIsMobile.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Composable for detecting mobile devices using media query.
3+
* Uses the same breakpoint as Tailwind's `md:` (768px).
4+
*
5+
* Returns `false` during SSR to avoid hydration mismatches.
6+
* @public
7+
*/
8+
export function useIsMobile() {
9+
return useMediaQuery('(max-width: 767px)')
10+
}

app/pages/[...package].vue

Lines changed: 3 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -310,34 +310,6 @@ const createPackageInfo = computed(() => {
310310
return packageAnalysis.value.createPackage
311311
})
312312
313-
// Expandable description
314-
const descriptionExpanded = ref(false)
315-
const descriptionRef = useTemplateRef('descriptionRef')
316-
const descriptionOverflows = ref(false)
317-
318-
// Check if description overflows on mount/update
319-
function checkDescriptionOverflow() {
320-
if (descriptionRef.value) {
321-
const paragraph = descriptionRef.value.querySelector('p')
322-
if (paragraph) {
323-
// Compare scrollHeight to the fixed container height (3 lines ~= 72px)
324-
descriptionOverflows.value = paragraph.scrollHeight > 72
325-
}
326-
}
327-
}
328-
329-
watch(
330-
() => pkg.value?.description,
331-
() => {
332-
descriptionExpanded.value = false
333-
nextTick(checkDescriptionOverflow)
334-
},
335-
)
336-
337-
onMounted(() => {
338-
nextTick(checkDescriptionOverflow)
339-
})
340-
341313
// Canonical URL for this package page
342314
const canonicalUrl = computed(() => {
343315
const base = `https://npmx.dev/${packageName.value}`
@@ -517,32 +489,14 @@ function handleClick(event: MouseEvent) {
517489
</nav>
518490
</div>
519491

520-
<!-- Fixed height description container to prevent CLS -->
521-
<div ref="descriptionRef" class="relative max-w-2xl min-h-[4.5rem]">
522-
<p
523-
v-if="pkg.description"
524-
class="text-fg-muted text-base m-0 overflow-hidden"
525-
:class="descriptionExpanded ? '' : 'max-h-[4.5rem]'"
526-
>
492+
<!-- Description container with min-height to prevent CLS -->
493+
<div class="max-w-2xl min-h-[4.5rem]">
494+
<p v-if="pkg.description" class="text-fg-muted text-base m-0">
527495
<MarkdownText :text="pkg.description" />
528496
</p>
529497
<p v-else class="text-fg-subtle text-base m-0 italic">
530498
{{ $t('package.no_description') }}
531499
</p>
532-
<!-- Fade overlay with show more button - only when collapsed and overflowing -->
533-
<div
534-
v-if="pkg.description && descriptionOverflows && !descriptionExpanded"
535-
class="absolute bottom-0 inset-is-0 inset-ie-0 h-10 bg-gradient-to-t from-bg via-bg/90 to-transparent flex items-end justify-end"
536-
>
537-
<button
538-
type="button"
539-
class="font-mono text-xs text-fg-muted hover:text-fg bg-bg px-1 transition-colors duration-200 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
540-
:aria-label="$t('package.show_full_description')"
541-
@click="descriptionExpanded = true"
542-
>
543-
{{ $t('common.show_more') }}
544-
</button>
545-
</div>
546500
</div>
547501

548502
<!-- External links -->

app/pages/code/[...path].vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ definePageMeta({
1111
})
1212
1313
const route = useRoute('code')
14-
const router = useRouter()
1514
1615
// Parse package name, version, and file path from URL
1716
// Patterns:

app/pages/docs/[...path].vue

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script setup lang="ts">
2+
import { setResponseHeader } from 'h3'
23
import type { DocsResponse } from '#shared/types'
34
import { assertValidPackageName } from '#shared/utils/npm'
45
@@ -38,6 +39,18 @@ const { data: pkg } = usePackage(packageName)
3839
3940
const latestVersion = computed(() => pkg.value?.['dist-tags']?.latest ?? null)
4041
42+
if (import.meta.server && !requestedVersion.value) {
43+
const app = useNuxtApp()
44+
const { data: pkg } = await usePackage(packageName)
45+
const latest = pkg.value?.['dist-tags']?.latest
46+
if (latest) {
47+
setResponseHeader(useRequestEvent()!, 'Cache-Control', 'no-cache')
48+
app.runWithContext(() =>
49+
navigateTo('/docs/' + packageName.value + '/v/' + latest, { redirectCode: 302 }),
50+
)
51+
}
52+
}
53+
4154
watch(
4255
[requestedVersion, latestVersion, packageName],
4356
([version, latest, name]) => {

app/pages/index.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const searchQuery = ref('')
66
const searchInputRef = useTemplateRef('searchInputRef')
77
const { focused: isSearchFocused } = useFocus(searchInputRef)
88
9+
const isMobile = useIsMobile()
10+
911
const debouncedNavigate = debounce(() => {
1012
router.push({
1113
path: '/search',
@@ -76,7 +78,7 @@ defineOgImageComponent('Default')
7678
name="q"
7779
:placeholder="$t('search.placeholder')"
7880
v-bind="noCorrect"
79-
autofocus
81+
:autofocus="!isMobile"
8082
class="w-full bg-bg-subtle border border-border rounded-lg ps-8 pe-24 py-4 font-mono text-base text-fg placeholder:text-fg-subtle transition-border-color duration-300 focus:border-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/50"
8183
@input="handleSearch"
8284
/>

cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"test:types": "tsc --noEmit"
3232
},
3333
"dependencies": {
34-
"@clack/prompts": "1.0.0-alpha.9",
34+
"@clack/prompts": "^1.0.0",
3535
"citty": "^0.2.0",
3636
"h3-next": "npm:h3@^2.0.1-rc.11",
3737
"obug": "^2.1.1",

docs/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
"preview": "nuxt preview --extends docus"
1919
},
2020
"dependencies": {
21-
"docus": "latest",
22-
"better-sqlite3": "12.5.0",
23-
"nuxt": "^4.2.2"
21+
"better-sqlite3": "12.6.2",
22+
"docus": "5.4.4",
23+
"nuxt": "4.3.0"
2424
}
2525
}

0 commit comments

Comments
 (0)