feat(ui) : prop reserveMessageSpace (défaut true) sur Select/SelectCheckbox/Checkbox/date/time

Ajoute reserveMessageSpace (défaut true) pour permettre de ne pas réserver
la ligne de message d'aide quand aucun message n'est présent. Comportement
inchangé par défaut. La famille date hérite via $attrs → CalendarField.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 16:53:22 +02:00
parent cda0f994ca
commit 1b5a4c9920
12 changed files with 152 additions and 6 deletions
+20
View File
@@ -17,6 +17,7 @@ type TimeProps = {
hint?: string
error?: string
success?: string
reserveMessageSpace?: boolean
}
const TimeForTest = Time as DefineComponent<TimeProps>
@@ -86,4 +87,23 @@ describe('MalioTime', () => {
const wrapper = mountTime({label: 'Champ'})
expect(wrapper.find('[data-test="required-mark"]').exists()).toBe(false)
})
it('réserve lespace message par défaut même sans message', () => {
const wrapper = mountTime({label: 'Champ'})
const msg = wrapper.find('[id$="-describedby"]')
expect(msg.exists()).toBe(true)
expect(msg.classes()).toContain('min-h-[1rem]')
})
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
const wrapper = mountTime({label: 'Champ', reserveMessageSpace: false})
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
})
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
const wrapper = mountTime({label: 'Champ', reserveMessageSpace: false, error: 'Erreur'})
const msg = wrapper.find('[id$="-describedby"]')
expect(msg.exists()).toBe(true)
expect(msg.classes()).not.toContain('min-h-[1rem]')
})
})
+5 -1
View File
@@ -58,6 +58,7 @@
</div>
<p
v-if="reserveMessageSpace || hint || error || success"
:id="`${inputId}-describedby`"
:class="[
hasError
@@ -65,7 +66,8 @@
: hasSuccess
? 'text-m-success'
: 'text-m-muted',
'mt-1 ml-[2px] text-xs min-h-[1rem]',
'mt-1 ml-[2px] text-xs',
reserveMessageSpace ? 'min-h-[1rem]' : '',
]"
>
{{ error || success || hint }}
@@ -95,6 +97,7 @@ const props = withDefaults(
hint?: string
error?: string
success?: string
reserveMessageSpace?: boolean
}>(),
{
id: '',
@@ -110,6 +113,7 @@ const props = withDefaults(
hint: '',
error: '',
success: '',
reserveMessageSpace: true,
},
)
@@ -19,6 +19,7 @@ type TimePickerProps = {
inputClass?: string
labelClass?: string
groupClass?: string
reserveMessageSpace?: boolean
}
const TimePickerForTest = TimePicker as DefineComponent<TimePickerProps>
@@ -120,4 +121,23 @@ describe('MalioTimePicker', () => {
expect(label.classes()).toContain('text-black')
expect(icon.classes()).toContain('text-black')
})
it('réserve lespace message par défaut même sans message', () => {
const wrapper = mountPicker({label: 'Champ'})
const msg = wrapper.find('[id$="-describedby"]')
expect(msg.exists()).toBe(true)
expect(msg.classes()).toContain('min-h-[1rem]')
})
it('reserveMessageSpace=false sans message : pas de ligne réservée', () => {
const wrapper = mountPicker({label: 'Champ', reserveMessageSpace: false})
expect(wrapper.find('[id$="-describedby"]').exists()).toBe(false)
})
it('reserveMessageSpace=false avec message : ligne rendue sans min-h', () => {
const wrapper = mountPicker({label: 'Champ', reserveMessageSpace: false, error: 'Erreur'})
const msg = wrapper.find('[id$="-describedby"]')
expect(msg.exists()).toBe(true)
expect(msg.classes()).not.toContain('min-h-[1rem]')
})
})
+5 -1
View File
@@ -78,10 +78,12 @@
</div>
<p
v-if="reserveMessageSpace || hint || error || success"
:id="`${inputId}-describedby`"
:class="[
hasError ? 'text-m-danger' : hasSuccess ? 'text-m-success' : 'text-m-muted',
'mt-1 ml-[2px] text-xs min-h-[1rem]',
'mt-1 ml-[2px] text-xs',
reserveMessageSpace ? 'min-h-[1rem]' : '',
]"
>
{{ error || success || hint }}
@@ -116,6 +118,7 @@ const props = withDefaults(
inputClass?: string
labelClass?: string
groupClass?: string
reserveMessageSpace?: boolean
}>(),
{
id: '',
@@ -134,6 +137,7 @@ const props = withDefaults(
inputClass: '',
labelClass: '',
groupClass: '',
reserveMessageSpace: true,
},
)