Skip to content

Commit 0588c12

Browse files
committed
fix: fix RTL comformity, fix lint/types, polish tests
1 parent f9affda commit 0588c12

13 files changed

Lines changed: 76 additions & 852 deletions

app/components/compare/ComparisonGrid.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ defineProps<{
6868
text-align: center;
6969
}
7070
71-
/* First header cell rounded top-left */
71+
/* First header cell rounded top-start */
7272
.comparison-header > .comparison-cell-header:first-of-type {
73-
border-top-left-radius: 0.5rem;
73+
border-start-start-radius: 0.5rem;
7474
}
7575
76-
/* Last header cell rounded top-right */
76+
/* Last header cell rounded top-end */
7777
.comparison-header > .comparison-cell-header:last-of-type {
78-
border-top-right-radius: 0.5rem;
78+
border-start-end-radius: 0.5rem;
7979
}
8080
</style>

app/components/compare/FacetSelector.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script setup lang="ts">
2+
import type { ComparisonFacet } from '#shared/types'
23
import { FACET_INFO, FACETS_BY_CATEGORY, CATEGORY_ORDER } from '#shared/types/comparison'
34
45
const { t } = useI18n()
@@ -18,7 +19,7 @@ const {
1819
const facetsByCategory = computed(() => {
1920
const result: Record<
2021
string,
21-
{ facet: string; info: (typeof FACET_INFO)[keyof typeof FACET_INFO] }[]
22+
{ facet: ComparisonFacet; info: (typeof FACET_INFO)[ComparisonFacet] }[]
2223
> = {}
2324
for (const category of CATEGORY_ORDER) {
2425
result[category] = FACETS_BY_CATEGORY[category].map(facet => ({
@@ -31,14 +32,14 @@ const facetsByCategory = computed(() => {
3132
3233
// Check if all non-comingSoon facets in a category are selected
3334
function isCategoryAllSelected(category: string): boolean {
34-
const facets = facetsByCategory.value[category]
35+
const facets = facetsByCategory.value[category] ?? []
3536
const selectableFacets = facets.filter(f => !f.info.comingSoon)
3637
return selectableFacets.length > 0 && selectableFacets.every(f => isFacetSelected(f.facet))
3738
}
3839
3940
// Check if no facets in a category are selected
4041
function isCategoryNoneSelected(category: string): boolean {
41-
const facets = facetsByCategory.value[category]
42+
const facets = facetsByCategory.value[category] ?? []
4243
const selectableFacets = facets.filter(f => !f.info.comingSoon)
4344
return selectableFacets.length > 0 && selectableFacets.every(f => !isFacetSelected(f.facet))
4445
}
@@ -114,7 +115,7 @@ function isCategoryNoneSelected(category: string): boolean {
114115
<span
115116
v-if="!info.comingSoon"
116117
class="w-3 h-3"
117-
:class="isFacetSelected(facet) ? 'i-carbon-checkmark' : 'i-carbon-add'"
118+
:class="isFacetSelected(facet) ? 'i-carbon:checkmark' : 'i-carbon:add'"
118119
aria-hidden="true"
119120
/>
120121
{{ info.label }}

app/components/compare/MetricRow.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ function getDiffIcon(diff?: DiffResult | null): string {
6464
if (!diff) return ''
6565
switch (diff.direction) {
6666
case 'increase':
67-
return 'i-carbon-arrow-up'
67+
return 'i-carbon:arrow-up'
6868
case 'decrease':
69-
return 'i-carbon-arrow-down'
69+
return 'i-carbon:arrow-down'
7070
case 'changed':
71-
return 'i-carbon-arrows-horizontal'
71+
return 'i-carbon:arrows-horizontal'
7272
default:
7373
return ''
7474
}
@@ -85,7 +85,7 @@ function getDiffIcon(diff?: DiffResult | null): string {
8585
<span class="text-xs text-fg-muted uppercase tracking-wider">{{ label }}</span>
8686
<span
8787
v-if="description"
88-
class="i-carbon-information w-3 h-3 text-fg-subtle"
88+
class="i-carbon:information w-3 h-3 text-fg-subtle"
8989
aria-hidden="true"
9090
/>
9191
</div>
@@ -99,15 +99,15 @@ function getDiffIcon(diff?: DiffResult | null): string {
9999
<!-- Background bar for numeric values -->
100100
<div
101101
v-if="showBar && value && getBarWidth(value) > 0"
102-
class="absolute inset-y-1 left-1 bg-fg/5 rounded-sm transition-all duration-300"
102+
class="absolute inset-y-1 inset-is-1 bg-fg/5 rounded-sm transition-all duration-300"
103103
:style="{ width: `calc(${getBarWidth(value)}% - 8px)` }"
104104
aria-hidden="true"
105105
/>
106106

107107
<!-- Loading state -->
108108
<template v-if="loading">
109109
<span
110-
class="i-carbon-circle-dash w-4 h-4 text-fg-subtle motion-safe:animate-spin"
110+
class="i-carbon:circle-dash w-4 h-4 text-fg-subtle motion-safe:animate-spin"
111111
aria-hidden="true"
112112
/>
113113
</template>

app/components/compare/PackageSelector.vue

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,19 @@ function handleBlur() {
102102
:aria-label="t('compare.selector.remove_package', { package: pkg })"
103103
@click="removePackage(pkg)"
104104
>
105-
<span class="i-carbon-close block w-3.5 h-3.5" aria-hidden="true" />
105+
<span class="i-carbon:close block w-3.5 h-3.5" aria-hidden="true" />
106106
</button>
107107
</div>
108108
</div>
109109

110110
<!-- Add package input -->
111111
<div v-if="packages.length < maxPackages" class="relative">
112112
<div class="relative">
113-
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-fg-subtle" aria-hidden="true">
114-
<span class="i-carbon-search w-4 h-4" />
113+
<span
114+
class="absolute inset-is-3 top-1/2 -translate-y-1/2 text-fg-subtle"
115+
aria-hidden="true"
116+
>
117+
<span class="i-carbon:search w-4 h-4" />
115118
</span>
116119
<input
117120
v-model="inputValue"
@@ -121,7 +124,7 @@ function handleBlur() {
121124
? t('compare.selector.search_first')
122125
: t('compare.selector.search_add')
123126
"
124-
class="w-full bg-bg-subtle border border-border rounded-lg pl-10 pr-4 py-2.5 font-mono text-sm text-fg placeholder:text-fg-subtle transition-colors duration-200 focus:border-accent focus-visible:outline-none"
127+
class="w-full bg-bg-subtle border border-border rounded-lg ps-10 pe-4 py-2.5 font-mono text-sm text-fg placeholder:text-fg-subtle transition-colors duration-200 focus:border-accent focus-visible:outline-none"
125128
aria-autocomplete="list"
126129
@focus="isInputFocused = true"
127130
@blur="handleBlur"
@@ -139,7 +142,7 @@ function handleBlur() {
139142
>
140143
<div
141144
v-if="isInputFocused && (filteredResults.length > 0 || isSearching)"
142-
class="absolute top-full left-0 right-0 mt-1 bg-bg-elevated border border-border rounded-lg shadow-lg z-50 max-h-64 overflow-y-auto"
145+
class="absolute top-full inset-x-0 mt-1 bg-bg-elevated border border-border rounded-lg shadow-lg z-50 max-h-64 overflow-y-auto"
143146
>
144147
<div v-if="isSearching" class="px-4 py-3 text-sm text-fg-muted">
145148
{{ t('compare.selector.searching') }}

app/composables/useFacetSelection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export function useFacetSelection(queryParam = 'facets') {
9292

9393
// Deselect all facets globally (keeps first facet to ensure at least one)
9494
function deselectAll(): void {
95-
selectedFacets.value = [DEFAULT_FACETS[0]]
95+
selectedFacets.value = [DEFAULT_FACETS[0] as ComparisonFacet]
9696
}
9797

9898
// Check if all facets are selected

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ function handleClick(event: MouseEvent) {
425425
class="px-2 py-1.5 font-mono text-xs rounded transition-colors duration-150 border border-transparent text-fg-subtle hover:text-fg hover:bg-bg hover:shadow hover:border-border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 inline-flex items-center gap-1.5"
426426
aria-keyshortcuts="c"
427427
>
428-
<span class="i-carbon-compare w-3 h-3" aria-hidden="true" />
428+
<span class="i-carbon:compare w-3 h-3" aria-hidden="true" />
429429
{{ $t('package.links.compare') }}
430430
<kbd
431431
class="inline-flex items-center justify-center w-4 h-4 text-xs bg-bg-muted border border-border rounded"
@@ -641,7 +641,7 @@ function handleClick(event: MouseEvent) {
641641
:to="{ path: '/compare', query: { packages: pkg.name } }"
642642
class="link-subtle font-mono text-sm inline-flex items-center gap-1.5"
643643
>
644-
<span class="i-carbon-compare w-4 h-4" aria-hidden="true" />
644+
<span class="i-carbon:compare w-4 h-4" aria-hidden="true" />
645645
{{ $t('package.links.compare') }}
646646
</NuxtLink>
647647
</li>

app/pages/compare.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ useSeoMeta({
137137

138138
<!-- Empty state -->
139139
<section v-else class="text-center py-16 border border-dashed border-border rounded-lg">
140-
<div class="i-carbon-compare w-12 h-12 text-fg-subtle mx-auto mb-4" aria-hidden="true" />
140+
<div class="i-carbon:compare w-12 h-12 text-fg-subtle mx-auto mb-4" aria-hidden="true" />
141141
<h2 class="font-mono text-lg text-fg-muted mb-2">{{ t('compare.packages.empty_title') }}</h2>
142142
<p class="text-sm text-fg-subtle max-w-md mx-auto">
143143
{{ t('compare.packages.empty_description') }}

test/nuxt/components/compare/FacetSelector.spec.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
22
import { ref } from 'vue'
33
import { mountSuspended } from '@nuxt/test-utils/runtime'
44
import FacetSelector from '~/components/compare/FacetSelector.vue'
5+
import type { ComparisonFacet } from '../../../../shared/types/comparison'
56
import { CATEGORY_ORDER, FACET_INFO, FACETS_BY_CATEGORY } from '../../../../shared/types/comparison'
67

78
// Mock useFacetSelection
@@ -88,7 +89,7 @@ describe('FacetSelector', () => {
8889

8990
const component = await mountSuspended(FacetSelector)
9091

91-
expect(component.find('.i-carbon-checkmark').exists()).toBe(true)
92+
expect(component.find('.i-carbon\\:checkmark').exists()).toBe(true)
9293
})
9394

9495
it('shows add icon for unselected facets', async () => {
@@ -97,7 +98,7 @@ describe('FacetSelector', () => {
9798

9899
const component = await mountSuspended(FacetSelector)
99100

100-
expect(component.find('.i-carbon-add').exists()).toBe(true)
101+
expect(component.find('.i-carbon\\:add').exists()).toBe(true)
101102
})
102103

103104
it('applies aria-pressed for selected state', async () => {
@@ -147,8 +148,8 @@ describe('FacetSelector', () => {
147148
const comingSoonButton = buttons.find(b => b.text().includes('Total Dependencies'))
148149

149150
// Should not have checkmark or add icon
150-
expect(comingSoonButton?.find('.i-carbon-checkmark').exists()).toBe(false)
151-
expect(comingSoonButton?.find('.i-carbon-add').exists()).toBe(false)
151+
expect(comingSoonButton?.find('.i-carbon\\:checkmark').exists()).toBe(false)
152+
expect(comingSoonButton?.find('.i-carbon\\:add').exists()).toBe(false)
152153
})
153154

154155
it('does not call toggleFacet when comingSoon facet is clicked', async () => {
@@ -168,8 +169,8 @@ describe('FacetSelector', () => {
168169
const component = await mountSuspended(FacetSelector)
169170

170171
// Find the first 'all' button (for performance category)
171-
const allButtons = component.findAll('button').filter(b => b.text() === 'all')
172-
await allButtons[0].trigger('click')
172+
const allButton = component.findAll('button').find(b => b.text() === 'all')
173+
await allButton!.trigger('click')
173174

174175
expect(mockSelectCategory).toHaveBeenCalledWith('performance')
175176
})
@@ -178,8 +179,8 @@ describe('FacetSelector', () => {
178179
const component = await mountSuspended(FacetSelector)
179180

180181
// Find the first 'none' button (for performance category)
181-
const noneButtons = component.findAll('button').filter(b => b.text() === 'none')
182-
await noneButtons[0].trigger('click')
182+
const noneButton = component.findAll('button').find(b => b.text() === 'none')
183+
await noneButton!.trigger('click')
183184

184185
expect(mockDeselectCategory).toHaveBeenCalledWith('performance')
185186
})
@@ -190,13 +191,15 @@ describe('FacetSelector', () => {
190191
f => !FACET_INFO[f].comingSoon,
191192
)
192193
mockSelectedFacets.value = performanceFacets
193-
mockIsFacetSelected.mockImplementation((f: string) => performanceFacets.includes(f))
194+
mockIsFacetSelected.mockImplementation((f: string) =>
195+
performanceFacets.includes(f as ComparisonFacet),
196+
)
194197

195198
const component = await mountSuspended(FacetSelector)
196199

197-
const allButtons = component.findAll('button').filter(b => b.text() === 'all')
200+
const allButton = component.findAll('button').find(b => b.text() === 'all')
198201
// First all button (performance) should be disabled
199-
expect(allButtons[0].attributes('disabled')).toBeDefined()
202+
expect(allButton!.attributes('disabled')).toBeDefined()
200203
})
201204

202205
it('disables none button when no facets in category are selected', async () => {
@@ -206,9 +209,9 @@ describe('FacetSelector', () => {
206209

207210
const component = await mountSuspended(FacetSelector)
208211

209-
const noneButtons = component.findAll('button').filter(b => b.text() === 'none')
212+
const noneButton = component.findAll('button').find(b => b.text() === 'none')
210213
// First none button (performance) should be disabled
211-
expect(noneButtons[0].attributes('disabled')).toBeDefined()
214+
expect(noneButton!.attributes('disabled')).toBeDefined()
212215
})
213216
})
214217

test/nuxt/components/compare/MetricRow.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ describe('MetricRow', () => {
251251
{ raw: 100, display: '100', status: 'neutral' },
252252
{ raw: 100, display: '100', status: 'neutral' },
253253
],
254-
diffs: [null, { direction: 'same', display: '0%', favorable: null }],
254+
diffs: [null, { direction: 'same', display: '0%', favorable: undefined }],
255255
},
256256
})
257257
expect(component.find('.i-carbon-arrow-up').exists()).toBe(false)

0 commit comments

Comments
 (0)