[#MUI-15] Création d'un composant drawer (#21)
| Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [ ] Pas de régression - [ ] TU/TI/TF rédigée - [ ] TU/TI/TF OK - [ ] CHANGELOG modifié Reviewed-on: #21 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #21.
This commit is contained in:
49
.playground/pages/composant/drawer/drawer.vue
Normal file
49
.playground/pages/composant/drawer/drawer.vue
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const drawerDefault = ref(false)
|
||||||
|
const drawerNoClose = ref(false)
|
||||||
|
const drawerCustomWidth = ref(false)
|
||||||
|
const drawerWithForm = ref(false)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="grid grid-cols-1 items-start gap-6 md:grid-cols-2">
|
||||||
|
<div class="rounded-lg border p-6">
|
||||||
|
<h2 class="mb-6 text-xl font-bold">Drawer simple</h2>
|
||||||
|
<MalioButton label="Ouvrir le drawer" @click="drawerDefault = true" />
|
||||||
|
<MalioDrawer v-model="drawerDefault" title="Titre du drawer">
|
||||||
|
<p class="text-m-text">Contenu du drawer. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
|
||||||
|
</MalioDrawer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rounded-lg border p-6">
|
||||||
|
<h2 class="mb-6 text-xl font-bold">Sans bouton fermer</h2>
|
||||||
|
<MalioButton label="Ouvrir le drawer" variant="secondary" @click="drawerNoClose = true" />
|
||||||
|
<MalioDrawer v-model="drawerNoClose" title="Sans croix" :show-close="false">
|
||||||
|
<p class="text-m-text">Ce drawer n'a pas de bouton fermer. Cliquez sur le backdrop pour fermer.</p>
|
||||||
|
</MalioDrawer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rounded-lg border p-6">
|
||||||
|
<h2 class="mb-6 text-xl font-bold">Largeur personnalisée</h2>
|
||||||
|
<MalioButton label="Ouvrir le drawer large" variant="tertiary" @click="drawerCustomWidth = true" />
|
||||||
|
<MalioDrawer v-model="drawerCustomWidth" title="Drawer large" drawer-class="max-w-2xl">
|
||||||
|
<p class="text-m-text">Ce drawer utilise une largeur personnalisée via drawerClass.</p>
|
||||||
|
</MalioDrawer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rounded-lg border p-6">
|
||||||
|
<h2 class="mb-6 text-xl font-bold">Avec formulaire</h2>
|
||||||
|
<MalioButton label="Ouvrir le formulaire" variant="danger" @click="drawerWithForm = true" />
|
||||||
|
<MalioDrawer v-model="drawerWithForm" title="Formulaire">
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<MalioInputText label="Nom" />
|
||||||
|
<MalioInputText label="Prénom" />
|
||||||
|
<MalioInputText label="Email" />
|
||||||
|
<MalioButton label="Enregistrer" button-class="w-full" @click="drawerWithForm = false" />
|
||||||
|
</div>
|
||||||
|
</MalioDrawer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -23,6 +23,7 @@ Liste des évolutions de la librairie Malio layer UI
|
|||||||
* [#MUI-23] Revoir la config couleur tailwind
|
* [#MUI-23] Revoir la config couleur tailwind
|
||||||
* [#MUI-10] Création d'un composant bouton
|
* [#MUI-10] Création d'un composant bouton
|
||||||
* [#MUI-2] Faire un MCP pour la librairie de composant
|
* [#MUI-2] Faire un MCP pour la librairie de composant
|
||||||
|
* [#MUI-15] Création d'un composant drawer
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@@ -355,3 +355,32 @@ Barre latérale de navigation rétractable.
|
|||||||
<template #logo-collapsed><img src="/logo-small.png" /></template>
|
<template #logo-collapsed><img src="/logo-small.png" /></template>
|
||||||
</MalioSidebar>
|
</MalioSidebar>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MalioDrawer
|
||||||
|
|
||||||
|
Panneau latéral (drawer) qui s'ouvre depuis la droite avec backdrop semi-transparent.
|
||||||
|
|
||||||
|
| Prop | Type | Défaut | Description |
|
||||||
|
|------|------|--------|-------------|
|
||||||
|
| `id` | `string` | auto | Identifiant HTML |
|
||||||
|
| `modelValue` | `boolean` | `undefined` | État ouvert/fermé (v-model) |
|
||||||
|
| `title` | `string` | `''` | Titre affiché dans le header |
|
||||||
|
| `showClose` | `boolean` | `true` | Afficher le bouton de fermeture (croix) |
|
||||||
|
| `drawerClass` | `string` | `''` | Classes CSS panneau (twMerge) |
|
||||||
|
|
||||||
|
**Events :** `update:modelValue(value: boolean)`
|
||||||
|
**Slots :** `default` (contenu du drawer)
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<MalioDrawer v-model="isOpen" title="Détails">
|
||||||
|
<p>Contenu du drawer</p>
|
||||||
|
</MalioDrawer>
|
||||||
|
<MalioDrawer v-model="isOpen" title="Sans croix" :show-close="false">
|
||||||
|
<p>Fermeture uniquement via backdrop</p>
|
||||||
|
</MalioDrawer>
|
||||||
|
<MalioDrawer v-model="isOpen" title="Large" drawer-class="max-w-2xl">
|
||||||
|
<p>Drawer plus large</p>
|
||||||
|
</MalioDrawer>
|
||||||
|
```
|
||||||
|
|||||||
122
app/components/malio/drawer/Drawer.test.ts
Normal file
122
app/components/malio/drawer/Drawer.test.ts
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import type { DefineComponent } from 'vue'
|
||||||
|
import { Icon as IconifyIcon } from '@iconify/vue'
|
||||||
|
import Drawer from './Drawer.vue'
|
||||||
|
|
||||||
|
type DrawerProps = {
|
||||||
|
modelValue?: boolean
|
||||||
|
title?: string
|
||||||
|
showClose?: boolean
|
||||||
|
id?: string
|
||||||
|
drawerClass?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const DrawerForTest = Drawer as DefineComponent<DrawerProps>
|
||||||
|
|
||||||
|
function mountComponent(props: DrawerProps = {}, slots?: Record<string, string>) {
|
||||||
|
return mount(DrawerForTest, {
|
||||||
|
props,
|
||||||
|
slots,
|
||||||
|
global: {
|
||||||
|
stubs: {
|
||||||
|
Teleport: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('MalioDrawer', () => {
|
||||||
|
it('does not render when modelValue is false', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: false })
|
||||||
|
expect(wrapper.find('[data-test="panel"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders when modelValue is true', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true })
|
||||||
|
expect(wrapper.find('[data-test="panel"]').exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders the title', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true, title: 'Mon tiroir' })
|
||||||
|
expect(wrapper.find('h2').text()).toBe('Mon tiroir')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders slot content', () => {
|
||||||
|
const wrapper = mountComponent(
|
||||||
|
{ modelValue: true },
|
||||||
|
{ default: '<p data-test="content">Contenu du drawer</p>' },
|
||||||
|
)
|
||||||
|
expect(wrapper.find('[data-test="content"]').text()).toBe('Contenu du drawer')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits update:modelValue false on backdrop click', async () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true })
|
||||||
|
await wrapper.find('[data-test="backdrop"]').trigger('click')
|
||||||
|
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([false])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits update:modelValue false on close button click', async () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true })
|
||||||
|
await wrapper.find('[data-test="close-button"]').trigger('click')
|
||||||
|
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([false])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows close button by default', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true })
|
||||||
|
expect(wrapper.find('[data-test="close-button"]').exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('hides close button when showClose is false', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true, showClose: false })
|
||||||
|
expect(wrapper.find('[data-test="close-button"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('close button renders mdi:close icon', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true })
|
||||||
|
const icon = wrapper.findComponent(IconifyIcon)
|
||||||
|
expect(icon.props('icon')).toBe('mdi:close')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('uses custom id when provided', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true, id: 'my-drawer' })
|
||||||
|
expect(wrapper.find('.fixed').attributes('id')).toBe('my-drawer')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates an id when not provided', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true })
|
||||||
|
const id = wrapper.find('.fixed').attributes('id')
|
||||||
|
expect(id).toMatch(/^malio-drawer-/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('has role="dialog" and aria-modal on panel', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true })
|
||||||
|
const panel = wrapper.find('[data-test="panel"]')
|
||||||
|
expect(panel.attributes('role')).toBe('dialog')
|
||||||
|
expect(panel.attributes('aria-modal')).toBe('true')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('aria-labelledby links to title id', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true, id: 'test-drawer' })
|
||||||
|
const panel = wrapper.find('[data-test="panel"]')
|
||||||
|
expect(panel.attributes('aria-labelledby')).toBe('test-drawer-title')
|
||||||
|
expect(wrapper.find('h2').attributes('id')).toBe('test-drawer-title')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('applies drawerClass to the panel', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true, drawerClass: 'max-w-lg' })
|
||||||
|
const panel = wrapper.find('[data-test="panel"]')
|
||||||
|
expect(panel.classes()).toContain('max-w-lg')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('works in uncontrolled mode', () => {
|
||||||
|
const wrapper = mountComponent()
|
||||||
|
// Without modelValue, defaults to closed
|
||||||
|
expect(wrapper.find('[data-test="panel"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('close button has aria-label "Fermer"', () => {
|
||||||
|
const wrapper = mountComponent({ modelValue: true })
|
||||||
|
expect(wrapper.find('[data-test="close-button"]').attributes('aria-label')).toBe('Fermer')
|
||||||
|
})
|
||||||
|
})
|
||||||
135
app/components/malio/drawer/Drawer.vue
Normal file
135
app/components/malio/drawer/Drawer.vue
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
<template>
|
||||||
|
<Teleport to="body">
|
||||||
|
<div
|
||||||
|
v-if="isOpen"
|
||||||
|
:id="componentId"
|
||||||
|
class="fixed inset-0 z-50"
|
||||||
|
v-bind="attrs"
|
||||||
|
>
|
||||||
|
<Transition name="drawer-backdrop">
|
||||||
|
<div
|
||||||
|
v-if="isOpen"
|
||||||
|
class="absolute inset-0 bg-black/40"
|
||||||
|
data-test="backdrop"
|
||||||
|
@click="close"
|
||||||
|
/>
|
||||||
|
</Transition>
|
||||||
|
|
||||||
|
<Transition name="drawer-panel">
|
||||||
|
<div
|
||||||
|
v-if="isOpen"
|
||||||
|
:class="twMerge(
|
||||||
|
'absolute right-0 top-0 h-full w-full max-w-md bg-white shadow-xl',
|
||||||
|
drawerClass,
|
||||||
|
)"
|
||||||
|
role="dialog"
|
||||||
|
:aria-modal="true"
|
||||||
|
:aria-labelledby="titleId"
|
||||||
|
data-test="panel"
|
||||||
|
>
|
||||||
|
<div class="flex items-center justify-between px-5 pb-8 pt-8">
|
||||||
|
<h2
|
||||||
|
:id="titleId"
|
||||||
|
class="text-[32px] font-semibold text-m-primary"
|
||||||
|
>
|
||||||
|
{{ title }}
|
||||||
|
</h2>
|
||||||
|
<button
|
||||||
|
v-if="showClose"
|
||||||
|
type="button"
|
||||||
|
aria-label="Fermer"
|
||||||
|
class="flex h-8 w-8 cursor-pointer items-center justify-center rounded-full transition-colors hover:bg-m-surface"
|
||||||
|
data-test="close-button"
|
||||||
|
@click="close"
|
||||||
|
>
|
||||||
|
<IconifyIcon
|
||||||
|
icon="mdi:close"
|
||||||
|
:width="24"
|
||||||
|
:height="24"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="overflow-y-auto px-5"
|
||||||
|
style="max-height: calc(100% - 96px)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, useAttrs, useId } from 'vue'
|
||||||
|
import { Icon as IconifyIcon } from '@iconify/vue'
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
|
defineOptions({ name: 'MalioDrawer', inheritAttrs: false })
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
id?: string
|
||||||
|
modelValue?: boolean
|
||||||
|
title?: string
|
||||||
|
showClose?: boolean
|
||||||
|
drawerClass?: string
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
id: '',
|
||||||
|
modelValue: undefined,
|
||||||
|
title: '',
|
||||||
|
showClose: true,
|
||||||
|
drawerClass: '',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:modelValue', value: boolean): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const attrs = useAttrs()
|
||||||
|
const generatedId = useId()
|
||||||
|
|
||||||
|
const componentId = computed(() => props.id || `malio-drawer-${generatedId}`)
|
||||||
|
const titleId = computed(() => `${componentId.value}-title`)
|
||||||
|
|
||||||
|
const isControlled = computed(() => props.modelValue !== undefined)
|
||||||
|
const localValue = ref(false)
|
||||||
|
|
||||||
|
const isOpen = computed(() =>
|
||||||
|
isControlled.value ? props.modelValue! : localValue.value,
|
||||||
|
)
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
if (!isControlled.value) {
|
||||||
|
localValue.value = false
|
||||||
|
}
|
||||||
|
emit('update:modelValue', false)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.drawer-backdrop-enter-active,
|
||||||
|
.drawer-backdrop-leave-active {
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-backdrop-enter-from,
|
||||||
|
.drawer-backdrop-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-panel-enter-active,
|
||||||
|
.drawer-panel-leave-active {
|
||||||
|
transition: transform 0.2s ease, opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-panel-enter-from,
|
||||||
|
.drawer-panel-leave-to {
|
||||||
|
transform: translateX(100%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
123
app/story/drawer/drawer.story.vue
Normal file
123
app/story/drawer/drawer.story.vue
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
<template>
|
||||||
|
<Story title="Overlay/Drawer">
|
||||||
|
<Variant title="Simple">
|
||||||
|
<div class="p-4">
|
||||||
|
<button
|
||||||
|
class="rounded bg-m-btn-primary px-4 py-2 text-white"
|
||||||
|
@click="showSimple = true"
|
||||||
|
>
|
||||||
|
Ouvrir le drawer
|
||||||
|
</button>
|
||||||
|
<MalioDrawer v-model="showSimple" title="Détails">
|
||||||
|
<p>Contenu simple du drawer.</p>
|
||||||
|
</MalioDrawer>
|
||||||
|
</div>
|
||||||
|
</Variant>
|
||||||
|
|
||||||
|
<Variant title="Avec formulaire">
|
||||||
|
<div class="p-4">
|
||||||
|
<button
|
||||||
|
class="rounded bg-m-btn-primary px-4 py-2 text-white"
|
||||||
|
@click="showForm = true"
|
||||||
|
>
|
||||||
|
Ouvrir le formulaire
|
||||||
|
</button>
|
||||||
|
<MalioDrawer v-model="showForm" title="Nouveau contact">
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<MalioInputText v-model="formNom" label="Nom" />
|
||||||
|
<MalioInputText v-model="formPrenom" label="Prénom" />
|
||||||
|
<MalioButton label="Enregistrer" button-class="w-full" @click="showForm = false" />
|
||||||
|
</div>
|
||||||
|
</MalioDrawer>
|
||||||
|
</div>
|
||||||
|
</Variant>
|
||||||
|
|
||||||
|
<Variant title="Sans bouton fermer">
|
||||||
|
<div class="p-4">
|
||||||
|
<button
|
||||||
|
class="rounded bg-m-btn-primary px-4 py-2 text-white"
|
||||||
|
@click="showNoClose = true"
|
||||||
|
>
|
||||||
|
Ouvrir (sans croix)
|
||||||
|
</button>
|
||||||
|
<MalioDrawer v-model="showNoClose" title="Information" :show-close="false">
|
||||||
|
<p>Ce drawer n'a pas de bouton fermer. Cliquez sur le backdrop pour fermer.</p>
|
||||||
|
</MalioDrawer>
|
||||||
|
</div>
|
||||||
|
</Variant>
|
||||||
|
|
||||||
|
<Variant title="Largeur personnalisée">
|
||||||
|
<div class="p-4">
|
||||||
|
<button
|
||||||
|
class="rounded bg-m-btn-primary px-4 py-2 text-white"
|
||||||
|
@click="showWide = true"
|
||||||
|
>
|
||||||
|
Ouvrir (large)
|
||||||
|
</button>
|
||||||
|
<MalioDrawer v-model="showWide" title="Drawer large" drawer-class="max-w-2xl">
|
||||||
|
<p>Ce drawer utilise une largeur personnalisée via la prop drawerClass.</p>
|
||||||
|
</MalioDrawer>
|
||||||
|
</div>
|
||||||
|
</Variant>
|
||||||
|
</Story>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<docs lang="md">
|
||||||
|
# MalioDrawer
|
||||||
|
|
||||||
|
Panneau latéral (drawer) qui s'ouvre depuis la droite avec un fond semi-transparent.
|
||||||
|
|
||||||
|
## Props détaillées
|
||||||
|
|
||||||
|
| Prop | Type | Défaut | Description |
|
||||||
|
|------|------|--------|-------------|
|
||||||
|
| `id` | `string` | auto-généré | Identifiant HTML du drawer |
|
||||||
|
| `modelValue` | `boolean` | `undefined` | État ouvert/fermé (v-model) |
|
||||||
|
| `title` | `string` | `''` | Titre affiché dans le header |
|
||||||
|
| `showClose` | `boolean` | `true` | Afficher le bouton de fermeture (croix) |
|
||||||
|
| `drawerClass` | `string` | `''` | Classes CSS additionnelles sur le panneau (fusionnées via `twMerge`) |
|
||||||
|
|
||||||
|
## Comportement
|
||||||
|
|
||||||
|
- Le drawer s'ouvre en glissant depuis la droite avec une transition
|
||||||
|
- Un backdrop semi-transparent couvre le reste de la page
|
||||||
|
- Clic sur le backdrop ferme le drawer
|
||||||
|
- Bouton de fermeture (croix) en haut à droite, masquable via `showClose`
|
||||||
|
- Contenu scrollable si plus haut que la fenêtre
|
||||||
|
- Teleport vers `<body>` pour éviter les problèmes de z-index
|
||||||
|
|
||||||
|
## Accessibilité
|
||||||
|
|
||||||
|
- `role="dialog"` et `aria-modal="true"` sur le panneau
|
||||||
|
- `aria-labelledby` lié au titre
|
||||||
|
- Bouton fermer avec `aria-label="Fermer"`
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
| Event | Payload | Description |
|
||||||
|
|-------|---------|-------------|
|
||||||
|
| `update:modelValue` | `boolean` | Émis à la fermeture (backdrop ou bouton) |
|
||||||
|
|
||||||
|
## Slots
|
||||||
|
|
||||||
|
| Slot | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `default` | Contenu du drawer |
|
||||||
|
</docs>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import MalioDrawer from '../../components/malio/drawer/Drawer.vue'
|
||||||
|
import MalioInputText from '../../components/malio/input/InputText.vue'
|
||||||
|
import MalioButton from '../../components/malio/button/Button.vue'
|
||||||
|
|
||||||
|
defineOptions({ name: 'DrawerStory' })
|
||||||
|
|
||||||
|
const showSimple = ref(false)
|
||||||
|
const showForm = ref(false)
|
||||||
|
const showNoClose = ref(false)
|
||||||
|
const showWide = ref(false)
|
||||||
|
|
||||||
|
const formNom = ref('Dupont')
|
||||||
|
const formPrenom = ref('Jean')
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user