refactor(combobox): SelectedTags as band above the Control (Chakra pattern)

Switched the multi-mode chips from MUI-style "inline inside the input"
to the Chakra v3 multi-select pattern — chips render as a separated
band ABOVE the Control. Two wins:

- The dropdown popover (opens downward) never covers the selected
  chips, which sit comfortably above the input.
- The Control stays a normal-height single-line input. No layout
  shifts, no absolute-positioned affordances, no `display: contents`
  gymnastics, no input flex tuning.

Reverts the inside-the-Control CSS gymnastics from `30e9517a` /
`64bbe9b1` / `87e3d68f` (flex-wrap, padding-right reservation,
absolute clear+trigger, input flex basis). `<Combobox.SelectedTags>`
now renders as a plain `flex-wrap` row with chip gap and a margin-
block-end separating it from the Control. Demo composes
`<Combobox.SelectedTags />` BEFORE `<Combobox.Control>` when
`mode === 'multiple'`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
active-uix
dev 5 months ago
parent 91b0efc461
commit 20709caf9c

@ -88,7 +88,6 @@
box-sizing: border-box;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--_combobox-control-gap);
inline-size: 100%;
min-inline-size: 0;
@ -165,11 +164,9 @@
[data-combobox-input] {
box-sizing: border-box;
/* Basis `4rem` lets the input share a wrapped row with chips +
* clear/trigger affordances while still growing to fill any remaining
* space. Pure `inline-size: 100%` forces a new line under flex-wrap. */
flex: 1 1 4rem;
min-inline-size: 4rem;
flex: 1 1 auto;
inline-size: 100%;
min-inline-size: 0;
border: 0;
background: transparent;
color: inherit;
@ -493,59 +490,25 @@
}
}
/* SelectedTags — logical group for the chip strip. Uses
* `display: contents` so each chip becomes a direct flex child of
* `<Combobox.Control>` instead of being nested in its own row. This
* lets the input flow on the same wrapped row as the last chip
* (Material UI Autocomplete behaviour) rather than always dropping
* to a fresh row below the whole tag block. */
/* SelectedTags — chip strip rendered ABOVE the Control so the
* dropdown popover (which opens downward) never covers the selected
* values. Chakra v3 multi-select pattern: clean separated band, the
* Control stays plain `<input>` height with no layout shift. */
[data-combobox-selected-tags] {
display: contents;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-1-5);
margin-block-end: var(--space-2);
min-inline-size: 0;
}
/* Empty state — element stays in DOM (so `:has(...:not([data-empty]))`
* still works for layout siblings) but no children render. */
/* Hide entirely when no chips so the Control isn't pushed down by an
* empty band. */
[data-combobox-selected-tags][data-empty] {
display: none;
}
/* Material UI Autocomplete pattern — when chips are present, pin the
* right-side affordances absolutely so chips + input wrap freely
* without ever pushing the clear/trigger to a new row.
*
* `--_combobox-affordances-w` reserves the right-padding the
* absolutely-positioned ClearButton + Trigger consume (each is ~26px
* wide with size=md, scaled below for xs/sm/lg/xl). */
[data-combobox-control]:has([data-combobox-selected-tags]:not([data-empty])) {
--_combobox-affordances-w: calc(var(--_combobox-control-height) * 2);
position: relative;
padding-block: var(--space-1);
padding-inline-end: calc(var(--_combobox-control-px) + var(--_combobox-affordances-w));
}
[data-combobox-control]:has([data-combobox-selected-tags]:not([data-empty]))
[data-combobox-clear-button],
[data-combobox-control]:has([data-combobox-selected-tags]:not([data-empty]))
[data-combobox-trigger] {
position: absolute;
/* Pin to the FIRST row of the wrapped control so the affordances stay
* aligned with the input + chip row even when many chips wrap into
* extra rows below. `padding-block` (var(--space-1)) is the control's
* top offset; matching that here keeps the buttons flush with the
* first chip / input row. */
inset-block-start: var(--space-1);
}
[data-combobox-control]:has([data-combobox-selected-tags]:not([data-empty]))
[data-combobox-clear-button] {
inset-inline-end: calc(var(--_combobox-control-px) + var(--_combobox-control-height));
}
[data-combobox-control]:has([data-combobox-selected-tags]:not([data-empty]))
[data-combobox-trigger] {
inset-inline-end: var(--_combobox-control-px);
}
[data-combobox-selected-tag] {
display: inline-flex;
align-items: center;

@ -265,10 +265,10 @@
{color}
name="framework"
>
{#if mode === 'multiple'}
<Combobox.SelectedTags />
{/if}
<Combobox.Control>
{#if mode === 'multiple'}
<Combobox.SelectedTags />
{/if}
<Combobox.Input
placeholder="Search framework..."
data-perm-step={!disabled ? '0' : undefined}

Loading…
Cancel
Save

Powered by TurnKey Linux.