Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion app/components/AppFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,12 @@ onMounted(() => {
z-index: 40;
/* Hidden by default (translated off-screen) */
transform: translateY(100%);
transition: transform 0.3s ease-out;
}

@media (prefers-reduced-motion: no-preference) {
.footer-scroll-state {
transition: transform 0.3s ease-out;
}
}

/* Show footer when user can scroll up (meaning they've scrolled down) */
Expand Down
4 changes: 3 additions & 1 deletion app/components/LoadingSpinner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ const { t } = useI18n()

<template>
<div aria-busy="true" class="flex items-center gap-3 text-fg-muted font-mono text-sm py-8">
<span class="w-4 h-4 border-2 border-fg-subtle border-t-fg rounded-full animate-spin" />
<span
class="w-4 h-4 border-2 border-fg-subtle border-t-fg rounded-full motion-safe:animate-spin"
/>
{{ text ?? t('common.loading') }}
</div>
</template>
2 changes: 1 addition & 1 deletion app/components/OrgMembersPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ watch(lastExecutionTime, () => {
>
<span
class="i-carbon-renew block w-4 h-4"
:class="{ 'animate-spin': isLoading || isLoadingTeams }"
:class="{ 'motion-safe:animate-spin': isLoading || isLoadingTeams }"
aria-hidden="true"
/>
</button>
Expand Down
4 changes: 2 additions & 2 deletions app/components/OrgTeamsPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ watch(lastExecutionTime, () => {
<!-- Loading state -->
<div v-if="isLoadingTeams && teams.length === 0" class="p-8 text-center">
<span
class="i-carbon-rotate-180 block w-5 h-5 text-fg-muted animate-spin mx-auto"
class="i-carbon-rotate-180 block w-5 h-5 text-fg-muted motion-safe:animate-spin mx-auto"
aria-hidden="true"
/>
<p class="font-mono text-sm text-fg-muted mt-2">{{ $t('org.teams.loading') }}</p>
Expand Down Expand Up @@ -390,7 +390,7 @@ watch(lastExecutionTime, () => {
</span>
<span
v-if="isLoadingUsers[teamName]"
class="i-carbon-rotate-180 w-3 h-3 text-fg-muted animate-spin"
class="i-carbon-rotate-180 w-3 h-3 text-fg-muted motion-safe:animate-spin"
aria-hidden="true"
/>
</button>
Expand Down
2 changes: 1 addition & 1 deletion app/components/PackageAccessControls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ watch(
>
<span
class="i-carbon-renew block w-3.5 h-3.5"
:class="{ 'animate-spin': isLoadingCollaborators }"
:class="{ 'motion-safe:animate-spin': isLoadingCollaborators }"
aria-hidden="true"
/>
</button>
Expand Down
6 changes: 4 additions & 2 deletions app/components/PackageList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ defineExpose({
:show-publisher="showPublisher"
:selected="index === (selectedIndex ?? -1)"
:index="index"
class="animate-fade-in animate-fill-both"
class="motion-safe:animate-fade-in motion-safe:animate-fill-both"
:style="{ animationDelay: `${Math.min(index * 0.02, 0.3)}s` }"
@focus="emit('select', $event)"
/>
Expand All @@ -122,7 +122,9 @@ defineExpose({
<!-- Loading indicator -->
<div v-if="isLoading" class="py-4 flex items-center justify-center">
<div class="flex items-center gap-3 text-fg-muted font-mono text-sm">
<span class="w-4 h-4 border-2 border-fg-subtle border-t-fg rounded-full animate-spin" />
<span
class="w-4 h-4 border-2 border-fg-subtle border-t-fg rounded-full motion-safe:animate-spin"
/>
{{ $t('common.loading_more') }}
</div>
</div>
Expand Down
6 changes: 5 additions & 1 deletion app/components/PackageSkeleton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ const { t } = useI18n()
</script>

<template>
<article aria-busy="true" :aria-label="t('package.skeleton.loading')" class="animate-fade-in">
<article
aria-busy="true"
:aria-label="t('package.skeleton.loading')"
class="motion-safe:animate-fade-in"
>
<!-- Package header - matches header in [...name].vue -->
<header class="mb-8 pb-8 border-b border-border">
<div class="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4 mb-4">
Expand Down
6 changes: 4 additions & 2 deletions app/components/PackageVersions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,8 @@ function getTagVersions(tag: string): VersionDisplay[] {
>
<span
v-if="loadingTags.has(row.tag)"
class="i-carbon-rotate-180 w-3 h-3 animate-spin"
class="i-carbon-rotate-180 w-3 h-3 motion-safe:animate-spin"
data-testid="loading-spinner"
aria-hidden="true"
/>
<span
Expand Down Expand Up @@ -457,7 +458,8 @@ function getTagVersions(tag: string): VersionDisplay[] {
>
<span
v-if="otherVersionsLoading"
class="i-carbon-rotate-180 w-3 h-3 animate-spin"
class="i-carbon-rotate-180 w-3 h-3 motion-safe:animate-spin"
data-testid="loading-spinner"
aria-hidden="true"
/>
<span
Expand Down
4 changes: 2 additions & 2 deletions app/pages/[...package].vue
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ defineOgImageComponent('Package', {
<main class="container py-8 sm:py-12 overflow-hidden w-full">
<PackageSkeleton v-if="status === 'pending'" />

<article v-else-if="status === 'success' && pkg" class="animate-fade-in min-w-0">
<article v-else-if="status === 'success' && pkg" class="motion-safe:animate-fade-in min-w-0">
<!-- Package header -->
<header class="mb-8 pb-8 border-b border-border">
<div class="mb-4">
Expand Down Expand Up @@ -627,7 +627,7 @@ defineOgImageComponent('Package', {
class="inline-flex items-center gap-1 text-fg-subtle"
>
<span
class="i-carbon-circle-dash w-3 h-3 animate-spin motion-reduce:animate-none"
class="i-carbon-circle-dash w-3 h-3 motion-safe:animate-spin"
aria-hidden="true"
/>
</span>
Expand Down
8 changes: 4 additions & 4 deletions app/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,21 @@ defineOgImageComponent('Default')
<header class="flex-1 flex flex-col items-center justify-center text-center py-20">
<!-- Animated title -->
<h1
class="font-mono text-5xl sm:text-7xl md:text-8xl font-medium tracking-tight mb-4 animate-fade-in animate-fill-both"
class="font-mono text-5xl sm:text-7xl md:text-8xl font-medium tracking-tight mb-4 motion-safe:animate-fade-in motion-safe:animate-fill-both"
>
<span class="text-accent"><span class="-tracking-0.2em">.</span>/</span>npmx
</h1>

<p
class="text-fg-muted text-lg sm:text-xl max-w-md mb-12 animate-slide-up animate-fill-both"
class="text-fg-muted text-lg sm:text-xl max-w-md mb-12 motion-safe:animate-slide-up motion-safe:animate-fill-both"
style="animation-delay: 0.1s"
>
{{ $t('tagline') }}
</p>

<!-- Search form with micro-interactions -->
<search
class="w-full max-w-xl animate-slide-up animate-fill-both"
class="w-full max-w-xl motion-safe:animate-slide-up motion-safe:animate-fill-both"
style="animation-delay: 0.2s"
>
<form role="search" class="relative" @submit.prevent="handleSearch">
Expand Down Expand Up @@ -90,7 +90,7 @@ defineOgImageComponent('Default')
<!-- Popular packages -->
<nav
:aria-label="$t('nav.popular_packages')"
class="pb-20 text-center animate-fade-in animate-fill-both"
class="pb-20 text-center motion-safe:animate-fade-in motion-safe:animate-fill-both"
style="animation-delay: 0.3s"
>
<ul class="flex flex-wrap items-center justify-center gap-x-6 gap-y-3 list-none m-0 p-0">
Expand Down
2 changes: 1 addition & 1 deletion app/pages/search.vue
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ defineOgImageComponent('Default', {
</div>
<button
type="button"
class="shrink-0 px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-colors duration-200 hover:bg-fg/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
class="shrink-0 px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md motion-safe:transition-colors motion-safe:duration-200 hover:bg-fg/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
@click="claimModalOpen = true"
>
{{ t('search.claim_button', { name: query }) }}
Expand Down
4 changes: 2 additions & 2 deletions test/nuxt/components/PackageVersions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ describe('PackageVersions', () => {

// Should show loading spinner (animate-spin class)
await vi.waitFor(() => {
expect(component.find('.animate-spin').exists()).toBe(true)
expect(component.find('[data-testid="loading-spinner"]').exists()).toBe(true)
})

// Resolve the promise to clean up
Expand Down Expand Up @@ -816,7 +816,7 @@ describe('PackageVersions', () => {

// Should show loading spinner
await vi.waitFor(() => {
expect(component.find('.animate-spin').exists()).toBe(true)
expect(component.find('[data-testid="loading-spinner"]').exists()).toBe(true)
})

// Resolve the promise to clean up
Expand Down