feat: editorial article list

This commit is contained in:
Florian Sylvain committed 2026-11-02 07:28:44 +01:00
1 parent a0b3c58c52
commit a671b81f80
103 files changed
+6493 -1805

No files matched your search

+99
View File
@@ -0,0 +1,99 @@
<script setup lang="ts">
import { t, formatNumber } from '@/i18n'
import { computed, ref } from 'vue'
import { useScrollEdges } from '@/composables/useScrollEdges'
import type { ListTab, ListTabKey } from '@/lib/storyList'
import { UNDERLINE_TAB_TRIGGER } from '@/lib/tabStyles'
const SCROLL_STEP_PX = 96
const EMPTY_COUNT = '–'
const props = defineProps<{
tabs: ListTab[]
active: ListTabKey
}>()
const emit = defineEmits<{ select: [key: ListTabKey] }>()
const scroller = ref<HTMLElement | null>(null)
const { hiddenBefore, hiddenAfter } = useScrollEdges(scroller)
const model = computed({
get: () => props.active,
set: (value: ListTabKey) => emit('select', value),
})
const items = computed(() =>
props.tabs.map((tab) => ({
label: tab.label,
value: tab.key,
count: tab.count === null ? EMPTY_COUNT : formatNumber(tab.count),
})),
)
function scroll(direction: -1 | 1) {
scroller.value?.scrollBy({ left: direction * SCROLL_STEP_PX })
}
</script>
<template>
<div class="relative flex items-center gap-1 border-b border-default">
<UButton
color="neutral"
variant="ghost"
icon="i-lucide-chevron-left"
:aria-label="t('Scroll tabs left')"
:disabled="!hiddenBefore"
class="size-11 shrink-0 justify-center md:hidden"
@click="scroll(-1)"
/>
<div class="relative min-w-0 flex-1">
<div
ref="scroller"
class="overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
>
<UTabs
v-model="model"
:items="items"
variant="link"
color="neutral"
:content="false"
:aria-label="t('Article views')"
class="w-max"
:ui="{
list: 'gap-4 border-b-0 p-0 md:gap-6',
trigger: `${UNDERLINE_TAB_TRIGGER} shrink-0 whitespace-nowrap md:h-9.5 max-md:h-11 max-md:text-base`,
}"
>
<template #default="{ item }">
<span class="truncate">{{ item.label }}</span
>{{ ' '
}}<span class="font-normal text-muted">{{
(item as (typeof items)[number]).count
}}</span>
</template>
</UTabs>
</div>
<div
v-if="hiddenAfter"
aria-hidden="true"
class="pointer-events-none absolute inset-y-0 right-0 w-7 bg-linear-to-r from-transparent to-(--ui-bg) md:hidden"
/>
<div
v-if="hiddenBefore"
aria-hidden="true"
class="pointer-events-none absolute inset-y-0 left-0 w-7 bg-linear-to-l from-transparent to-(--ui-bg) md:hidden"
/>
</div>
<UButton
color="neutral"
variant="ghost"
icon="i-lucide-chevron-right"
:aria-label="t('Scroll tabs right')"
:disabled="!hiddenAfter"
class="size-11 shrink-0 justify-center md:hidden"
@click="scroll(1)"
/>
</div>
</template>