En-tête de tableau - DsfrTableHeader
Enfant de DsfrHeaders
(attention au pluriel), DsfrHeader
(ici donc au singulier) permet de personnaliser complètement les en-tête de vos tableaux, et il va y mettre une touche de magie !
Parfait pour ajouter du texte et des icônes personnalisées, ce composant est un incontournable pour un tableau élégant et fonctionnel.
🏅 La documentation sur le tableau sur le DSFR
La story sur l’en-tête de tableau sur le storybook de VueDsfr🛠️ Props
Nom | Type | Défaut | Obligatoire | Description |
---|---|---|---|---|
header | string | '' | Le texte de l'en-tête du tableau. | |
headerAttrs | Object | {} | Les attributs HTML supplémentaires pour l'élément <th> . | |
icon | string | Object | undefined | undefined | L'icône à afficher dans l'en-tête. Peut être une chaîne ou un objet pour les icônes personnalisées. |
📝 Exemples
Exemple basique
vue
<DsfrTableHeader header="Nom" />
Exemple avec attributs supplémentaires
vue
<DsfrTableHeader
header="Age"
:headerAttrs="{ class: 'header-age', id: 'age-header' }"
/>
Exemple avec icône
vue
<DsfrTableHeader
header="Ville"
icon="ri-location-pin"
/>
Exemple avec icône
vue
<DsfrTableHeader
header="Ville"
icon="fr-icon-mail-line"
/>
Exemple complet
vue
<script lang="ts" setup>
import { computed, ref } from 'vue'
import DsfrTable from '../DsfrTable.vue'
import DsfrTableHeader from '../DsfrTableHeader.vue'
const icon = ref<{ name: string } | undefined>({
name: 'ri-sort-desc',
})
const header = 'En-tête'
const headerAttrs = computed(() => ({
class: 'ns-resize',
onClick: ($event) => {
$event.preventDefault()
const iconName = icon.value?.name
icon.value = iconName === 'ri-sort-desc'
? { name: 'ri-sort-asc' }
: iconName === 'ri-sort-asc'
? undefined
: { name: 'ri-sort-desc' }
},
}))
</script>
<template>
<DsfrTable
title="Titre du tableau"
>
<template #header>
<tr>
<DsfrTableHeader
class="flex justify-between items-center"
:header="header"
:header-attrs="headerAttrs"
:icon="icon"
/>
</tr>
</template>
<tr>
<td>
Corps du tableau
</td>
</tr>
</DsfrTable>
</template>
<style scoped>
.ns-resize {
cursor: ns-resize;
}
.flex {
display: flex;
}
.justify-between {
justify-content: space-between;
}
.items-center {
align-items: center;
}
</style>
⚙️ Code source du composant
vue
<script lang="ts" setup>
import { computed } from 'vue'
import VIcon from '../VIcon/VIcon.vue'
import type { DsfrTableHeaderProps } from './DsfrTable.types'
export type { DsfrTableHeaderProps }
const props = withDefaults(defineProps<DsfrTableHeaderProps>(), {
header: '',
headerAttrs: () => ({}),
icon: undefined,
})
const dsfrIcon = computed(() => {
return props.icon && typeof props.icon === 'string' && props.icon.startsWith('fr-') ? props.icon : ''
})
const iconProps = computed(() => dsfrIcon.value ? undefined : typeof props.icon === 'string' ? { name: props.icon } : props.icon)
</script>
<template>
<th
v-bind="headerAttrs"
scope="col"
>
{{ header }}
<VIcon
v-if="icon && !dsfrIcon"
v-bind="iconProps"
/>
<span
v-if="dsfrIcon"
:class="{ [String(icon)]: dsfrIcon }"
/>
</th>
</template>
ts
import type { HTMLAttributes, TdHTMLAttributes, ThHTMLAttributes } from 'vue'
import type VIcon from '../VIcon/VIcon.vue'
export type DsfrTableRowProps = {
rowData?: (string | Record<string, any>)[]
rowAttrs?: HTMLAttributes
}
export type DsfrTableHeaderProps = {
header?: string
headerAttrs?: ThHTMLAttributes & { onClick?: (e: MouseEvent) => void }
icon?: string | InstanceType<typeof VIcon>['$props']
}
export type DsfrTableHeadersProps = (string | (DsfrTableHeaderProps & { text?: string }))[]
export type DsfrTableCellProps = {
field: string | Record<string, unknown>
cellAttrs?: TdHTMLAttributes
component?: string
text?: string
title?: string
class?: string
onClick?: Promise<void>
}
export type DsfrTableProps = {
title: string
headers?: DsfrTableHeadersProps
rows?: (DsfrTableRowProps | (DsfrTableCellProps | { component: string, [k: string]: unknown } | string)[])[]
rowKey?: ((row: (string | Record<string, any>)[] | undefined) => string | number | symbol | undefined) | string
noCaption?: boolean
pagination?: boolean
currentPage?: number
resultsDisplayed?: number
}