feat : ajustements visuels du datepicker selon maquette (#MUI-33)

- nouveau token couleur m-primary-light (#EFEFFD)
- popover en largeur du champ, shadow au lieu de bordure, collé au champ
- frames semaine (35x45) et jours alignés à 45px, cercle centré, font-medium
- colonne semaine étroite + marge, numéros en black/60 (semaine courante en black)
- vue mois en toutes lettres sur 3 colonnes, blocs 45px
- label bleu et grossissement calibré du champ à l'ouverture
- header sans hover, chevrons et titre plaqués en haut

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 11:13:08 +02:00
parent 9479c649be
commit c96cb5112d
7 changed files with 107 additions and 79 deletions

View File

@@ -1,44 +1,44 @@
<template>
<div class="flex h-12 items-center justify-between border-b border-m-primary/20 px-2">
<div class="flex h-[36px] justify-between border-b border-black/60 mb-3">
<button
type="button"
data-test="header-prev"
class="rounded p-2 hover:bg-m-primary/10"
class="ml-2 flex self-start rounded"
:aria-label="viewMode === 'days' ? 'Mois précédent' : 'Année précédente'"
@click="emit('prev')"
>
<Icon
icon="mdi:chevron-left"
:width="20"
:height="20"
:width="25"
:height="25"
/>
</button>
<button
type="button"
data-test="header-toggle"
class="flex items-center gap-1 rounded px-2 py-1 text-base font-medium hover:bg-m-primary/10"
class="flex gap-1 rounded text-base font-medium"
@click="emit('toggle-view')"
>
{{ label }}
<span class="mt-[2px]">{{ label }}</span>
<Icon
icon="mdi:chevron-down"
:width="16"
:height="16"
:width="25"
:height="25"
/>
</button>
<button
type="button"
data-test="header-next"
class="rounded p-2 hover:bg-m-primary/10"
class="mr-2 flex self-start rounded"
:aria-label="viewMode === 'days' ? 'Mois suivant' : 'Année suivante'"
@click="emit('next')"
>
<Icon
icon="mdi:chevron-right"
:width="20"
:height="20"
:width="25"
:height="25"
/>
</button>
</div>

View File

@@ -1,24 +1,29 @@
<template>
<div data-test="month-grid">
<div class="grid grid-cols-8">
<div class="flex h-8 items-center justify-center text-xs font-medium uppercase text-m-muted">
Sem
<div class="grid grid-cols-[auto_repeat(7,minmax(0,1fr))]">
<div class="mr-[12px] flex h-8 w-[35px] items-center justify-center text-[14px] font-medium opacity-[60%]">
S
</div>
<div
v-for="d in dayLabels"
:key="d"
class="flex h-8 items-center justify-center text-xs font-medium uppercase text-m-muted"
class="flex h-8 items-center justify-center text-[14px] font-medium opacity-[60%]"
>
{{ d }}
</div>
<template
v-for="week in weeks"
v-for="(week, wIndex) in weeks"
:key="week.days[0].isoDate"
>
<div
data-test="week-number"
class="flex h-10 items-center justify-center bg-m-primary/10 text-sm text-m-primary/70"
class="mr-[12px] flex h-[45px] w-[35px] shrink-0 items-center justify-center bg-m-primary-light p-[10px] text-sm"
:class="[
week.days.some(d => d.isToday) ? 'text-black' : 'text-black/60',
wIndex === 0 ? 'rounded-t-md' : '',
wIndex === weeks.length - 1 ? 'rounded-b-md' : '',
]"
>
{{ week.weekNumber }}
</div>
@@ -31,11 +36,16 @@
:disabled="!inRange(cell.isoDate)"
:aria-label="ariaLabel(cell)"
:aria-disabled="!inRange(cell.isoDate)"
class="flex h-10 w-10 items-center justify-center text-sm transition-colors duration-100"
:class="cellClass(cell)"
class="flex h-[45px] w-full items-center justify-center"
:class="inRange(cell.isoDate) ? 'cursor-pointer' : 'cursor-not-allowed'"
@click="onSelect(cell.isoDate)"
>
{{ cell.day }}
<span
class="flex h-10 w-10 items-center justify-center rounded-full text-sm font-medium transition-colors duration-100"
:class="cellClass(cell)"
>
{{ cell.day }}
</span>
</button>
</template>
</div>
@@ -77,12 +87,12 @@ const ariaLabel = (cell: DayCell) => {
const cellClass = (cell: DayCell) => {
const selected = props.selectedDate === cell.isoDate
if (!inRange(cell.isoDate)) return 'text-m-muted/30 cursor-not-allowed'
if (selected) return 'bg-m-primary text-white font-medium rounded-full'
const parts = ['cursor-pointer hover:bg-m-primary/10 rounded-full']
if (cell.isToday) parts.push('border border-m-primary text-m-primary font-semibold')
if (!inRange(cell.isoDate)) return 'text-m-muted/30'
if (selected) return 'bg-m-primary text-white'
const parts = ['hover:bg-m-primary/10']
if (cell.isToday) parts.push('border border-m-primary text-m-primary')
else if (cell.isCurrentMonth) parts.push('text-black')
else parts.push('text-m-muted/50')
else parts.push('opacity-[60%]')
return parts.join(' ')
}

View File

@@ -1,21 +1,25 @@
<template>
<div
data-test="month-picker"
class="grid grid-cols-4 gap-2 p-3"
class="grid grid-cols-3 gap-3"
>
<button
v-for="(name, index) in monthsShort"
v-for="(name, index) in months"
:key="name"
type="button"
data-test="month"
:data-month="index"
class="rounded py-3 text-sm transition-colors duration-100"
:class="index === selectedMonth
? 'bg-m-primary text-white'
: 'text-black hover:bg-m-primary/10'"
class="flex h-[45px] w-full items-center justify-center"
@click="emit('select', index)"
>
{{ name }}
<span
class="flex h-[30px] w-full items-center justify-center rounded text-sm transition-colors duration-100"
:class="index === selectedMonth
? 'bg-m-primary text-white'
: 'text-black hover:bg-m-primary/10'"
>
{{ name }}
</span>
</button>
</div>
</template>
@@ -27,6 +31,6 @@ defineProps<{selectedMonth?: number}>()
const emit = defineEmits<{(e: 'select', month: number): void}>()
const monthsShort = ['Janv', 'Févr', 'Mars', 'Avr', 'Mai', 'Juin',
'Juil', 'Août', 'Sept', 'Oct', 'Nov', 'Déc']
const months = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
</script>