feat(etabs): improve MultiEnumControlRenderer UX for analysis result export (#60)

* fix(ui): add scrolling support to MultiEnumControlRenderer dropdown

* feat(ui): add select all/deselect all functionality to MultiEnumControlRenderer

* fix(ui): prevent jumpiness and dropdown misalignment

* fix: not generous enough on the width

* fix: heigh alignment and comments
This commit is contained in:
Björn Steinhagen
2025-09-19 14:07:04 +02:00
committed by GitHub
parent aa5d59ba5b
commit 11b6d5254e
@@ -3,12 +3,17 @@
<div class="text-foreground-2 text-body-2xs mb-1 pl-1">
{{ control.label }}
</div>
<!-- button next to component (like revit send categories) -->
<!-- min width to keep components "in-sync" at narrow sizes -->
<!-- size "sm" matches height of select all toggle -->
<div class="flex items-center space-x-2 min-w-72">
<FormSelectMulti
:model-value="modelValue"
:name="fieldName"
:rules="multiValidator"
:label="control.label"
:items="control.options"
class="flex-1 min-w-0"
clearable
:search="true"
:search-placeholder="'Search'"
@@ -19,6 +24,7 @@
button-style="tinted"
:validate-on-value-update="validateOnValueUpdate"
mount-menu-on-body
fixed-height
@update:model-value="handleChange"
>
<template #nothing-selected>
@@ -46,6 +52,12 @@
</div>
</template>
</FormSelectMulti>
<!-- Select All / Deselect All button - positioned next to dropdown like Revit -->
<FormButton color="outline" class="min-w-28" size="base" @click="toggleSelectAll">
{{ allSelected ? 'Deselect all' : 'Select all' }}
</FormButton>
</div>
</div>
</template>
<script setup lang="ts">
@@ -108,4 +120,27 @@ const modelValue = computed(() => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return control.value.options.filter((o) => val?.includes(o.value))
})
/**
* Computed property to check if all available options are selected.
*/
const allSelected = computed(() => {
const currentSelection = modelValue.value || []
const allOptions = control.value.options || []
return currentSelection.length === allOptions.length && allOptions.length > 0
})
/**
* Toggle between selecting all categories and clearing all selections.
*/
const toggleSelectAll = () => {
if (allSelected.value) {
// deselect all -> pass empty array
handleChange([])
} else {
// select all available options
const allOptions = control.value.options || []
handleChange(allOptions)
}
}
</script>