Skip to content

Commit 3e17ada

Browse files
authored
Merge branch 'main' into fix/add-clear-icon-in-search-field-for-mobile-view
2 parents fd2a652 + e69428d commit 3e17ada

59 files changed

Lines changed: 976 additions & 250 deletions

Some content is hidden

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

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ test-results/
4040
# generated files
4141
shared/types/lexicons
4242
file-tree-sprite.svg
43+
public/blog/avatar
4344

4445
**/__screenshots__/**
4546

app/components/AuthorList.vue

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
<script setup lang="ts">
2-
import type { Author } from '#shared/schemas/blog'
2+
import type { ResolvedAuthor } from '#shared/schemas/blog'
33
4-
const props = defineProps<{
5-
authors: Author[]
4+
defineProps<{
5+
authors: ResolvedAuthor[]
66
variant?: 'compact' | 'expanded'
77
}>()
8-
9-
const { resolvedAuthors } = useBlueskyAuthorProfiles(props.authors)
108
</script>
119

1210
<template>
1311
<!-- Expanded variant: vertical list with larger avatars -->
1412
<div v-if="variant === 'expanded'" class="flex flex-wrap items-center gap-4">
15-
<div v-for="author in resolvedAuthors" :key="author.name" class="flex items-center gap-2">
13+
<div v-for="author in authors" :key="author.name" class="flex items-center gap-2">
1614
<AuthorAvatar :author="author" size="md" disable-link />
1715
<div class="flex flex-col">
1816
<span class="text-sm font-medium text-fg">{{ author.name }}</span>
@@ -34,7 +32,7 @@ const { resolvedAuthors } = useBlueskyAuthorProfiles(props.authors)
3432
<div v-else class="flex items-center gap-2 min-w-0">
3533
<div class="flex items-center">
3634
<AuthorAvatar
37-
v-for="(author, index) in resolvedAuthors"
35+
v-for="(author, index) in authors"
3836
:key="author.name"
3937
:author="author"
4038
size="md"
@@ -43,7 +41,7 @@ const { resolvedAuthors } = useBlueskyAuthorProfiles(props.authors)
4341
/>
4442
</div>
4543
<span class="text-xs text-fg-muted font-mono truncate">
46-
{{ resolvedAuthors.map(a => a.name).join(', ') }}
44+
{{ authors.map(a => a.name).join(', ') }}
4745
</span>
4846
</div>
4947
</template>

app/components/BlogPostListCard.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<script setup lang="ts">
2-
import type { Author } from '#shared/schemas/blog'
2+
import type { ResolvedAuthor } from '#shared/schemas/blog'
33
44
defineProps<{
55
/** Authors of the blog post */
6-
authors: Author[]
6+
authors: ResolvedAuthor[]
77
/** Blog Title */
88
title: string
99
/** Tags such as OpenSource, Architecture, Community, etc. */

app/components/Code/Viewer.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ watch(
115115
<!-- Code content -->
116116
<div class="code-content flex-1 overflow-x-auto min-w-0">
117117
<!-- eslint-disable vue/no-v-html -- HTML is generated server-side by Shiki -->
118-
<div ref="codeRef" class="code-lines w-fit" v-html="html" />
118+
<div ref="codeRef" class="code-lines min-w-full w-fit" v-html="html" />
119119
<!-- eslint-enable vue/no-v-html -->
120120
</div>
121121
</div>
@@ -157,7 +157,7 @@ watch(
157157
158158
/* Highlighted lines in code content - extend full width with negative margin */
159159
.code-content :deep(.line.highlighted) {
160-
background: rgb(234 179 8 / 0.2); /* yellow-500/20 */
160+
@apply bg-yellow-500/20;
161161
margin: 0 -1rem;
162162
padding: 0 1rem;
163163
}

app/components/CopyToClipboardButton.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function handleClick() {
3737
class="absolute z-20 inset-is-0 top-full inline-flex items-center gap-1 px-2 py-1 rounded border text-xs font-mono whitespace-nowrap transition-all duration-150 opacity-0 -translate-y-1 pointer-events-none group-hover:opacity-100 group-hover:translate-y-0 group-hover:pointer-events-auto focus-visible:opacity-100 focus-visible:translate-y-0 focus-visible:pointer-events-auto"
3838
:class="[
3939
$style.copyButton,
40-
copied ? 'text-accent bg-accent/10' : 'text-fg-muted bg-bg border-border',
40+
copied ? ['text-accent', $style.copiedBg] : 'text-fg-muted bg-bg border-border',
4141
]"
4242
:aria-label="copied ? buttonAriaLabelCopied : buttonAriaLabelCopy"
4343
v-bind="buttonAttrs"
@@ -80,6 +80,10 @@ function handleClick() {
8080
translate 0.15s;
8181
}
8282
83+
.copiedBg {
84+
background-color: color-mix(in srgb, var(--accent) 10%, var(--bg));
85+
}
86+
8387
@media (hover: none) {
8488
.copyButton {
8589
display: none;

app/components/Header/ConnectorModal.vue

Lines changed: 28 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,22 @@ function handleDisconnect() {
2727
disconnect()
2828
}
2929
30-
// function copyCommand() {
31-
// let command = executeNpmxConnectorCommand.value
32-
// if (portInput.value !== '31415') {
33-
// command += ` --port ${portInput.value}`
34-
// }
35-
// copy(command)
36-
// }
37-
38-
// const selectedPM = useSelectedPackageManager()
39-
40-
// const executeNpmxConnectorCommand = computed(() => {
41-
// return getExecuteCommand({
42-
// packageName: 'npmx-connector',
43-
// packageManager: selectedPM.value,
44-
// })
45-
// })
30+
function copyCommand() {
31+
let command = executeNpmxConnectorCommand.value
32+
if (portInput.value !== '31415') {
33+
command += ` --port ${portInput.value}`
34+
}
35+
copy(command)
36+
}
37+
38+
const selectedPM = useSelectedPackageManager()
39+
40+
const executeNpmxConnectorCommand = computed(() => {
41+
return getExecuteCommand({
42+
packageName: 'npmx-connector',
43+
packageManager: selectedPM.value,
44+
})
45+
})
4646
</script>
4747

4848
<template>
@@ -87,26 +87,6 @@ function handleDisconnect() {
8787

8888
<!-- Disconnected state -->
8989
<form v-else class="space-y-4" @submit.prevent="handleConnect">
90-
<!-- Contributor-only notice -->
91-
<div class="p-3 bg-amber-500/10 border border-amber-500/30 rounded-lg">
92-
<div>
93-
<span class="inline-block text-xs font-bold uppercase tracking-wider text-fg rounded">
94-
{{ $t('connector.modal.contributor_badge') }}
95-
</span>
96-
<p class="text-sm text-fg-muted">
97-
<i18n-t keypath="connector.modal.contributor_notice" scope="global">
98-
<template #link>
99-
<LinkBase
100-
to="https://github.com/npmx-dev/npmx.dev/blob/main/CONTRIBUTING.md#local-connector-cli"
101-
>
102-
{{ $t('connector.modal.contributor_link') }}
103-
</LinkBase>
104-
</template>
105-
</i18n-t>
106-
</p>
107-
</div>
108-
</div>
109-
11090
<p class="text-sm text-fg-muted">
11191
{{ $t('connector.modal.run_hint') }}
11292
</p>
@@ -116,43 +96,20 @@ function handleDisconnect() {
11696
dir="ltr"
11797
>
11898
<span class="text-fg-subtle">$</span>
119-
<span class="text-fg-subtle ms-2">npx npmx-connector</span>
120-
<ButtonBase
121-
:aria-label="copied ? $t('connector.modal.copied') : $t('connector.modal.copy_command')"
122-
@click="copy('npx npmx-connector')"
123-
class="ms-auto"
124-
:classicon="copied ? 'i-lucide:check text-green-500' : 'i-lucide:copy'"
125-
/>
99+
<span class="text-fg-subtle ms-2">{{ executeNpmxConnectorCommand }}</span>
100+
<div class="ms-auto flex items-center gap-2">
101+
<!-- Disable teleport in a modal dialog -->
102+
<PackageManagerSelect :teleport="false" />
103+
104+
<ButtonBase
105+
:aria-label="copied ? $t('connector.modal.copied') : $t('connector.modal.copy_command')"
106+
@click="copyCommand"
107+
class="ms-auto"
108+
:classicon="copied ? 'i-lucide:check text-green-500' : 'i-lucide:copy'"
109+
/>
110+
</div>
126111
</div>
127112

128-
<!-- TODO: Uncomment when npmx-connector is published to npm
129-
<div
130-
class="flex items-center p-3 bg-bg-muted border border-border rounded-lg font-mono text-sm"
131-
>
132-
<span class="text-fg-subtle">$</span>
133-
<span class="text-fg-subtle ms-2">{{ executeNpmxConnectorCommand }}</span>
134-
<div class="ms-auto flex items-center gap-2">
135-
<PackageManagerSelect />
136-
137-
<button
138-
type="button"
139-
:aria-label="
140-
copied ? $t('connector.modal.copied') : $t('connector.modal.copy_command')
141-
"
142-
class="ms-auto text-fg-subtle p-1.5 -m-1.5 hover:text-fg transition-colors duration-200 focus-visible:outline-accent/70 rounded"
143-
@click="copyCommand"
144-
>
145-
<span v-if="!copied" class="i-lucide:copy block w-5 h-5" aria-hidden="true" />
146-
<span
147-
v-else
148-
class="i-lucide:check block w-5 h-5 text-green-500"
149-
aria-hidden="true"
150-
/>
151-
</button>
152-
</div>
153-
</div>
154-
-->
155-
156113
<p class="text-sm text-fg-muted">{{ $t('connector.modal.paste_token') }}</p>
157114

158115
<div class="space-y-3">

app/components/OgImage/BlogPost.vue

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script setup lang="ts">
2-
import type { Author } from '#shared/schemas/blog'
2+
import type { ResolvedAuthor } from '#shared/schemas/blog'
33
44
const props = withDefaults(
55
defineProps<{
66
title: string
7-
authors?: Author[]
7+
authors?: ResolvedAuthor[]
88
date?: string
99
primaryColor?: string
1010
}>(),
@@ -15,8 +15,6 @@ const props = withDefaults(
1515
},
1616
)
1717
18-
const { resolvedAuthors } = useBlueskyAuthorProfiles(props.authors)
19-
2018
const formattedDate = computed(() => {
2119
if (!props.date) return ''
2220
try {
@@ -41,17 +39,17 @@ const getInitials = (name: string) =>
4139
.slice(0, 2)
4240
4341
const visibleAuthors = computed(() => {
44-
if (resolvedAuthors.value.length <= 3) return resolvedAuthors.value
45-
return resolvedAuthors.value.slice(0, MAX_VISIBLE_AUTHORS)
42+
if (props.authors.length <= 3) return props.authors
43+
return props.authors.slice(0, MAX_VISIBLE_AUTHORS)
4644
})
4745
4846
const extraCount = computed(() => {
49-
if (resolvedAuthors.value.length <= 3) return 0
50-
return resolvedAuthors.value.length - MAX_VISIBLE_AUTHORS
47+
if (props.authors.length <= 3) return 0
48+
return props.authors.length - MAX_VISIBLE_AUTHORS
5149
})
5250
5351
const formattedAuthorNames = computed(() => {
54-
const allNames = resolvedAuthors.value.map(a => a.name)
52+
const allNames = props.authors.map(a => a.name)
5553
if (allNames.length === 0) return ''
5654
if (allNames.length === 1) return allNames[0]
5755
if (allNames.length === 2) return `${allNames[0]} and ${allNames[1]}`
@@ -96,7 +94,7 @@ const formattedAuthorNames = computed(() => {
9694

9795
<!-- Authors -->
9896
<div
99-
v-if="resolvedAuthors.length"
97+
v-if="authors.length"
10098
class="flex items-center gap-4 self-start justify-start flex-nowrap"
10199
style="font-family: 'Geist', sans-serif"
102100
>

app/components/Package/Dependencies.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,8 @@ const numberFormatter = useNumberFormatter()
218218
:key="peer.name"
219219
class="flex items-center justify-between py-1 text-sm gap-1 min-w-0"
220220
>
221-
<div class="flex items-center gap-1 min-w-0 flex-1">
222-
<LinkBase :to="packageRoute(peer.name)" class="block truncate" dir="ltr">
221+
<div class="flex items-center gap-2 min-w-0 flex-1">
222+
<LinkBase :to="packageRoute(peer.name)" class="block max-w-[70%] break-words" dir="ltr">
223223
{{ peer.name }}
224224
</LinkBase>
225225
<TagStatic v-if="peer.optional" :title="$t('package.dependencies.optional')">
@@ -228,7 +228,7 @@ const numberFormatter = useNumberFormatter()
228228
</div>
229229
<LinkBase
230230
:to="packageRoute(peer.name, peer.version)"
231-
class="block truncate max-w-[40%]"
231+
class="block truncate max-w-[30%]"
232232
:title="peer.version"
233233
dir="ltr"
234234
>
@@ -278,9 +278,9 @@ const numberFormatter = useNumberFormatter()
278278
optionalDepsExpanded ? undefined : 10,
279279
)"
280280
:key="dep"
281-
class="flex items-center justify-between py-1 text-sm gap-2"
281+
class="flex items-baseline justify-between py-1 text-sm gap-2"
282282
>
283-
<LinkBase :to="packageRoute(dep)" class="block truncate" dir="ltr">
283+
<LinkBase :to="packageRoute(dep)" class="block max-w-[80%] break-words" dir="ltr">
284284
{{ dep }}
285285
</LinkBase>
286286
<LinkBase

app/components/Package/LikeCard.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const { user } = useAtproto()
1717
1818
const authModal = useModal('auth-modal')
1919
20-
const { data: likesData } = useFetch(() => `/api/social/likes/${name.value}`, {
20+
const { data: likesData, status: likesStatus } = useFetch(() => `/api/social/likes/${name.value}`, {
2121
default: () => ({ totalLikes: 0, userHasLiked: false }),
2222
server: false,
2323
})
@@ -76,6 +76,7 @@ const likeAction = async () => {
7676
<div class="flex items-center gap-4 justify-between shrink-0">
7777
<ClientOnly>
7878
<TooltipApp
79+
v-if="likesStatus !== 'pending'"
7980
:text="likesData?.userHasLiked ? $t('package.likes.unlike') : $t('package.likes.like')"
8081
position="bottom"
8182
>

app/components/Package/ManagerSelect.vue

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
<script setup lang="ts">
22
import { onClickOutside, useEventListener } from '@vueuse/core'
33
4+
withDefaults(
5+
defineProps<{
6+
teleport?: boolean
7+
}>(),
8+
{
9+
teleport: true,
10+
},
11+
)
12+
413
const selectedPM = useSelectedPackageManager()
514
615
const listRef = useTemplateRef('listRef')
@@ -121,7 +130,7 @@ function handleKeydown(event: KeyboardEvent) {
121130
</button>
122131

123132
<!-- Dropdown menu (teleported to body to avoid clipping) -->
124-
<Teleport to="body">
133+
<Teleport to="body" :disabled="!teleport">
125134
<Transition
126135
:enter-active-class="prefersReducedMotion ? '' : 'transition-opacity duration-150'"
127136
:enter-from-class="prefersReducedMotion ? '' : 'opacity-0'"

0 commit comments

Comments
 (0)