fix: readonly component style + TabList + required component (#61)
Release / release (push) Successful in 1m24s
Release / release (push) Successful in 1m24s
| Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [ ] Pas de régression - [ ] TU/TI/TF rédigée - [ ] TU/TI/TF OK - [ ] CHANGELOG modifié --------- Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-authored-by: matthieu <matthieu@yuno.malio.fr> Reviewed-on: #61 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #61.
This commit is contained in:
@@ -8,14 +8,14 @@
|
||||
:autocomplete="autocomplete"
|
||||
class="floating-input peer w-full border bg-white pl-3 pr-3 py-1 outline-none placeholder:text-transparent overflow-auto"
|
||||
:class="[
|
||||
isFilled ? 'border-black' : 'border-m-muted',
|
||||
disabled ? 'cursor-not-allowed text-black/60 border-m-muted' : 'cursor-text',
|
||||
isReadonly ? 'border-black' : (isFilled ? 'border-black' : 'border-m-muted'),
|
||||
disabled ? 'cursor-not-allowed text-black/60 border-m-muted' : (isReadonly ? 'cursor-default' : 'cursor-text'),
|
||||
hasError
|
||||
? 'border-m-danger focus:border-m-danger'
|
||||
: hasSuccess
|
||||
? 'border-m-success focus:border-m-success'
|
||||
: 'focus:border-m-primary',
|
||||
isFocused ? 'textarea-scrollbar-primary' : '',
|
||||
: isReadonly ? '' : 'focus:border-m-primary',
|
||||
isReadonly ? '' : (isFocused ? 'textarea-scrollbar-primary' : ''),
|
||||
textInput,
|
||||
showCounterComputed ? 'pb-6' : '',
|
||||
rounded,
|
||||
@@ -47,11 +47,13 @@
|
||||
? 'text-m-success'
|
||||
: disabled
|
||||
? 'text-m-muted'
|
||||
: isFocused ? 'text-m-primary' : shouldFloatLabel ? 'text-black' : 'text-m-muted',
|
||||
: isReadonly
|
||||
? (isFilled ? 'text-black' : 'text-m-muted')
|
||||
: (isFocused ? 'text-m-primary' : shouldFloatLabel ? 'text-black' : 'text-m-muted'),
|
||||
textLabel,
|
||||
]"
|
||||
>
|
||||
{{ label }}
|
||||
{{ label }}<MalioRequiredMark v-if="required" />
|
||||
</label>
|
||||
<span
|
||||
v-if="showCounterComputed"
|
||||
@@ -61,7 +63,10 @@
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mt-1 flex items-center justify-between gap-2 text-xs min-h-[1rem]"
|
||||
v-if="reserveMessageSpace || hint || error || success"
|
||||
data-test="message-line"
|
||||
class="mt-1 flex items-center justify-between gap-2 text-xs"
|
||||
:class="reserveMessageSpace ? 'min-h-[1rem]' : ''"
|
||||
>
|
||||
<p
|
||||
:id="`${inputId}-describedby`"
|
||||
@@ -83,6 +88,7 @@
|
||||
<script setup lang="ts">
|
||||
import {computed, ref, useAttrs, useId} from 'vue'
|
||||
import {twMerge} from 'tailwind-merge'
|
||||
import MalioRequiredMark from '../shared/RequiredMark.vue'
|
||||
|
||||
defineOptions({name: 'MalioInputTextArea', inheritAttrs: false})
|
||||
|
||||
@@ -111,6 +117,7 @@ const props = withDefaults(
|
||||
success?: string
|
||||
rounded?: string
|
||||
groupClass?: string
|
||||
reserveMessageSpace?: boolean
|
||||
|
||||
}>(),
|
||||
{
|
||||
@@ -137,11 +144,14 @@ const props = withDefaults(
|
||||
minResizeHeight: 40,
|
||||
maxResizeHeight: 320,
|
||||
groupClass: '',
|
||||
reserveMessageSpace: true,
|
||||
},
|
||||
)
|
||||
|
||||
const mergedGroupClass = computed(() =>
|
||||
twMerge('flex flex-col w-full', props.groupClass),
|
||||
// pt-1 (4px) aligne le haut de la textarea avec les inputs floating-label,
|
||||
// qui centrent un champ de 40px dans un groupe h-12 (≈ 4px de décalage en haut).
|
||||
twMerge('flex flex-col w-full pt-1', props.groupClass),
|
||||
)
|
||||
|
||||
const attrs = useAttrs()
|
||||
@@ -152,9 +162,15 @@ const isFocused = ref(false)
|
||||
const inputId = computed(() => props.id?.toString() || `malio-input-textarea-${generatedId}`)
|
||||
const isControlled = computed(() => props.modelValue !== undefined)
|
||||
const currentValue = computed(() => (isControlled.value ? (props.modelValue ?? '') : localValue.value))
|
||||
const shouldFloatLabel = computed(() => isFocused.value || currentValue.value.length > 0)
|
||||
const hasError = computed(() => !!props.error)
|
||||
const hasSuccess = computed(() => !!props.success && !hasError.value)
|
||||
const isFilled = computed(() => currentValue.value.trim().length > 0)
|
||||
const isReadonly = computed(() => props.readonly && !props.disabled)
|
||||
const shouldFloatLabel = computed(() =>
|
||||
isReadonly.value
|
||||
? isFilled.value
|
||||
: isFocused.value || currentValue.value.length > 0,
|
||||
)
|
||||
const rowsCount = computed(() => Math.max(1, Number(props.size || 3)))
|
||||
const currentLength = computed(() => (currentValue.value ?? '').length)
|
||||
const showCounterComputed = computed(() =>
|
||||
@@ -168,7 +184,6 @@ const textareaStyle = computed(() => ({
|
||||
minHeight: toCssSize(props.minResizeHeight),
|
||||
maxHeight: toCssSize(props.maxResizeHeight),
|
||||
}))
|
||||
const isFilled = computed(() => currentValue.value.trim().length > 0)
|
||||
const describedBy = computed(() =>
|
||||
(hasError.value || hasSuccess.value || !!props.hint) ? `${inputId.value}-describedby` : undefined,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user