Skip to content

Commit 3ac628c

Browse files
authored
Merge pull request #83 from laruiss/feat/dsfr-modal
Feat/dsfr modal
2 parents fa1d52a + 787cab3 commit 3ac628c

File tree

10 files changed

+231
-12
lines changed

10 files changed

+231
-12
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ end_of_line = lf
66
trim_trailing_whitespace = true
77
insert_final_newline = true
88

9-
[*.{js,jsx,ts,tsx,vue}]
9+
[*.{js,jsx,ts,tsx,vue,css}]
1010
indent_style = space
1111
indent_size = 2

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"build": "run-p build:css build:js",
1919
"build:css": "node build-css.mjs",
2020
"build:js": "cross-env NODE_ENV=production rollup --config rollup.config.js",
21-
"serve": "vite preview",
21+
"demo-app": "vite",
2222
"test": "jest",
2323
"format": "npm run lint -- --fix",
2424
"lint": "eslint ./src/**/*.{vue,js,jsx,ts,tsx}",

src/App.vue

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,74 @@
1+
<script setup>
2+
import { ref } from 'vue'
3+
4+
const isModalOpen = ref(false)
5+
const displayAlert = ref(false)
6+
const close = () => {
7+
displayAlert.value = false
8+
setTimeout(
9+
() => { isModalOpen.value = false },
10+
1000,
11+
)
12+
}
13+
14+
const actions = [
15+
{
16+
label: 'Valider',
17+
onClick: () => {
18+
displayAlert.value = true
19+
setTimeout(
20+
close,
21+
2000,
22+
)
23+
},
24+
},
25+
{
26+
label: 'Annuler',
27+
secondary: true,
28+
onClick: () => { isModalOpen.value = false },
29+
},
30+
]
31+
32+
</script>
33+
134
<template>
235
<div>
3-
App
36+
<h1>App</h1>
37+
<DsfrButton
38+
class="m1"
39+
@click="isModalOpen = true"
40+
>
41+
Open modal
42+
</DsfrButton>
43+
<teleport to="body">
44+
<DsfrModal
45+
v-if="isModalOpen"
46+
:opened="isModalOpen"
47+
:actions="actions"
48+
@close="isModalOpen = false"
49+
>
50+
<DsfrAlert
51+
:closed="!displayAlert"
52+
type="success"
53+
sm
54+
description="Opération terminée avec succès"
55+
/>
56+
Ceci est une modale. Elle peut se fermer sans aucun changement au clic sur le bouton "Fermer" ou bien simplement avec la touche <kbd>Échappe</kbd>
57+
</DsfrModal>
58+
</teleport>
459
</div>
560
</template>
661

7-
<script>
8-
export default {
9-
name: 'App',
10-
}
11-
</script>
12-
1362
<style>
1463
#app {
15-
font-family: Avenir, Helvetica, Arial, sans-serif;
1664
-webkit-font-smoothing: antialiased;
1765
-moz-osx-font-smoothing: grayscale;
1866
text-align: center;
1967
color: #2c3e50;
2068
margin-top: 60px;
2169
}
70+
71+
.m1 {
72+
margin: 0.5rem;
73+
}
2274
</style>

src/assets/objects-dsfr.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
@import url(./objects/fieldset.css);
22
@import url(./objects/link.css);
3-
@import url(./objects/modal.css);

src/components/DsfrModal/DsfrModal.spec.js

Whitespace-only changes.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import DsfrModal from './DsfrModal.vue'
2+
import DsfrButton from '../DsfrButton/DsfrButton.vue'
3+
4+
export default {
5+
component: DsfrModal,
6+
title: 'Éléments/Modale - Modal',
7+
}
8+
9+
export const Modal = (args) => ({
10+
components: {
11+
DsfrModal,
12+
DsfrButton,
13+
},
14+
data () {
15+
return {
16+
...args,
17+
actions: args.actions.map(action => ({ ...action, onClick: args.onClick })),
18+
}
19+
},
20+
template: `
21+
<div :data-rf-theme="dark ? 'dark' : ''" style="background-color: var(--w); padding: 1rem;">
22+
<DsfrButton
23+
label="Ouvre la modale"
24+
@click="open()"
25+
/>
26+
<DsfrModal
27+
:opened="opened"
28+
:actions="actions"
29+
@close="onClose"
30+
>
31+
<h1
32+
id="fr-modal-title-modal-1"
33+
class="fr-modal__title"
34+
>
35+
<span class="fr-fi-arrow-right-line fr-fi--lg" />Titre de la modale
36+
</h1>
37+
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas varius tortor nibh, sit amet tempor nibh finibus et. Aenean eu enim justo. Vestibulum aliquam hendrerit molestie. Mauris malesuada nisi sit amet augue accumsan tincidunt. Maecenas tincidunt, velit ac porttitor pulvinar, tortor eros facilisis libero, vitae commodo nunc quam et ligula. Ut nec ipsum sapien. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer id nisi nec nulla luctus lacinia non eu turpis. Etiam in ex imperdiet justo tincidunt egestas. Ut porttitor urna ac augue cursus tincidunt sit amet sed orci.</p>
38+
</DsfrModal>
39+
</div>
40+
`,
41+
methods: {
42+
onClose () {
43+
this.opened = false
44+
},
45+
open () {
46+
this.opened = true
47+
},
48+
},
49+
})
50+
51+
Modal.args = {
52+
dark: false,
53+
opened: false,
54+
actions: [
55+
{
56+
label: 'Valider',
57+
},
58+
{
59+
label: 'Annuler',
60+
secondary: true,
61+
},
62+
],
63+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<script>
2+
import DsfrButtonGroup from '../DsfrButton/DsfrButtonGroup.vue'
3+
4+
export default {
5+
name: 'DsfrModal',
6+
7+
components: {
8+
DsfrButtonGroup,
9+
},
10+
11+
props: {
12+
opened: Boolean,
13+
actions: {
14+
type: Array,
15+
default: () => [],
16+
},
17+
},
18+
19+
emits: [
20+
'close',
21+
],
22+
23+
data () {
24+
return {
25+
closeIfEscape: ($event) => {
26+
if ($event.key === 'Escape') {
27+
this.close()
28+
}
29+
},
30+
}
31+
},
32+
33+
mounted () {
34+
this.startListeningToEscape()
35+
},
36+
37+
beforeUnmount () {
38+
this.startListeningToEscape()
39+
},
40+
41+
methods: {
42+
startListeningToEscape () {
43+
document.addEventListener('keydown', this.closeIfEscape)
44+
},
45+
46+
stopListeningToEscape () {
47+
document.removeEventListener('keydown', this.closeIfEscape)
48+
},
49+
50+
close () {
51+
this.$emit('close')
52+
},
53+
},
54+
}
55+
</script>
56+
57+
<template>
58+
<dialog
59+
id="fr-modal-1"
60+
aria-labelledby="fr-modal-title-modal-1"
61+
role="dialog"
62+
class="fr-modal"
63+
:class="{'fr-modal--opened': opened}"
64+
>
65+
<div class="fr-container fr-container--fluid fr-container-md">
66+
<div class="fr-grid-row fr-grid-row--center">
67+
<div class="fr-col-12 fr-col-md-8 fr-col-lg-6">
68+
<div class="fr-modal__body">
69+
<div class="fr-modal__header">
70+
<button
71+
class="fr-link--close fr-link"
72+
title="Fermer la fenêtre modale"
73+
aria-controls="fr-modal-1"
74+
@click="close"
75+
>
76+
Fermer
77+
</button>
78+
</div>
79+
<div class="fr-modal__content">
80+
<slot />
81+
</div>
82+
<div
83+
v-if="actions && actions.length"
84+
class="fr-modal__footer"
85+
>
86+
<DsfrButtonGroup
87+
align="right"
88+
:buttons="actions"
89+
inline
90+
reverse
91+
/>
92+
</div>
93+
</div>
94+
</div>
95+
</div>
96+
</div>
97+
</dialog>
98+
</template>
99+
100+
<style src="./modal.css" />

src/components/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export { default as DsfrCheckboxSet } from './DsfrCheckbox/DsfrCheckboxSet.vue'
77
export { default as DsfrHeader } from './DsfrHeader/DsfrHeader.vue'
88
export { default as DsfrInput } from './DsfrInput/DsfrInput.vue'
99
export { default as DsfrLogo } from './DsfrLogo/DsfrLogo.vue'
10+
export { default as DsfrModal } from './DsfrModal/DsfrModal.vue'
1011
export { default as DsfrRadioButton } from './DsfrRadioButton/DsfrRadioButton.vue'
1112
export { default as DsfrRadioButtonSet } from './DsfrRadioButton/DsfrRadioButtonSet.vue'
1213
export { default as DsfrSearchBar } from './DsfrSearchBar/DsfrSearchBar.vue'

src/main.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import {
44
RiCheckboxCircleLine,
55
} from 'oh-vue-icons/icons'
66

7+
import './main.css'
8+
import './assets/fonts-dsfr.css'
9+
import VueDsfr from './index.js'
10+
711
import App from './App.vue'
812

913
OhVueIcon.add(
1014
RiCheckboxCircleLine,
1115
)
1216

1317
createApp(App)
14-
.component('v-icon', OhVueIcon)
18+
.use(VueDsfr)
1519
.mount('#app')

0 commit comments

Comments
 (0)