You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/eidos/components/combobox
dev 218ccfcc5e
Theming: untitled-ui demo theme, engine fixes, audit + P0/P1 fixes
4 months ago
..
README.md combobox: PASS audit + extend focus-move list for listbox/menu nav 5 months ago
combobox-arrow.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-clear-button.svelte refactor(combobox + search-field): ClearButton/Clear render <Button> 5 months ago
combobox-content.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-control.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-group-heading.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-group.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-indicator.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-input.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-item-indicator.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-item.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-selected-tag-remove.svelte feat(combobox): SelectedTags inline chips for multi mode 5 months ago
combobox-selected-tag.svelte feat(combobox): SelectedTags inline chips for multi mode 5 months ago
combobox-selected-tags.svelte feat(combobox): SelectedTags inline chips for multi mode 5 months ago
combobox-separator.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-trigger.svelte Advance Eidos demos and form validation docs 5 months ago
combobox-viewport.svelte Advance Eidos demos and form validation docs 5 months ago
combobox.css Theming: untitled-ui demo theme, engine fixes, audit + P0/P1 fixes 4 months ago
combobox.svelte Advance Eidos demos and form validation docs 5 months ago
context.svelte.ts Advance Eidos demos and form validation docs 5 months ago
index.ts feat(combobox): SelectedTags inline chips for multi mode 5 months ago
types.ts refactor(combobox + search-field): ClearButton/Clear render <Button> 5 months ago

README.md

Combobox

Eidos Combobox wraps Soma Combobox and keeps the component compound: <Combobox> + Control, Input, Trigger, Indicator, Portal, Content, Viewport, Item, ItemIndicator, Group, GroupHeading, Separator and Arrow.

Baseline

  • air: tenía un Combobox completo con input editable, popover listbox, groups/separators, hidden form value, scroll affordances y validation state. Es la referencia ergonomic.
  • soma actual: cubre input value + open state + single/multiple values + hidden inputs + groups + floating + dismissal + keyboard nav.
  • morfo: declara las parts y el contrato data-/aria-; eventos sema sólo para commit-select y commit-unselect.

Comparativa

Feature Air Radix Bits Ark shadcn-svelte React Aria Soma Eidos Decision
Editable input + popup listbox ✅ ❌ ✅ ✅ ⚠️ ✅ ✅ ✅ Covered with Input + Content; Radix has no dedicated Combobox primitive.
Compound anatomy ✅ ❌ ✅ ✅ ⚠️ ✅ ✅ ✅ Eidos exposes one namespace and attached parts; the root is <Combobox> itself.
Input + trigger grouped visually ✅ ❌ ✅ ✅ ✅ ✅ ✅ ✅ Combobox.Control is Eidos-only layout.
Portal + floating content + arrow ✅ ❌ ✅ ✅ ✅ ✅ ✅ ✅ Soma owns Floating; Eidos consumes data-side and floating CSS vars.
Groups, headings and separators ✅ ❌ ✅ ✅ ⚠️ ✅ ✅ ✅ Covered.
Selected item indicator ⚠️ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ItemIndicator is Eidos-only; item state comes from Soma/Morfo.
Single select ✅ ❌ ✅ ✅ ✅ ✅ ✅ ✅ Covered.
Multiple select ✅ ❌ ✅ ✅ ❌ ❌ ✅ ✅ Covered by Soma type="multiple"; Eidos only styles selected items.
Typeahead / filtering input ✅ ❌ ✅ ✅ ✅ ✅ ✅ ✅ Soma owns input value and filtering surface.
Hidden form value ✅ ❌ ✅ ✅ ⚠️ ✅ ✅ ✅ Soma renders hidden inputs when name is passed.
Clear trigger ❌ ❌ ⚠️ ✅ ❌ ✅ ❌ ❌ Defer to Soma; clearing changes value/input state.
Scroll up/down affordance parts ✅ ❌ ✅ ⚠️ ❌ ❌ ❌ ❌ Defer to Soma; requires viewport scroll behavior.
Static/non-floating content ✅ ❌ ⚠️ ⚠️ ❌ ❌ ❌ ❌ Defer to Soma if inline listbox topology is needed.
Menu trigger behavior ❌ ❌ ⚠️ ✅ ❌ ✅ ❌ ❌ Defer to Soma; affects when open state changes.
Inline autocomplete / auto highlight ❌ ❌ ⚠️ ✅ ❌ ✅ ❌ ❌ Defer to Soma; input behavior, not visual styling.
Custom value / freeform commit ❌ ❌ ⚠️ ⚠️ ❌ ✅ ❌ ❌ Defer to Soma/Form; needs value semantics.
Validation state ✅ ❌ ⚠️ ✅ ⚠️ ✅ ❌ ❌ Defer to Field/Soma; Eidos must not invent invalid state.
Async/virtualized collections ❌ ❌ ⚠️ ✅ ❌ ✅ ❌ ❌ Belongs in collection/virtualization, not visual wrapper.

References:

Layer split

Layer Owns
Morfo Parts, ARIA/data contract, commit-select and commit-unselect events.
Soma Input text, open state, single/multiple values, hidden form inputs, groups, floating, dismissal and keyboard navigation.
Sema Subtle form commit sounds + tap haptic for select/unselect. Typing, filtering, open/close and highlight are intentionally silent.
Eidos Control layout, size, variant, intent color, trigger icon, selected item indicator, panel recipe and animation.

Morfo/Sema

Event Family Verb Intent Target Sequence Reason
commit-select commit select affirm item post User confirms an option. The concrete item is the perceived target.
commit-unselect commit remove neutral item post Multiple deselect or single clear via allowDeselect.

Opening, closing, typing, filtering and highlighting are navigation mechanics, not committed choices. They do not emit Sema events.

Decisiones

  • No se emiten eventos sema en open/close/typing/filter/highlight. Son mecánicas de navegación, no compromisos del usuario. El sema sólo viaja con commit-select y commit-unselect (la elección concreta).
  • Las teclas de navegación interna de la listbox son focus moves: ArrowDown/ArrowUp/Home/End mueven el highlight, no mutan el valor. El audit las cuenta como focus-only — el único keystroke que mutea es Enter (mapped a select → covered por commit-select).
  • Escape delega al popover: la tecla cierra cerrando la layer popover/dismissal; combobox no duplica el evento close-dismiss que ya emite el popover.
  • Combobox.Control es composición Eidos-only: agrupa Input + Trigger
    • Indicator dentro de un único chrome. No tiene contraparte en morfo/soma porque es puramente layout visual.
  • ItemIndicator es Eidos-only: el estado del item llega vía data-state que el provider sopla; ItemIndicator sólo decide qué glyph pintar en función de ese atributo.
  • Single vs multiple lo decide el consumer via prop type: el morfo expone data-type en Provider para que la receta pueda diferenciar.
  • Multi-select aria-multiselectable se aplica condicionalmente cuando prop:multiple es truthy.

Gaps

Gap Disposición Detalle
ClearTrigger (Ark, React Aria) implementar Mutates value + inputValue. Estimación 80-140 LOC across Morfo/Soma/Eidos. Útil para todos los pickers con field input.
ScrollUpButton / ScrollDownButton (air, bits) diferir Requiere scroll behavior + viewport awareness en soma. Sin demanda actual. 120-180 LOC.
ContentStatic (variante inline, no floating) diferir Cambia topología y dismissal. Sin caso de uso. 80-140 LOC.
menuTrigger / autoHighlight / inlineAutocomplete (ark, react-aria) diferir Afectan open/highlighted/input value state. 180-260 LOC. Esperar caso real.
Custom / freeform value (react-aria) diferir Cambia value semantics + form value submitted. 140-220 LOC.
Validation state implementar Combobox debe consumir field state real cuando esté dentro de un <Field>. 120-200 LOC. Bloqueante para integración Form.
Async / virtualized collections descartar Belongs in collection/virtualization layer, no Eidos. Out of scope.
Modal mode + footer pattern (como pickers) descartar Combobox es inline por diseño — no es un picker con confirmación explícita.

Usage

<script lang="ts">
	import { Combobox } from '$uix/eidos/components/combobox'

	let value = $state<string[]>([])
	let inputValue = $state('')
</script>

<Combobox bind:value bind:inputValue name="framework" size="md" variant="surface" color="primary">
	<Combobox.Control>
		<Combobox.Input placeholder="Search framework..." />
		<Combobox.Trigger>
			<Combobox.Indicator />
		</Combobox.Trigger>
	</Combobox.Control>
	<Combobox.Portal>
		<Combobox.Content sideOffset={6}>
			<Combobox.Viewport>
				<Combobox.Group>
					<Combobox.GroupHeading>Frontend</Combobox.GroupHeading>
					<Combobox.Item value="svelte" label="Svelte">
						<span>Svelte</span>
						<Combobox.ItemIndicator />
					</Combobox.Item>
					<Combobox.Item value="react" label="React">
						<span>React</span>
						<Combobox.ItemIndicator />
					</Combobox.Item>
					<Combobox.Item value="vue" label="Vue">
						<span>Vue</span>
						<Combobox.ItemIndicator />
					</Combobox.Item>
					<Combobox.Item value="solid" label="Solid">
						<span>Solid</span>
						<Combobox.ItemIndicator />
					</Combobox.Item>
				</Combobox.Group>
				<Combobox.Separator />
				<Combobox.Group>
					<Combobox.GroupHeading>Runtime</Combobox.GroupHeading>
					<Combobox.Item value="node" label="Node">
						<span>Node</span>
						<Combobox.ItemIndicator />
					</Combobox.Item>
					<Combobox.Item value="deno" label="Deno">
						<span>Deno</span>
						<Combobox.ItemIndicator />
					</Combobox.Item>
				</Combobox.Group>
			</Combobox.Viewport>
			<Combobox.Arrow />
		</Combobox.Content>
	</Combobox.Portal>
</Combobox>

Powered by TurnKey Linux.