feat(ui) : état readonly visuel sur les inputs floating-label
Applique le traitement readonly canonique (isReadonly, shouldFloatLabel, mergedInputClass sans grow-height, bordure noire fixe, sans focus:border-m-primary, mergedLabelClass sans peer-focus, iconStateClass sans isFocused) sur les 6 composants InputText, InputEmail, InputAmount, InputAutocomplete, InputPassword et InputTextArea. L'œil de InputPassword reste cliquable en readonly. Tests TDD ajoutés (3 cas par fichier). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -249,7 +249,12 @@ const hasSelection = computed(() =>
|
||||
const hasError = computed(() => !!props.error)
|
||||
const hasSuccess = computed(() => !!props.success && !hasError.value)
|
||||
const isFilled = computed(() => inputValue.value.trim().length > 0 || hasSelection.value)
|
||||
const shouldFloatLabel = computed(() => isFocused.value || inputValue.value.length > 0)
|
||||
const isReadonly = computed(() => props.readonly && !props.disabled)
|
||||
const shouldFloatLabel = computed(() =>
|
||||
isReadonly.value
|
||||
? isFilled.value
|
||||
: isFocused.value || inputValue.value.length > 0,
|
||||
)
|
||||
|
||||
const showMinSearch = computed(() =>
|
||||
props.minSearchLength > 0 && inputValue.value.length < props.minSearchLength,
|
||||
@@ -311,8 +316,11 @@ const labelPositionClass = computed(() =>
|
||||
|
||||
const mergedInputClass = computed(() =>
|
||||
twMerge(
|
||||
'floating-input grow-height peer min-h-[40px] w-full border bg-white pl-3 pr-3 py-1 outline-none placeholder:text-transparent text-lg rounded-md',
|
||||
isFilled.value ? 'border-black' : 'border-m-muted',
|
||||
'floating-input peer min-h-[40px] w-full border bg-white pl-3 pr-3 py-1 outline-none placeholder:text-transparent text-lg rounded-md',
|
||||
isReadonly.value ? '' : 'grow-height',
|
||||
isReadonly.value
|
||||
? 'border-black'
|
||||
: isFilled.value ? 'border-black' : 'border-m-muted',
|
||||
props.disabled
|
||||
? 'cursor-not-allowed text-black/60 [&:not(:placeholder-shown)]:border-m-muted border-m-muted'
|
||||
: 'cursor-text',
|
||||
@@ -320,7 +328,8 @@ const mergedInputClass = computed(() =>
|
||||
? 'border-m-danger focus:border-m-danger [&:not(:placeholder-shown)]:border-m-danger'
|
||||
: hasSuccess.value
|
||||
? 'border-m-success focus:border-m-success [&:not(:placeholder-shown)]:border-m-success'
|
||||
: 'focus:border-m-primary',
|
||||
: isReadonly.value ? '' : 'focus:border-m-primary',
|
||||
isReadonly.value ? 'cursor-default' : '',
|
||||
isOpen.value ? '!rounded-b-none !border-b-transparent' : '',
|
||||
props.inputClass,
|
||||
iconInputPaddingClass.value,
|
||||
@@ -338,7 +347,9 @@ const mergedLabelClass = computed(() =>
|
||||
? 'text-m-success'
|
||||
: props.disabled
|
||||
? 'text-m-muted'
|
||||
: 'peer-placeholder-shown:text-m-muted peer-[&:not(:placeholder-shown):not(:focus)]:text-black peer-focus:text-m-primary',
|
||||
: isReadonly.value
|
||||
? isFilled.value ? 'text-black' : 'text-m-muted'
|
||||
: 'peer-placeholder-shown:text-m-muted peer-[&:not(:placeholder-shown):not(:focus)]:text-black peer-focus:text-m-primary',
|
||||
props.labelClass,
|
||||
),
|
||||
)
|
||||
@@ -347,6 +358,7 @@ const iconStateClass = computed(() => {
|
||||
if (hasError.value) return 'text-m-danger'
|
||||
if (hasSuccess.value) return 'text-m-success'
|
||||
if (props.disabled) return props.iconColor
|
||||
if (isReadonly.value) return isFilled.value ? 'text-black' : 'text-m-muted'
|
||||
if (isFocused.value) return 'text-m-primary'
|
||||
if (isFilled.value) return 'text-black'
|
||||
return props.iconColor
|
||||
@@ -355,6 +367,7 @@ const iconStateClass = computed(() => {
|
||||
const chevronColorClass = computed(() => {
|
||||
if (hasError.value) return 'text-m-danger'
|
||||
if (hasSuccess.value) return 'text-m-success'
|
||||
if (isReadonly.value) return isFilled.value ? 'text-black' : 'text-m-muted'
|
||||
if (isOpen.value) return 'text-m-primary'
|
||||
if (isFilled.value) return 'text-black'
|
||||
return 'text-m-muted'
|
||||
|
||||
Reference in New Issue
Block a user