Contenu d’onglet - DsfrTabContent
🌟 Introduction
Le composant DsfrTabContent
est conçu pour être utilisé comme panneau de contenu dans une interface à onglets. Il utilise une transition fluide pour animer l'affichage du contenu de l'onglet sélectionné.
Ce composant doit s’utiliser dans un DsfrTabs
.
📐 Structure
<DsfrTabContent>
: Le composant principal.- Affiche le contenu associé à un onglet.
- Utilise une transition animée pour l'apparition et la disparition du contenu.
- Utilise des classes pour gérer l'état de sélection de l'onglet.
🛠️ Props
Propriété | Type | Description | Valeur par défaut |
---|---|---|---|
panelId | string | ID unique pour le panneau, utilisé pour l'accessibilité. | obligatoire |
tabId | string | ID unique de l'onglet associé, utilisé pour l'accessibilité. | obligatoire |
📡 Événements
Ce composant ne déclenche pas d'événements spécifiques.
🧩 Slots
default
: Slot pour insérer le contenu de l'onglet à afficher.
📝 Exemples
vue
<script lang="ts" setup>
import { ref } from 'vue'
import DsfrButton from '../../DsfrButton/DsfrButton.vue'
import DsfrTabContent from '../DsfrTabContent.vue'
import DsfrTabItem from '../DsfrTabItem.vue'
import DsfrTabs from '../DsfrTabs.vue'
const tabListName = 'Liste d’onglet'
const title1 = 'Titre 1'
const tabTitles = [
{ title: title1, icon: 'ri-checkbox-circle-line', tabId: 'tab-0', panelId: 'tab-content-0' },
{ title: 'Titre 2', icon: 'ri-checkbox-circle-line', tabId: 'tab-1', panelId: 'tab-content-1' },
{ title: 'Titre 3', icon: 'ri-checkbox-circle-line', tabId: 'tab-2', panelId: 'tab-content-2' },
{ title: 'Titre 4', icon: 'ri-checkbox-circle-line', tabId: 'tab-3', panelId: 'tab-content-3' },
]
const activeTab = ref(0)
const selectPrevious = async () => {
const newIndex = activeTab.value === 0 ? tabTitles.length - 1 : activeTab.value - 1
activeTab.value = newIndex
}
const selectNext = async () => {
const newIndex = activeTab.value === tabTitles.length - 1 ? 0 : activeTab.value + 1
activeTab.value = newIndex
}
const selectFirst = async () => {
activeTab.value = 0
}
const selectLast = async () => {
activeTab.value = tabTitles.length - 1
}
</script>
<template>
<div class="fr-container fr-my-2w">
<DsfrTabs
v-model="activeTab"
:tab-list-name="tabListName"
>
<template #tab-items>
<DsfrTabItem
v-for="(tab, index) of tabTitles"
:key="tab.tabId"
:tab-id="tab.tabId"
:panel-id="tab.panelId"
:icon="tab.icon"
@click="activeTab = index"
@next="selectNext()"
@previous="selectPrevious()"
@first="selectFirst()"
@last="selectLast()"
>
{{ tab.title }}
</DsfrTabItem>
</template>
<DsfrTabContent
panel-id="tab-content-0"
tab-id="tab-0"
>
<div>Contenu 1 avec d'<em>autres composants</em></div>
</DsfrTabContent>
<DsfrTabContent
panel-id="tab-content-1"
tab-id="tab-1"
>
<div>Contenu 2 avec d'<strong>autres composants</strong></div>
</DsfrTabContent>
<DsfrTabContent
panel-id="tab-content-2"
tab-id="tab-2"
>
<div>Contenu 3 avec d'<em><strong>autres composants</strong></em></div>
</DsfrTabContent>
<DsfrTabContent
panel-id="tab-content-3"
tab-id="tab-3"
>
<div>
<p>Contenu 4 avec beaucoup de contenus</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Vitae fugit sit et eos a officiis adipisci nulla repellat cupiditate? Assumenda, explicabo ullam laboriosam ex sit corporis enim illum a itaque.</p>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quasi animi quis quos consectetur alias delectus recusandae sunt quisquam incidunt provident quidem, at voluptatibus id, molestias et? Temporibus perspiciatis aut voluptates.</p>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quibusdam obcaecati at delectus iusto possimus! Molestiae, iusto veritatis. Nostrum magni officiis autem, in ullam aliquid, mollitia, commodi architecto vitae omnis vero.</p>
</div>
</DsfrTabContent>
</DsfrTabs>
<div style="display: flex; gap: 1rem; margin-block: 1rem;">
<DsfrButton
label="Activer le 1er onglet"
:disabled="activeTab === 0"
@click="activeTab = 0"
/>
<DsfrButton
label="Activer le 2è onglet"
:disabled="activeTab === 1"
@click="activeTab = 1"
/>
<DsfrButton
label="Activer le 3è onglet"
:disabled="activeTab === 2"
@click="activeTab = 2"
/>
<DsfrButton
label="Activer le dernier onglet"
:disabled="activeTab === tabTitles.length - 1"
@click="activeTab = tabTitles.length - 1"
/>
</div>
</div>
</template>
⚙️ Code source du composant
vue
<script setup lang="ts">
import { computed, inject, toRef } from 'vue'
import { registerTabKey } from './injection-key'
export type DsfrTabContentProps = {
panelId: string
tabId: string
}
const props = defineProps<DsfrTabContentProps>()
const values = { true: '100%', false: '-100%' }
const useTab = inject(registerTabKey)!
const { isVisible, asc } = useTab(toRef(() => props.tabId))
// @ts-expect-error this will be fine
const translateValueFrom = computed(() => values[String(asc?.value)])
// @ts-expect-error this will be fine
const translateValueTo = computed(() => values[String(!asc?.value)])
</script>
<template>
<Transition
name="slide-fade"
mode="in-out"
>
<div
v-show="isVisible"
:id="panelId"
class="fr-tabs__panel"
:class="{
'fr-tabs__panel--selected': isVisible,
}"
role="tabpanel"
:aria-labelledby="tabId"
:tabindex="isVisible ? 0 : -1"
>
<!-- @slot Slot par défaut pour le contenu de l’onglet. Sera dans `<div class="fr-tabs__panel">` -->
<slot />
</div>
</Transition>
</template>
<style scoped>
.slide-fade-enter-active {
transition: all 0.3s ease-out;
}
.slide-fade-leave-active {
transition: all 0.3s ease-out;
}
.slide-fade-enter-from {
transform: translateX(v-bind(translateValueFrom));
opacity: 0;
}
.slide-fade-leave-to {
transform: translateX(v-bind(translateValueTo));
opacity: 0;
}
</style>
ts
export type DsfrTabItemProps = {
panelId: string
tabId: string
icon?: string
}
export type DsfrTabContentProps = {
panelId: string
tabId: string
}
export type DsfrTabsProps = {
modelValue: number
tabListName: string
tabTitles: (Partial<DsfrTabItemProps> & { title: string })[]
tabContents?: string[]
}
ts
import type { InjectionKey, Ref } from 'vue'
type RegisterTab = (title: Ref<string>) => {
isVisible: Ref<boolean>
asc?: Ref<boolean>
}
export const registerTabKey: InjectionKey<RegisterTab> = Symbol('tabs')