feat(date) : anneau focus clavier et ouverture clavier sur CalendarField
Couvre toute la famille date (Date, DateRange, DateTime, DateWeek) : - Anneau de focus clavier (clavier-only) ; ouvert, l'anneau entoure champ + calendrier d'un seul tenant (combo) - Entrée / Espace ouvrent/ferment le calendrier (mode non éditable), Échap ferme ; mode éditable inchangé - Anneau sur la croix d'effacement Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,10 +23,10 @@
|
||||
placeholder="_"
|
||||
type="text"
|
||||
@click="onFieldClick"
|
||||
@focus="onFocus"
|
||||
@focus="onFocus(); onKbdFocus()"
|
||||
@input="onInput"
|
||||
@blur="onBlur"
|
||||
@keydown.enter.prevent="onEnter"
|
||||
@blur="onBlur(); onKbdBlur()"
|
||||
@keydown="onKeydown"
|
||||
>
|
||||
|
||||
<label
|
||||
@@ -42,7 +42,7 @@
|
||||
v-if="showClear"
|
||||
type="button"
|
||||
data-test="clear"
|
||||
class="text-m-muted hover:text-m-primary"
|
||||
class="m-focus-ring rounded-malio text-m-muted hover:text-m-primary"
|
||||
aria-label="Effacer la date"
|
||||
@click.stop="emit('clear')"
|
||||
>
|
||||
@@ -66,6 +66,7 @@
|
||||
data-test="popover"
|
||||
role="dialog"
|
||||
class="absolute left-0 right-0 top-full z-20 box-border w-full rounded-b-md bg-white p-[10px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)]"
|
||||
:class="keyboardFocused ? 'm-combo-ring-bottom' : ''"
|
||||
>
|
||||
<CalendarHeader
|
||||
:view-mode="viewMode"
|
||||
@@ -114,9 +115,12 @@ import CalendarHeader from './CalendarHeader.vue'
|
||||
import MonthPicker from './MonthPicker.vue'
|
||||
import {useCalendarPopover} from '../composables/useCalendarPopover'
|
||||
import {useCalendarView} from '../composables/useCalendarView'
|
||||
import {useKbdFocusRing} from '../../shared/useKbdFocusRing'
|
||||
|
||||
defineOptions({name: 'MalioCalendarField', inheritAttrs: false})
|
||||
|
||||
const {keyboardFocused, onFocus: onKbdFocus, onBlur: onKbdBlur} = useKbdFocusRing()
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
displayValue: string
|
||||
@@ -236,6 +240,33 @@ const onEnter = () => {
|
||||
closePopover()
|
||||
}
|
||||
|
||||
const onKeydown = (e: KeyboardEvent) => {
|
||||
if (props.disabled || props.readonly) return
|
||||
|
||||
if (e.key === 'Escape') {
|
||||
if (isOpen.value) {
|
||||
e.preventDefault()
|
||||
closePopover()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (props.editable) {
|
||||
// En mode éditable, Entrée valide la saisie (Espace = caractère normal)
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault()
|
||||
onEnter()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Mode non éditable : Entrée / Espace ouvre ou ferme le calendrier
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault()
|
||||
onFieldClick()
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => props.syncTo, (value) => {
|
||||
if (isOpen.value) syncToIso(value)
|
||||
})
|
||||
@@ -262,6 +293,7 @@ const mergedInputClass = computed(() =>
|
||||
? 'border-m-success'
|
||||
: isReadonly.value ? '' : 'focus:border-m-primary',
|
||||
(!isReadonly.value && isOpen.value) ? 'border-m-primary !py-[9px] !rounded-b-none' : '',
|
||||
keyboardFocused.value ? (isOpen.value ? 'm-combo-ring-top' : 'm-focus-ring-kbd') : '',
|
||||
props.inputClass,
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user