Skip to content

Commit 2370eeb

Browse files
authored
Merge pull request #625 from dnum-mi/develop
Develop
2 parents 21056c1 + f4b6396 commit 2370eeb

File tree

10 files changed

+244
-74
lines changed

10 files changed

+244
-74
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { render } from '@testing-library/vue'
2+
import DsfrBackToTop from './DsfrBackToTop.vue'
3+
4+
describe('DsfrBackToTop', () => {
5+
it('should render a success BackToTop', async () => {
6+
const label = 'Haut de page'
7+
const expectClass = 'fr-link fr-icon-arrow-up-fill'
8+
const position = 'left'
9+
10+
const { getByText } = render(DsfrBackToTop, {
11+
props: {
12+
label,
13+
position,
14+
},
15+
})
16+
17+
const anchorElement = getByText(label)
18+
expect(anchorElement).toBeDefined()
19+
// Verifier si a possède la class attendu
20+
expect(anchorElement).toHaveClass(expectClass)
21+
expect(anchorElement).toHaveClass(`fr-link--icon-${position}`)
22+
})
23+
})
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import DsfrBackToTop from './DsfrBackToTop.vue'
2+
3+
/**
4+
* [Voir quand l’utiliser sur la documentation du DSFR](https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/retour-en-haut-de-page/)
5+
*/
6+
export default {
7+
component: DsfrBackToTop,
8+
title: 'Composants/DsfrBackToTop',
9+
argTypes: {
10+
label: {
11+
control: 'text',
12+
description: 'Titre (texte)',
13+
},
14+
position: {
15+
options: ['left', 'right'],
16+
control: 'select',
17+
description: '(Optionnel) **Position** de la fleche îcone : `left` (à gauche), `right` (à droite)',
18+
},
19+
},
20+
}
21+
22+
export const BackToTop = (args) => ({
23+
components: {
24+
DsfrBackToTop,
25+
},
26+
data () {
27+
return args
28+
},
29+
template: `
30+
<DsfrBackToTop :label="label" :position="position"/>
31+
`,
32+
})
33+
BackToTop.args = {
34+
position: 'left',
35+
label: 'Haut de page',
36+
}
37+
38+
export const TousLesBacktoTop = (args) => ({
39+
components: {
40+
DsfrBackToTop,
41+
},
42+
data () {
43+
return args
44+
},
45+
template: `
46+
<p>
47+
<DsfrBackToTop label="Haut de page" position="left"/>
48+
</p>
49+
<p>
50+
<DsfrBackToTop label="Haut de page" position="right"/>
51+
</p>
52+
<p>
53+
<DsfrBackToTop label="Haut" position="right"/>
54+
</p>
55+
`,
56+
})
57+
TousLesBacktoTop.args = {
58+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<script setup lang="ts">
2+
withDefaults(defineProps<{
3+
label?: string
4+
position?: 'right' | 'left'
5+
}>(), {
6+
position: 'right',
7+
label: 'Haut de page',
8+
})
9+
</script>
10+
11+
<template>
12+
<a
13+
class="fr-link fr-icon-arrow-up-fill"
14+
:class="`fr-link--icon-${position}`"
15+
href="#top"
16+
>
17+
{{ label }}
18+
</a>
19+
</template>

src/components/DsfrTable/DsfrTable.vue

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<script lang="ts" setup>
2-
import { ref, watch } from 'vue'
2+
import { computed, ref, watch } from 'vue'
33
import DsfrTableRow, { type DsfrTableRowProps } from './DsfrTableRow.vue'
44
import DsfrTableHeaders from './DsfrTableHeaders.vue'
5-
import { type DsfrTableHeaderProps } from './DsfrTableHeader.vue'
5+
import { type DsfrTableHeadersProps } from './DsfrTableHeaders.vue'
66
77
const props = withDefaults(defineProps<{
88
title?: string
9-
headers?:(DsfrTableHeaderProps | string)[]
10-
rows?: (DsfrTableRowProps | string)[]
9+
headers?: DsfrTableHeadersProps
10+
rows?:(DsfrTableRowProps | string[])[]
1111
noCaption?: boolean
1212
pagination?: boolean
1313
defaultCurrentPage?: number
@@ -20,9 +20,8 @@ const props = withDefaults(defineProps<{
2020
defaultOptionSelected: 10,
2121
})
2222
23-
const getRowData = (row: (DsfrTableRowProps | string | ({component: string} & Record<string, any>))) => {
24-
// @ts-ignore TODO: find a way to improve types here
25-
return row.rowData || row
23+
const getRowData = (row: (DsfrTableRowProps | string[])) => {
24+
return Array.isArray(row) ? row : row.rowData
2625
}
2726
2827
const currentPage = ref(props.defaultCurrentPage)
@@ -31,15 +30,17 @@ const pageCount = ref(props.rows.length > optionSelected.value ? Math.ceil(props
3130
const paginationOptions = [5, 10, 25, 50, 100]
3231
const returnLowestLimit = () => currentPage.value * optionSelected.value - optionSelected.value
3332
const returnHighestLimit = () => currentPage.value * optionSelected.value
34-
let truncatedResults = props.rows.slice(returnLowestLimit(), returnHighestLimit())
3533
3634
watch(() => optionSelected.value, (newVal, OldVal) => {
37-
props.rows.length > optionSelected.value ? pageCount.value = Math.ceil(props.rows.length / newVal) : pageCount.value = 1
38-
truncatedResults = props.rows.slice(returnLowestLimit(), returnHighestLimit())
35+
pageCount.value = props.rows.length > optionSelected.value ? Math.ceil(props.rows.length / newVal) : 1
3936
})
4037
41-
watch(() => currentPage.value, (newVal, OldVal) => {
42-
truncatedResults = props.rows.slice(returnLowestLimit(), returnHighestLimit())
38+
const truncatedResults = computed(() => {
39+
if(props.pagination) {
40+
return props.rows.slice(returnLowestLimit(), returnHighestLimit())
41+
}
42+
43+
return props.rows;
4344
})
4445
4546
const goFirstPage = () => { currentPage.value = 1 }
@@ -54,7 +55,6 @@ const goNextPage = () => {
5455
}
5556
}
5657
const goLastPage = () => { currentPage.value = pageCount.value }
57-
5858
</script>
5959

6060
<template>
@@ -85,7 +85,7 @@ const goLastPage = () => { currentPage.value = pageCount.value }
8585
v-for="(row, i) of truncatedResults"
8686
:key="i"
8787
:row-data="getRowData(row)"
88-
:row-attrs="typeof row === 'string' ? {} : row.rowAttrs"
88+
:row-attrs="'rowAttrs' in row ? row.rowAttrs : {}"
8989
/>
9090
</template>
9191
<tr v-if="pagination">

src/components/DsfrTable/DsfrTableHeaders.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script setup lang="ts">
22
import DsfrTableHeader, { DsfrTableHeaderProps } from './DsfrTableHeader.vue'
33
4-
type Header = DsfrTableHeaderProps & { text?: string }
4+
export type DsfrTableHeadersProps = (string | (DsfrTableHeaderProps & { text?: string }))[]
55
66
defineProps<{
7-
headers:(DsfrTableHeaderProps | string)[]
7+
headers: DsfrTableHeadersProps
88
}>()
99
</script>
1010

@@ -15,7 +15,7 @@ defineProps<{
1515
<DsfrTableHeader
1616
v-for="(header, i) of headers"
1717
:key="i"
18-
:header="(header as Header).text || (header as string)"
18+
:header="(typeof header === 'object' ? header : {}).text || (header as string)"
1919
:header-attrs="(header as DsfrTableHeaderProps).headerAttrs"
2020
/>
2121
</tr>

src/components/DsfrTile/DsfrTile.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,28 @@ describe('DsfrTile', () => {
6868
expect(titleEl.parentNode.parentNode.parentNode.parentNode).toHaveClass('fr-tile--horizontal')
6969
expect(descriptionEl).toHaveClass('fr-tile__desc')
7070
})
71+
72+
it('should display a tile with a download link', async () => {
73+
const title = 'Titre de la tuile'
74+
const imgSrc = 'https://placekitten.com/80/80'
75+
const description = 'Lorem ipsum dolor sit amet, consectetur adipiscing, incididunt, ut labore et dol'
76+
const download = true
77+
const { getByText } = render(DsfrTile, {
78+
global: {
79+
plugins: [router],
80+
},
81+
props: {
82+
title,
83+
imgSrc,
84+
description,
85+
download,
86+
to: 'https://placekitten.com/80/80',
87+
},
88+
})
89+
90+
await router.isReady()
91+
92+
const titleEl = getByText(title)
93+
expect(titleEl).toHaveAttribute('download', 'true')
94+
})
7195
})

src/components/DsfrTile/DsfrTile.stories.ts

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -27,49 +27,52 @@ export default {
2727
control: 'boolean',
2828
description: 'Permet le basculement de la tuile en mode horizontal',
2929
},
30-
verticalAtMd: {
31-
control: 'boolean',
32-
description: 'Permet le basculement de la tuile en mode vertical au point de rupture "md"',
30+
vertical: {
31+
options: ['md', 'lg'],
32+
control: {
33+
type: 'select',
34+
},
35+
description: 'Permet le basculement de la tuile en mode vertical, selon le point de rupture "md" ou "lg" spécifié',
3336
},
34-
verticalAtLg: {
37+
disabled: {
3538
control: 'boolean',
36-
description: 'Permet le basculement de la tuile en mode vertical au point de rupture "lg"',
39+
description: 'Permet de rendre la tuile désactivée et non-cliquable',
3740
},
38-
small: {
41+
to: {
42+
control: 'text',
43+
description: 'Lien vers lequel la tuile pointe. Peut être une string ou objet à donner à `RouterLink` ou un lien externe (`string` commençant par `"http"`)',
44+
},
45+
titleTag: {
46+
control: 'text',
47+
description: 'Permet de choisir la balise contenant le titre de la tuile (h3 par défaut)',
48+
},
49+
download: {
3950
control: 'boolean',
40-
description: 'Permet d’afficher la tuile dans un plus petit format',
51+
description: 'Permet de passer la tuile en mode téléchargement',
4152
},
42-
disabled: {
53+
small: {
4354
control: 'boolean',
44-
description: 'Permet de rendre la tuile désactivée et non-cliquable',
55+
description: 'Permet de basculer la tuile en petit format',
4556
},
46-
download: {
57+
icon: {
4758
control: 'boolean',
48-
description: 'Variante de tuile indiquant que le lien permet de télécharger un fichier (la tuile de téléchargement est obligatoirement horizontale)',
59+
description: 'Permet de désactiver l\'icone associée au lien',
4960
},
5061
noBorder: {
5162
control: 'boolean',
52-
description: 'Variante de tuile sans bordure',
63+
description: 'Permet de désactiver la bordure de la tuile',
5364
},
54-
noBackground: {
65+
shadow: {
5566
control: 'boolean',
56-
description: 'Variante de tuile sans arrière-plan',
67+
description: 'Permet d\'ajouter une ombre portée à la tuile',
5768
},
58-
shadow: {
69+
noBackground: {
5970
control: 'boolean',
60-
description: 'Variante de tuile avec ombre portée',
71+
description: 'Permet de désactiver la couleur de fond de la tuile',
6172
},
6273
grey: {
6374
control: 'boolean',
64-
description: 'Variante de tuile plus contrastée avec arrière-plan grisé',
65-
},
66-
to: {
67-
control: 'text',
68-
description: 'Lien vers lequel la tuile pointe. Peut être une string ou objet à donner à `RouterLink` ou un lien externe (`string` commençant par `"http"`)',
69-
},
70-
titleTag: {
71-
control: 'text',
72-
description: 'Permet de choisir la balise contenant le titre de la tuile (h3 par défaut)',
75+
description: 'Permet de passer le fond de la tuile en gris',
7376
},
7477
},
7578
}
@@ -92,36 +95,34 @@ export const TuileSimple = (args) => ({
9295
:description="description"
9396
:details="details"
9497
:horizontal="horizontal"
95-
:verticalAtMd="verticalAtMd"
96-
:verticalAtLg="verticalAtLg"
97-
:small="small"
98+
:vertical="vertical"
9899
:disabled="false"
100+
:to="to"
101+
:title-tag="titleTag"
99102
:download="download"
100-
:noBorder="noBorder"
101-
:noBackground="noBackground"
103+
:small="small"
104+
:icon="icon"
105+
:no-border="noBorder"
102106
:shadow="shadow"
107+
:no-background="noBackground"
103108
:grey="grey"
104-
:to="to"
105-
:title-tag="titleTag"
106109
/>
107110
`,
108111

109112
})
110113
TuileSimple.args = {
111114
title: 'Ma formidable tuile',
112-
imgSrc: 'http://placekitten.com/g/80/80',
115+
imgSrc: 'http://placekitten.com/g/200/200',
113116
description: 'Une tuile absolument formidable',
114-
details: 'Quelques détails',
115117
horizontal: false,
116-
verticalAtMd: false,
117-
verticalAtLg: false,
118-
small: false,
119118
disabled: false,
119+
to: '#',
120+
titleTag: 'h2',
120121
download: false,
122+
small: false,
123+
icon: false,
121124
noBorder: false,
122-
noBackground: false,
123125
shadow: false,
126+
noBackground: false,
124127
grey: false,
125-
to: '#',
126-
titleTag: 'h2',
127128
}

0 commit comments

Comments
 (0)