refactor : migrate UI to Malio layer-ui components (MalioButton, MalioDrawer, MalioSelectCheckbox)

- Replace all AppDrawer with MalioDrawer across 10 drawer components
- Replace native <button> with MalioButton/MalioButtonIcon in all pages and components
- Fix TimeTrackingExportDrawer: use MalioSelectCheckbox for multi-select filters
- Add Malio design system colors (m-btn-*, m-disabled, m-surface) to tailwind.config.ts
- Align toggle button heights with MalioButton (h-[40px])

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-03-26 09:33:28 +01:00
parent d7968af525
commit 22373a0b87
53 changed files with 673 additions and 640 deletions

View File

@@ -1,5 +1,5 @@
<template>
<AppDrawer v-model="isOpen" :title="isEditing ? $t('timeEntries.editEntry') : $t('timeEntries.addEntry')">
<MalioDrawer v-model="isOpen" :title="isEditing ? $t('timeEntries.editEntry') : $t('timeEntries.addEntry')">
<form class="space-y-4" @submit.prevent="onSubmit">
<div>
<label class="mb-1 block text-sm font-semibold text-neutral-700">Titre</label>
@@ -97,33 +97,30 @@
</div>
<div class="flex items-center" :class="isEditing ? 'justify-between' : 'justify-end'">
<button
<MalioButton
v-if="isEditing"
type="button"
class="rounded-md bg-red-500 px-4 py-2 text-sm font-semibold text-white hover:bg-red-600 transition"
variant="danger"
label="Supprimer"
button-class="w-auto px-4"
@click="onDelete"
>
Supprimer
</button>
/>
<div class="flex gap-2">
<button
<MalioButton
v-if="isEditing"
type="button"
class="rounded-md bg-blue-500 px-4 py-2 text-sm font-semibold text-white hover:bg-blue-600 transition"
variant="secondary"
label="Dupliquer"
button-class="w-auto px-4"
@click="onDuplicate"
>
Dupliquer
</button>
<button
type="submit"
class="rounded-md bg-primary-500 px-4 py-2 text-sm font-semibold text-white hover:bg-primary-600 transition"
>
Enregistrer
</button>
/>
<MalioButton
label="Enregistrer"
button-class="w-auto px-4"
@click="onSubmit"
/>
</div>
</div>
</form>
</AppDrawer>
</MalioDrawer>
</template>
<script setup lang="ts">

View File

@@ -54,13 +54,14 @@
</div>
<!-- Delete action -->
<button
class="shrink-0 rounded-md p-1.5 text-neutral-300 opacity-0 transition hover:bg-red-50 hover:text-red-500 group-hover:opacity-100"
:title="$t('common.delete')"
<MalioButtonIcon
icon="mdi:delete-outline"
:aria-label="$t('common.delete')"
variant="ghost"
icon-size="18"
button-class="shrink-0 text-neutral-300 opacity-0 hover:bg-red-50 hover:text-red-500 group-hover:opacity-100"
@click.stop="emit('deleteEntry', entry)"
>
<Icon name="mdi:delete-outline" size="18" />
</button>
/>
</div>
</div>
</template>

View File

@@ -53,8 +53,6 @@
:display-tag="true"
:display-select-all="true"
min-width="!w-full"
text-field="text-sm"
text-value="text-sm"
/>
</div>
@@ -66,8 +64,6 @@
:label="$t('timeEntries.exportClient')"
:empty-option-label="$t('timeEntries.exportAllClients')"
min-width="!w-full"
text-field="text-sm"
text-value="text-sm"
/>
</div>
@@ -80,8 +76,6 @@
:display-tag="true"
:display-select-all="true"
min-width="!w-full"
text-field="text-sm"
text-value="text-sm"
/>
</div>
@@ -94,19 +88,17 @@
:display-tag="true"
:display-select-all="true"
min-width="!w-full"
text-field="text-sm"
text-value="text-sm"
/>
</div>
<!-- Export button -->
<button
class="flex w-full items-center justify-center gap-2 rounded-md bg-primary-500 px-4 py-3 text-sm font-semibold text-white hover:bg-primary-600 transition"
<MalioButton
:label="$t('timeEntries.export')"
icon-name="mdi:download"
icon-position="left"
button-class="w-full"
@click="doExport"
>
<Icon name="mdi:download" size="18" />
{{ $t('timeEntries.export') }}
</button>
/>
</div>
</MalioDrawer>
</template>
@@ -148,11 +140,11 @@ const selectedProjectIds = ref<number[]>([])
const selectedTagIds = ref<number[]>([])
const userOptions = computed(() =>
props.users.map(u => ({ label: u.username, value: u.id }))
props.users.map(u => ({ text: u.username, value: u.id }))
)
const clientOptions = computed(() =>
props.clients.map(c => ({ label: c.name, value: c.id }))
props.clients.map(c => ({ text: c.name, value: c.id }))
)
const filteredProjectOptions = computed(() => {
@@ -160,11 +152,11 @@ const filteredProjectOptions = computed(() => {
if (selectedClientId.value) {
list = list.filter(p => p.client?.id === selectedClientId.value)
}
return list.map(p => ({ label: p.name, value: p.id }))
return list.map(p => ({ text: p.name, value: p.id }))
})
const tagOptions = computed(() =>
props.tags.map(t => ({ label: t.label, value: t.id }))
props.tags.map(t => ({ text: t.label, value: t.id }))
)
// Reset project selection when client changes