feat : ajout composant select checkbox
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
? openDirection === 'down'
|
||||
? 'rounded-b-none !border-2 !border-m-primary !border-b-0'
|
||||
: 'rounded-t-none !border-2 !border-m-primary !border-t-0'
|
||||
: isOptionSelected
|
||||
: isOptionSelected
|
||||
? 'border-black'
|
||||
: 'border-m-muted',
|
||||
disabled ? 'cursor-not-allowed border-m-muted text-black/60' : 'cursor-pointer',
|
||||
@@ -44,7 +44,7 @@
|
||||
v-if="label"
|
||||
class="floating-label pointer-events-none absolute left-3 inline-block origin-left transition-transform duration-150 font-medium"
|
||||
:class="[
|
||||
isOpen ? 'top-2 z-30' : 'top-1/2 -translate-y-1/2',
|
||||
shouldFloatLabel ? 'top-2 z-30' : 'top-1/2 -translate-y-1/2',
|
||||
hasError
|
||||
? 'text-m-error'
|
||||
: hasSuccess
|
||||
@@ -61,7 +61,22 @@
|
||||
{{ label }}
|
||||
</label>
|
||||
|
||||
<div
|
||||
v-if="displayTags && selectedOptions.length > 0"
|
||||
class="flex flex-wrap items-center justify-start gap-1 px-1 pr-6"
|
||||
:class="[label ? 'pt-3 pb-1' : '']"
|
||||
>
|
||||
<span
|
||||
v-for="option in selectedOptions"
|
||||
:key="String(option.value)"
|
||||
class="inline-flex max-w-full items-center rounded-md border border-black px-2 text-sm leading-none text-black"
|
||||
>
|
||||
<span class="truncate">{{ option.label }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span
|
||||
v-show="!displayTags"
|
||||
class="block truncate text-right"
|
||||
:class="[
|
||||
textValue,
|
||||
@@ -184,6 +199,7 @@ const props = withDefaults(defineProps<{
|
||||
textValue?: string
|
||||
textLabel?: string
|
||||
rounded?: string
|
||||
displayTag?: boolean
|
||||
disabled?: boolean
|
||||
}>(), {
|
||||
options: () => [],
|
||||
@@ -198,6 +214,7 @@ const props = withDefaults(defineProps<{
|
||||
textValue: 'text-lg',
|
||||
textLabel: 'text-sm',
|
||||
rounded: 'rounded-md',
|
||||
displayTag: false,
|
||||
disabled: false,
|
||||
})
|
||||
|
||||
@@ -219,8 +236,14 @@ const hasSuccess = computed(() => !!props.success && !hasError.value)
|
||||
const isOptionSelected = computed(() =>
|
||||
props.modelValue.length > 0
|
||||
)
|
||||
const selectedOptions = computed(() =>
|
||||
normalizedOptions.value.filter(option => props.modelValue.includes(option.value)),
|
||||
)
|
||||
const displayTags = computed(() =>
|
||||
props.displayTag && selectedOptions.value.length > 0,
|
||||
)
|
||||
const shouldFloatLabel = computed(() =>
|
||||
isOpen.value
|
||||
isOpen.value || displayTags.value
|
||||
)
|
||||
const selectionSummary = computed(() =>
|
||||
`${props.modelValue.length}/${normalizedOptions.value.length}`
|
||||
@@ -264,24 +287,18 @@ function open() {
|
||||
}
|
||||
|
||||
const labelTransformStyle = computed(() => {
|
||||
// label non flottant
|
||||
if (!shouldFloatLabel.value) {
|
||||
return {
|
||||
transform: 'translateY(-50%)',
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
// fermé ou ouverture vers le bas : comportement classique
|
||||
if (!isOpen.value || openDirection.value === 'down') {
|
||||
return {
|
||||
transform: 'translateY(-1.15rem) scale(0.9)',
|
||||
}
|
||||
}
|
||||
|
||||
// ouverture vers le haut : on remonte en fonction de la hauteur de la liste
|
||||
const extraOffset = 8 // marge visuelle au-dessus de la liste en px
|
||||
const total = 4 +listHeight.value + extraOffset
|
||||
// 18 ≈ 1.15rem pour garder la même base que votre flottant actuel
|
||||
const total = 4 + listHeight.value + extraOffset
|
||||
|
||||
return {
|
||||
transform: `translateY(-${total}px) scale(0.9)`,
|
||||
|
||||
Reference in New Issue
Block a user