feat(filter-builder): multi-pick values render as removable chips
The id-kind value cells (feed/library/collection/added_by) rendered their picks as one comma-joined string inside a 9rem-wide input — you saw the first label and nothing else, and reading 3-5 picks meant scrolling inside a tiny box (worst on mobile, user request 2026-11-01). Id-kind cells now render a chipbox: each picked value is a chip (label truncated with a hover title, removable via an X button with a finger- sized tap target), the box flex-wraps and grows vertically instead of clipping, and the inline input stays at the end for typing/searching — including the Backspace-on-empty-removes-last-chip affordance. Text/ number/date cells keep today's single input; the value menu is unchanged (it never offers an already-picked value, so the chip X is the faster removal path, not a new one). Presentation only: the stored wire is still one comma-joined value per rule; matching, menus, apply, and label resolution are untouched. Pins moved from valueCellText (now text-cells-only) to the chip model (idChipsFor/idDraftFor) and cover removal order, last-chip removal, and Backspace; 187 web tests green.
This commit is contained in:
1 parent
d56031f334
commit
a20741ccc9
6 files changed
+187
-27
No files matched your search
@@ -59,10 +59,28 @@ templ FilterBuilderRows(countNoun string) {
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="hasValueCell(row.rule) && (valueArity(row.rule) === 'one' || valueArity(row.rule) === 'many')">
|
||||
<span class="fb-value-cell relative flex items-center gap-1">
|
||||
<input type="text" class="input fb-value" :value="valueCellText(row.path)" @input.debounce.250ms="onValueCellInput(row.path, $el.value)" @focus="openValueMenu(row.key, row.path, row.rule)" :placeholder="valuePlaceholderFor(row.rule)"/>
|
||||
<template x-if="fieldIsDays(row.rule.field)">
|
||||
<span class="text-xs whitespace-nowrap" style="color: var(--text-secondary)" x-text="'days'"></span>
|
||||
<span class="fb-value-cell relative flex items-center gap-1" :class="isIdValueRow(row.path) ? 'fb-chipbox flex-wrap' : ''">
|
||||
<template x-if="isIdValueRow(row.path)">
|
||||
<span class="contents">
|
||||
<!-- picked values as removable chips: the box
|
||||
wraps and grows instead of a 9rem input
|
||||
you can't read past the first entry -->
|
||||
<template x-for="chip in idChipsFor(row.path)" :key="chip.id">
|
||||
<span class="fb-chip" :title="chip.label">
|
||||
<span class="fb-chip-label" x-text="chip.label"></span>
|
||||
<button type="button" class="fb-chip-x" :aria-label="'Remove ' + chip.label" @click="removeIdChip(row.path, chip.id)">×</button>
|
||||
</span>
|
||||
</template>
|
||||
<input type="text" class="fb-value fb-chip-input" :value="idDraftFor(row.path)" @input.debounce.250ms="onValueCellInput(row.path, $el.value)" @focus="openValueMenu(row.key, row.path, row.rule)" @keydown="chipInputKeydown(row.path, $event)" :placeholder="valuePlaceholderFor(row.rule)" :aria-label="fieldLabelOf(row.rule.field) + ' values'"/>
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="!isIdValueRow(row.path)">
|
||||
<span class="contents">
|
||||
<input type="text" class="input fb-value" :value="valueCellText(row.path)" @input.debounce.250ms="onValueCellInput(row.path, $el.value)" @focus="openValueMenu(row.key, row.path, row.rule)" :placeholder="valuePlaceholderFor(row.rule)"/>
|
||||
<template x-if="fieldIsDays(row.rule.field)">
|
||||
<span class="text-xs whitespace-nowrap" style="color: var(--text-secondary)" x-text="'days'"></span>
|
||||
</template>
|
||||
</span>
|
||||
</template>
|
||||
<!-- field-aware value menu: server JSON (the other
|
||||
rules bound), or the field's fixed options.
|
||||
|
||||
Reference in new issue
Block a user