feat : ajout composant select checkbox

This commit is contained in:
2026-03-12 15:31:29 +01:00
parent af4dcdfc04
commit c96eafdb23

View File

@@ -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)`,