Skip to content

Commit a949475

Browse files
committed
feat: ✨ permet d’utiliser les icônes DSFR
Désormais tous les composants qui ont une prop `icon` peuvent recevoir en valeur le nom d’une classe correspondant à une icône DSFR.
1 parent c6b1ec2 commit a949475

File tree

14 files changed

+85
-23
lines changed

14 files changed

+85
-23
lines changed

src/components/DsfrButton/DsfrButton.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ defineExpose({ focus })
2525
2626
const dsfrIcon = computed(() => typeof props.icon === 'string' && props.icon.startsWith('fr-icon-'))
2727
const defaultScale = computed(() => props.iconOnly ? 1.25 : 0.8325)
28-
const iconProps = computed(() => typeof props.icon === 'string' ? { name: props.icon, scale: defaultScale.value } : { scale: defaultScale.value, ...props.icon })
28+
const iconProps = computed(() => typeof props.icon === 'string'
29+
? { scale: defaultScale.value, name: props.icon }
30+
: { scale: defaultScale.value, ...props.icon },
31+
)
2932
</script>
3033

3134
<template>

src/components/DsfrButton/DsfrButtonGroup.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ onMounted(async () => {
8383
@click="onClick"
8484
/>
8585
</li>
86+
<!-- @slot Slot par défaut pour le contenu de la liste de boutons. Sera dans `<ul class="fr-btns-group">` -->
8687
<slot />
8788
</ul>
8889
</template>
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import type { OhVueIcon as VIcon } from 'oh-vue-icons'
12
import type { DsfrButtonProps } from '../DsfrButton/DsfrButton.types'
23

34
export type DsfrCalloutProps = {
45
title: string
56
content: string
67
titleTag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
78
button?: DsfrButtonProps
8-
icon?: string
9+
icon?: string | InstanceType<typeof VIcon>['$props']
910
}

src/components/DsfrCallout/DsfrCallout.vue

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,32 @@
11
<script lang="ts" setup>
2+
import { computed } from 'vue'
3+
24
import DsfrButton from '../DsfrButton/DsfrButton.vue'
35
46
import type { DsfrCalloutProps } from './DsfrCallout.types'
57
68
export type { DsfrCalloutProps }
79
8-
withDefaults(defineProps<DsfrCalloutProps>(), {
10+
const props = withDefaults(defineProps<DsfrCalloutProps>(), {
911
// @ts-ignore this is really undefined
1012
button: () => undefined,
1113
titleTag: 'h3',
1214
icon: undefined,
1315
})
16+
17+
const dsfrIcon = computed(() => typeof props.icon === 'string' && props.icon.startsWith('fr-icon-'))
18+
const iconProps = computed(() => dsfrIcon.value ? undefined : typeof props.icon === 'string' ? { name: props.icon } : { ...(props.icon ?? {}) })
1419
</script>
1520

1621
<template>
17-
<div class="fr-callout">
22+
<div
23+
class="fr-callout"
24+
:class="{ [String(icon)]: dsfrIcon }"
25+
>
26+
<VIcon
27+
v-if="iconProps"
28+
v-bind="iconProps"
29+
/>
1830
<component
1931
:is="titleTag"
2032
class="fr-callout__title"

src/components/DsfrFieldset/DsfrFieldset.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ withDefaults(defineProps<DsfrFieldsetProps>(), {
3737
<slot name="hint" />
3838
</span>
3939
</div>
40-
<!-- @slot Slot par défaut pour le contenu du fieldset (sera dans `<fieldset>`, après `</legend>`) -->
4140
<div class="fr-fieldset__element">
41+
<!-- @slot Slot par défaut pour le contenu du fieldset (sera dans `<div class="fr-fieldset__element">`) -->
4242
<slot />
4343
</div>
4444
</fieldset>

src/components/DsfrHeader/DsfrHeader.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ defineEmits<{
250250
:hidemodal="hideModal"
251251
/>
252252
</div>
253+
<!-- @slot Slot par défaut pour le contenu du fieldset (sera dans `<div class="fr-header__body-row">`) -->
253254
<slot />
254255
</div>
255256
</div>

src/components/DsfrHeader/DsfrHeaderMenuLink.vue

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,30 +47,40 @@ const actualTo = computed(() => {
4747
const linkData = computed(() => {
4848
return actualTo.value ? { to: actualTo.value } : { href: actualHref.value }
4949
})
50+
const dsfrIcon = computed(() => typeof props.icon === 'string' && props.icon.startsWith('fr-icon-'))
51+
const defaultScale = 1
52+
const iconProps = computed(() => typeof props.icon === 'string'
53+
? { name: props.icon, scale: defaultScale, ...(props.iconAttrs ?? {}) }
54+
: { scale: defaultScale, ...(props.icon ?? {}), ...(props.iconAttrs ?? {}) },
55+
)
5056
</script>
5157

5258
<template>
5359
<component
5460
:is="is"
5561
class="fr-btn"
62+
:class="{
63+
'fr-btn--icon-right': dsfrIcon && iconRight,
64+
'fr-btn--icon-left': dsfrIcon && !iconRight,
65+
[String(icon)]: dsfrIcon,
66+
}"
5667
v-bind="linkData"
5768
:target="target"
5869
@click.stop="onClick"
5970
>
6071
<template
61-
v-if="(icon || iconAttrs?.name) && !iconRight"
72+
v-if="!dsfrIcon && (icon || iconAttrs?.name) && !iconRight"
6273
>
6374
<VIcon
64-
:name="icon"
6575
class="fr-mr-1w"
66-
v-bind="iconAttrs"
76+
v-bind="iconProps"
6777
/>
6878
</template>
6979

7080
{{ label }}
7181

7282
<template
73-
v-if="(icon || iconAttrs?.name) && iconRight"
83+
v-if="!dsfrIcon && (icon || iconAttrs?.name) && iconRight"
7484
>
7585
<VIcon
7686
:name="icon"

src/components/DsfrInput/DsfrInputGroup.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const messageClass = computed(() => props.errorMessage ? 'fr-error-text' : 'fr-v
3636
}"
3737
>
3838
<slot name="before-input" />
39+
<!-- @slot Slot par défaut pour le contenu du groupe de champ -->
3940
<slot />
4041
<DsfrInput
4142
v-if="!$slots.default"

src/components/DsfrModal/DsfrModal.vue

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ async function close () {
6767
props.origin?.focus()
6868
emit('close')
6969
}
70+
71+
const dsfrIcon = computed(() => typeof props.icon === 'string' && props.icon.startsWith('fr-icon-'))
72+
const defaultScale = 2
73+
const iconProps = computed(() => dsfrIcon.value
74+
? undefined
75+
: typeof props.icon === 'string'
76+
? { name: props.icon, scale: defaultScale }
77+
: { scale: defaultScale, ...(props.icon ?? {}) },
78+
)
7079
</script>
7180

7281
<template>
@@ -113,11 +122,14 @@ async function close () {
113122
class="fr-modal__title"
114123
>
115124
<span
116-
v-if="icon"
125+
v-if="dsfrIcon || iconProps"
126+
:class="{
127+
[String(icon)]: dsfrIcon,
128+
}"
117129
>
118130
<VIcon
119-
:name="icon"
120-
scale="2"
131+
v-if="iconProps"
132+
v-bind="iconProps"
121133
/>
122134
</span>
123135
{{ title }}

src/components/DsfrNavigation/DsfrNavigationMenuLink.vue

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ const props = withDefaults(defineProps<DsfrNavigationMenuLinkProps>(), {
1919
defineEmits<{(event: 'toggle-id', id: string): void}>()
2020
2121
const isExternal = computed(() => typeof props.to === 'string' && props.to.startsWith('http'))
22+
const dsfrIcon = computed(() => props.icon && typeof props.icon === 'string' && props.icon.startsWith('fr-icon-'))
23+
const defaultScale = 2
24+
const iconProps = computed(() => (dsfrIcon.value || !props.icon)
25+
? undefined
26+
: (typeof props.icon === 'string')
27+
? { scale: defaultScale, name: props.icon }
28+
: { scale: defaultScale, ...(props.icon || {}) },
29+
)
2230
</script>
2331

2432
<template>
@@ -36,11 +44,14 @@ const isExternal = computed(() => typeof props.to === 'string' && props.to.start
3644
class="fr-nav__link"
3745
data-testid="nav-router-link"
3846
:to="to"
47+
:class="{
48+
[String(icon)]: dsfrIcon,
49+
}"
3950
@click="$emit('toggle-id', id)"
4051
>
4152
<VIcon
42-
v-if="icon"
43-
:name="icon"
53+
v-if="iconProps"
54+
v-bind="iconProps"
4455
/>
4556
{{ text }}
4657
</RouterLink>

0 commit comments

Comments
 (0)