Files
malio-layer-ui/app/components/malio/date/internal/MonthGrid.vue
tristan c96cb5112d 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>
2026-05-20 11:13:08 +02:00

104 lines
3.3 KiB
Vue

<template>
<div data-test="month-grid">
<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-[14px] font-medium opacity-[60%]"
>
{{ d }}
</div>
<template
v-for="(week, wIndex) in weeks"
:key="week.days[0].isoDate"
>
<div
data-test="week-number"
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>
<button
v-for="cell in week.days"
:key="cell.isoDate"
type="button"
data-test="day"
:data-iso="cell.isoDate"
:disabled="!inRange(cell.isoDate)"
:aria-label="ariaLabel(cell)"
:aria-disabled="!inRange(cell.isoDate)"
class="flex h-[45px] w-full items-center justify-center"
:class="inRange(cell.isoDate) ? 'cursor-pointer' : 'cursor-not-allowed'"
@click="onSelect(cell.isoDate)"
>
<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>
</div>
</template>
<script setup lang="ts">
import {toRef} from 'vue'
import {useMonthMatrix, type DayCell} from '../composables/useMonthMatrix'
import {isDateInRange} from '../composables/dateFormat'
defineOptions({name: 'MalioDateMonthGrid'})
const props = withDefaults(
defineProps<{
month: number
year: number
selectedDate?: string | null
min?: string
max?: string
}>(),
{selectedDate: null, min: undefined, max: undefined},
)
const emit = defineEmits<{(e: 'select', iso: string): void}>()
const dayLabels = ['Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim']
const monthsLong = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin',
'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre']
const {weeks} = useMonthMatrix(toRef(props, 'month'), toRef(props, 'year'))
const inRange = (iso: string) => isDateInRange(iso, props.min, props.max)
const ariaLabel = (cell: DayCell) => {
const [, m, d] = cell.isoDate.split('-')
return `${Number(d)} ${monthsLong[Number(m) - 1]} ${cell.isoDate.slice(0, 4)}`
}
const cellClass = (cell: DayCell) => {
const selected = props.selectedDate === cell.isoDate
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('opacity-[60%]')
return parts.join(' ')
}
const onSelect = (iso: string) => {
if (!inRange(iso)) return
emit('select', iso)
}
</script>