add image support to MultiSelect
This commit is contained in:
parent
23527c727e
commit
d47b076dda
1 changed files with 37 additions and 1 deletions
|
|
@ -9,6 +9,7 @@
|
||||||
label: string
|
label: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
color?: string
|
color?: string
|
||||||
|
image?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -44,6 +45,11 @@
|
||||||
// Convert value array to string array for Bits UI
|
// Convert value array to string array for Bits UI
|
||||||
const stringValue = $derived(value.map((v) => String(v)))
|
const stringValue = $derived(value.map((v) => String(v)))
|
||||||
|
|
||||||
|
// Get first selected option for display (image/color)
|
||||||
|
const firstSelectedOption = $derived(
|
||||||
|
value.length > 0 ? options.find((opt) => opt.value === value[0]) : undefined
|
||||||
|
)
|
||||||
|
|
||||||
// Get selected labels for display
|
// Get selected labels for display
|
||||||
const selectedLabels = $derived(() => {
|
const selectedLabels = $derived(() => {
|
||||||
if (value.length === 0) return null
|
if (value.length === 0) return null
|
||||||
|
|
@ -84,6 +90,11 @@
|
||||||
items={stringOptions}
|
items={stringOptions}
|
||||||
>
|
>
|
||||||
<SelectPrimitive.Trigger class={selectClasses} data-placeholder={value.length === 0}>
|
<SelectPrimitive.Trigger class={selectClasses} data-placeholder={value.length === 0}>
|
||||||
|
{#if firstSelectedOption?.image}
|
||||||
|
<img src={firstSelectedOption.image} alt="" class="trigger-image" />
|
||||||
|
{:else if firstSelectedOption?.color}
|
||||||
|
<span class="trigger-color-dot" style="background-color: {firstSelectedOption.color}"></span>
|
||||||
|
{/if}
|
||||||
<span class="text">{selectedLabels() || placeholder}</span>
|
<span class="text">{selectedLabels() || placeholder}</span>
|
||||||
<Icon name="chevron-down-small" size={14} class="chevron" />
|
<Icon name="chevron-down-small" size={14} class="chevron" />
|
||||||
</SelectPrimitive.Trigger>
|
</SelectPrimitive.Trigger>
|
||||||
|
|
@ -99,7 +110,11 @@
|
||||||
style={option.color ? `--option-color: ${option.color}` : ''}
|
style={option.color ? `--option-color: ${option.color}` : ''}
|
||||||
>
|
>
|
||||||
{#snippet children({ selected })}
|
{#snippet children({ selected })}
|
||||||
<span class="label" class:has-color={!!option.color} class:selected>{option.label}</span
|
{#if option.image}
|
||||||
|
<img src={option.image} alt="" class="item-image" />
|
||||||
|
{/if}
|
||||||
|
<span class="label" class:has-color={!!option.color && !option.image} class:selected
|
||||||
|
>{option.label}</span
|
||||||
>
|
>
|
||||||
<span class="indicator">
|
<span class="indicator">
|
||||||
<Icon name="check" size={12} class="check-icon {selected ? 'visible' : ''}" />
|
<Icon name="check" size={12} class="check-icon {selected ? 'visible' : ''}" />
|
||||||
|
|
@ -166,6 +181,20 @@
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.trigger-image {
|
||||||
|
width: $unit-3x;
|
||||||
|
height: $unit-3x;
|
||||||
|
flex-shrink: 0;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trigger-color-dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
:global(.chevron) {
|
:global(.chevron) {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
|
|
@ -254,6 +283,13 @@
|
||||||
border-bottom-right-radius: $item-corner;
|
border-bottom-right-radius: $item-corner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-image {
|
||||||
|
width: $unit-3x;
|
||||||
|
height: $unit-3x;
|
||||||
|
flex-shrink: 0;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
:global(.check-icon) {
|
:global(.check-icon) {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity $duration-quick ease;
|
transition: opacity $duration-quick ease;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue