Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
036dfc2
chore: add link to jonathanyeong.com post to alpha blog post (#1907)
jonathanyeong Mar 3, 2026
225b6d4
feat: add sticky effect to the readme header on the readme page (#1775)
btea Mar 4, 2026
d87e85c
fix(i18n): update zh-CN translation (#1915)
liweijie0812 Mar 4, 2026
f2045e6
fix(ui): readme toc dropdown scroll to the selected item position (#1…
btea Mar 4, 2026
94f95fa
test: add coverage for critical `resolveDependencyTree` (#1911)
serhalp Mar 4, 2026
9216309
fix(ui): fix transparency bleeding of copied tooltip (#1913)
ShroXd Mar 4, 2026
9c5a6cb
fix(ui): don't show state before profile/likes finish loading (#1910)
serhalp Mar 4, 2026
6a44d71
fix: remove the contributors only warning for connector (#1920)
liangmiQwQ Mar 4, 2026
f3403eb
perf: only load `vue-data-ui` css in components that use it (#1918)
danielroe Mar 4, 2026
462fb98
fix: remove hidden overflow from sparkline wrapper (#1926)
graphieros Mar 4, 2026
7c249c5
fix(ui): ensure selected line highlights full width in code viewer (#…
9romise Mar 4, 2026
af71229
fix: improve sponsors layout on the about page for mobile users (#1890)
iiio2 Mar 4, 2026
6a5e6b2
feat: add marko playground links (#1927)
LuLaValva Mar 4, 2026
e3209f2
fix(i18n): add missing Azerbaijani (az-AZ) translations (#1929)
mrnasil Mar 4, 2026
01abe3b
fix(i18n): add recently added phrases to uk-ua (#1930)
alex-key Mar 4, 2026
11c2116
fix(blog): resolve blog author avatars at build time (#1879)
danielroe Mar 4, 2026
51ecbc7
fix(ui): dependency name readability (#1933)
MatteoGabriele Mar 4, 2026
a682a99
fix(i18n): missing/updated Turkish and Azerbaijani translations (#1928)
mrnasil Mar 5, 2026
f06b73f
refactor: resue NPM_REGISTRY from shared constants file (#1938)
ShroXd Mar 5, 2026
e69428d
fix(lunaria): underline anchor tags and lighten consistently on hover…
20jasper Mar 5, 2026
e42fff4
feat: add clear button in search input (#1895)
SahulKola Mar 5, 2026
f9c8e9c
fix(i18n): update Czech translations (#1932)
VentyCZ Mar 5, 2026
d10e3c3
feat: add Svelte CI anomalies to download-anomalies.data.ts (#1934)
samal-rasmussen Mar 5, 2026
6a78b90
chore: dark mode iconify logo (#1940)
cyberalien Mar 5, 2026
bf12be0
fix(ui): make install size tooltip interactive for copying (#1941)
maxchang3 Mar 5, 2026
71116e8
fix(ui): replace "yolo" mode with npm API max of 250 results (#1922)
MatteoGabriele Mar 5, 2026
5530873
fix(ui): load all versions when semver range filter is entered (#1912)
serhalp Mar 5, 2026
4f4b600
fix(i18n): update Japanese translations (#1951)
shuuji3 Mar 5, 2026
ee3ffaa
fix: change paragraph to small tag for legal copy (#1950)
BradEstey Mar 5, 2026
58da597
fix: separate class getters from methods in docs rendering (#1949)
RYGRIT Mar 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ test-results/
# generated files
shared/types/lexicons
file-tree-sprite.svg
public/blog/avatar

**/__screenshots__/**

Expand Down
42 changes: 42 additions & 0 deletions app/assets/logos/oss-partners/iconify-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 42 additions & 1 deletion app/assets/logos/oss-partners/iconify.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion app/assets/logos/oss-partners/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import LogoFastCheck from './fast-check.svg'
import LogoLunaria from './lunaria.svg'
import LogoJsr from './jsr.svg'
import LogoIconify from './iconify.svg'
import LogoIconifyLight from './iconify-light.svg'
import LogoFloatingUi from './floating-ui-vue.svg'
import LogoBlento from './blento.svg'

Expand Down Expand Up @@ -188,7 +189,10 @@ export const OSS_PARTNERS = [
},
{
name: 'Iconify',
logo: LogoIconify,
logo: {
dark: LogoIconify,
light: LogoIconifyLight,
},
url: 'https://iconify.design/',
},
{
Expand Down
4 changes: 2 additions & 2 deletions app/components/AppFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ const closeModal = () => modalRef.value?.close?.()
</div>
</div>
</div>
<p class="text-xs text-fg-muted text-center sm:text-start m-0">
<small class="text-xs text-fg-muted text-center sm:text-start m-0">
<span class="sm:hidden">{{ $t('non_affiliation_disclaimer') }}</span>
<span class="hidden sm:inline">{{ $t('trademark_disclaimer') }}</span>
</p>
</small>
</div>
</footer>
</template>
Expand Down
14 changes: 6 additions & 8 deletions app/components/AuthorList.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
<script setup lang="ts">
import type { Author } from '#shared/schemas/blog'
import type { ResolvedAuthor } from '#shared/schemas/blog'

const props = defineProps<{
authors: Author[]
defineProps<{
authors: ResolvedAuthor[]
variant?: 'compact' | 'expanded'
}>()

const { resolvedAuthors } = useBlueskyAuthorProfiles(props.authors)
</script>

<template>
<!-- Expanded variant: vertical list with larger avatars -->
<div v-if="variant === 'expanded'" class="flex flex-wrap items-center gap-4">
<div v-for="author in resolvedAuthors" :key="author.name" class="flex items-center gap-2">
<div v-for="author in authors" :key="author.name" class="flex items-center gap-2">
<AuthorAvatar :author="author" size="md" disable-link />
<div class="flex flex-col">
<span class="text-sm font-medium text-fg">{{ author.name }}</span>
Expand All @@ -34,7 +32,7 @@ const { resolvedAuthors } = useBlueskyAuthorProfiles(props.authors)
<div v-else class="flex items-center gap-2 min-w-0">
<div class="flex items-center">
<AuthorAvatar
v-for="(author, index) in resolvedAuthors"
v-for="(author, index) in authors"
:key="author.name"
:author="author"
size="md"
Expand All @@ -43,7 +41,7 @@ const { resolvedAuthors } = useBlueskyAuthorProfiles(props.authors)
/>
</div>
<span class="text-xs text-fg-muted font-mono truncate">
{{ resolvedAuthors.map(a => a.name).join(', ') }}
{{ authors.map(a => a.name).join(', ') }}
</span>
</div>
</template>
4 changes: 2 additions & 2 deletions app/components/BlogPostListCard.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script setup lang="ts">
import type { Author } from '#shared/schemas/blog'
import type { ResolvedAuthor } from '#shared/schemas/blog'

defineProps<{
/** Authors of the blog post */
authors: Author[]
authors: ResolvedAuthor[]
/** Blog Title */
title: string
/** Tags such as OpenSource, Architecture, Community, etc. */
Expand Down
4 changes: 2 additions & 2 deletions app/components/Code/Viewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ watch(
<!-- Code content -->
<div class="code-content flex-1 overflow-x-auto min-w-0">
<!-- eslint-disable vue/no-v-html -- HTML is generated server-side by Shiki -->
<div ref="codeRef" class="code-lines w-fit" v-html="html" />
<div ref="codeRef" class="code-lines min-w-full w-fit" v-html="html" />
<!-- eslint-enable vue/no-v-html -->
</div>
</div>
Expand Down Expand Up @@ -157,7 +157,7 @@ watch(

/* Highlighted lines in code content - extend full width with negative margin */
.code-content :deep(.line.highlighted) {
background: rgb(234 179 8 / 0.2); /* yellow-500/20 */
@apply bg-yellow-500/20;
margin: 0 -1rem;
padding: 0 1rem;
}
Expand Down
6 changes: 5 additions & 1 deletion app/components/CopyToClipboardButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function handleClick() {
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"
:class="[
$style.copyButton,
copied ? 'text-accent bg-accent/10' : 'text-fg-muted bg-bg border-border',
copied ? ['text-accent', $style.copiedBg] : 'text-fg-muted bg-bg border-border',
]"
:aria-label="copied ? buttonAriaLabelCopied : buttonAriaLabelCopy"
v-bind="buttonAttrs"
Expand Down Expand Up @@ -80,6 +80,10 @@ function handleClick() {
translate 0.15s;
}

.copiedBg {
background-color: color-mix(in srgb, var(--accent) 10%, var(--bg));
}

@media (hover: none) {
.copyButton {
display: none;
Expand Down
99 changes: 28 additions & 71 deletions app/components/Header/ConnectorModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,22 @@ function handleDisconnect() {
disconnect()
}

// function copyCommand() {
// let command = executeNpmxConnectorCommand.value
// if (portInput.value !== '31415') {
// command += ` --port ${portInput.value}`
// }
// copy(command)
// }

// const selectedPM = useSelectedPackageManager()

// const executeNpmxConnectorCommand = computed(() => {
// return getExecuteCommand({
// packageName: 'npmx-connector',
// packageManager: selectedPM.value,
// })
// })
function copyCommand() {
let command = executeNpmxConnectorCommand.value
if (portInput.value !== '31415') {
command += ` --port ${portInput.value}`
}
copy(command)
}

const selectedPM = useSelectedPackageManager()

const executeNpmxConnectorCommand = computed(() => {
return getExecuteCommand({
packageName: 'npmx-connector',
packageManager: selectedPM.value,
})
})
</script>

<template>
Expand Down Expand Up @@ -87,26 +87,6 @@ function handleDisconnect() {

<!-- Disconnected state -->
<form v-else class="space-y-4" @submit.prevent="handleConnect">
<!-- Contributor-only notice -->
<div class="p-3 bg-amber-500/10 border border-amber-500/30 rounded-lg">
<div>
<span class="inline-block text-xs font-bold uppercase tracking-wider text-fg rounded">
{{ $t('connector.modal.contributor_badge') }}
</span>
<p class="text-sm text-fg-muted">
<i18n-t keypath="connector.modal.contributor_notice" scope="global">
<template #link>
<LinkBase
to="https://github.com/npmx-dev/npmx.dev/blob/main/CONTRIBUTING.md#local-connector-cli"
>
{{ $t('connector.modal.contributor_link') }}
</LinkBase>
</template>
</i18n-t>
</p>
</div>
</div>

<p class="text-sm text-fg-muted">
{{ $t('connector.modal.run_hint') }}
</p>
Expand All @@ -116,43 +96,20 @@ function handleDisconnect() {
dir="ltr"
>
<span class="text-fg-subtle">$</span>
<span class="text-fg-subtle ms-2">npx npmx-connector</span>
<ButtonBase
:aria-label="copied ? $t('connector.modal.copied') : $t('connector.modal.copy_command')"
@click="copy('npx npmx-connector')"
class="ms-auto"
:classicon="copied ? 'i-lucide:check text-green-500' : 'i-lucide:copy'"
/>
<span class="text-fg-subtle ms-2">{{ executeNpmxConnectorCommand }}</span>
<div class="ms-auto flex items-center gap-2">
<!-- Disable teleport in a modal dialog -->
<PackageManagerSelect :teleport="false" />

<ButtonBase
:aria-label="copied ? $t('connector.modal.copied') : $t('connector.modal.copy_command')"
@click="copyCommand"
class="ms-auto"
:classicon="copied ? 'i-lucide:check text-green-500' : 'i-lucide:copy'"
/>
</div>
</div>

<!-- TODO: Uncomment when npmx-connector is published to npm
<div
class="flex items-center p-3 bg-bg-muted border border-border rounded-lg font-mono text-sm"
>
<span class="text-fg-subtle">$</span>
<span class="text-fg-subtle ms-2">{{ executeNpmxConnectorCommand }}</span>
<div class="ms-auto flex items-center gap-2">
<PackageManagerSelect />

<button
type="button"
:aria-label="
copied ? $t('connector.modal.copied') : $t('connector.modal.copy_command')
"
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"
@click="copyCommand"
>
<span v-if="!copied" class="i-lucide:copy block w-5 h-5" aria-hidden="true" />
<span
v-else
class="i-lucide:check block w-5 h-5 text-green-500"
aria-hidden="true"
/>
</button>
</div>
</div>
-->

<p class="text-sm text-fg-muted">{{ $t('connector.modal.paste_token') }}</p>

<div class="space-y-3">
Expand Down
18 changes: 17 additions & 1 deletion app/components/Header/SearchBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@ const showSearchBar = computed(() => {
})

const { model: searchQuery, startSearch } = useGlobalSearch('header')
const hasSearchQuery = computed(() => searchQuery.value.trim().length > 0)

function handleSubmit() {
startSearch()
}

function clearSearch() {
searchQuery.value = ''
inputRef.value?.focus()
}

// Expose focus method for parent components
const inputRef = useTemplateRef('inputRef')
function focus() {
Expand Down Expand Up @@ -52,11 +58,21 @@ defineExpose({ focus })
name="q"
:placeholder="$t('search.placeholder')"
no-correct
class="w-full min-w-25 ps-7"
class="w-full min-w-25 ps-7 pe-8"
@focus="isSearchFocused = true"
@blur="isSearchFocused = false"
size="small"
/>
<button
v-if="hasSearchQuery"
type="button"
class="absolute inset-ie-2 h-6 w-6 items-center justify-center rounded text-fg-muted hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent group-focus-within:flex group-hover:inline-flex hidden"
@click="clearSearch"
aria-hidden="true"
tabindex="-1"
>
<span class="i-lucide:circle-x h-4 w-4" />
</button>
<button type="submit" class="sr-only">{{ $t('search.button') }}</button>
</div>
</div>
Expand Down
Loading
Loading