Mixins / foldkit-mixins-ui

Listbox

namespace · packages/mixins-ui/src/listbox.ts:1

export * as Listbox from './listbox.js'

In the guides

Members

Listbox.fluid

const · packages/mixins-ui/src/listbox.ts:188

const fluid: readonly [Mixin<never>, Mixin<never>]

What moves the open panel's highlight and indicator: on its rows, the chosen row is measured (--fk-popup-chosen-*) and one highlight follows the pointer to the nearest row (--fk-popup-hover-*), and to the row the keys mark (data-active) while the pointer is away. Pass them beside the style; until they run, each row marks itself.

Listbox.ListboxSlots

const · packages/mixins-ui/src/listbox.ts:26

const ListboxSlots: Slots.Contract<{ readonly wrapper: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly button: Slot.UnnamedSlot<Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>, readonly [Event.EventToken<"click">, Event.EventToken<"pointerdown">, Event.EventToken<"keydown">], readonly [Attr.AttrToken<"role">, Attr.AttrToken<"aria-expanded">, Attr.AttrToken<"disabled">, Attr.AttrToken<"aria-disabled">], readonly Slot.RequirementName[], boolean>; readonly backdrop: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly [Event.EventToken<"click">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly items: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly [Event.EventToken<"keydown">, Event.EventToken<"blur">], readonly [Attr.AttrToken<"role">], readonly Slot.RequirementName[], boolean>; readonly scroll: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], re …;

Listbox is a nested Submodel: one button/backdrop/items group plus an item per entry (and group/heading/separator where the caller groups), so the resolver runs once per bundle and each base attribute passes through by identity. hiddenInputs are the form inputs submitted under name: generated markup with no styling surface, passed through for the draw to place.

The button owns click (and pointerdown/keydown while enabled); an item owns click while interactive. A Behavior adding its own handler to one of those is a conflict, not a second silent owner. Disabled buttons and items publish no click, so the contract still lists it as allowed.

Listbox.resolve

function · packages/mixins-ui/src/listbox.ts:95

function resolve<Input, Message>(
  render: ListboxRenderInfo,
  mixins: MixinList<Message>,
  context: ResolveContext<Input, Message>,
): ResolvedListbox<Message>

Resolves the listbox's bundles (and every item's); pass-throughs stay intact.

Listbox.ResolvedListbox

type · packages/mixins-ui/src/listbox.ts:71

type ResolvedListbox<Message> = Omit<
  ListboxRenderInfo,
  'wrapper' | 'button' | 'backdrop' | 'items' | 'scroll' | 'groups'
> & {
  readonly wrapper: SlotAttributes<Message>
  readonly button: SlotAttributes<Message>
  readonly buttonContent: Html
  readonly hiddenInputs: ReadonlyArray<Html>
  readonly backdrop:
    | {
        key: string
        attributes: SlotAttributes<Message>
      }
    | undefined
  readonly items:
    | {
        key: string
        attributes: SlotAttributes<Message>
      }
    | undefined
  readonly scroll: SlotAttributes<Message> | undefined
  readonly rows: SlotAttributes<Message> | undefined
  readonly highlight: SlotAttributes<Message> | undefined
  readonly indicator: SlotAttributes<Message> | undefined
  readonly groups: ReadonlyArray<ResolvedListboxGroup<Message>>
}

Listbox.ResolvedListboxGroup

type · packages/mixins-ui/src/listbox.ts:61

type ResolvedListboxGroup<Message> = Omit<
  ListboxGroupRender,
  'heading' | 'group' | 'separator' | 'items'
> & {
  readonly heading: ResolvedListboxHeading<Message> | undefined
  readonly group:
    | {
        key: string
        attributes: SlotAttributes<Message>
      }
    | undefined
  readonly separator:
    | {
        key: string
        attributes: SlotAttributes<Message>
      }
    | undefined
  readonly items: ReadonlyArray<ResolvedListboxItem<Message>>
}

Listbox.ResolvedListboxHeading

type · packages/mixins-ui/src/listbox.ts:57

type ResolvedListboxHeading<Message> = Omit<
  ListboxHeadingRender,
  'attributes'
> & {
  readonly attributes: SlotAttributes<Message>
}

Listbox.ResolvedListboxItem

type · packages/mixins-ui/src/listbox.ts:53

type ResolvedListboxItem<Message> = Omit<ListboxItemRender, 'attributes'> & {
  readonly attributes: SlotAttributes<Message>
}

Listbox.toView

function · packages/mixins-ui/src/listbox.ts:169

function toView<Message>(
  mixins: MixinList<Message>,
  context: ResolveContext<unknown, Message>,
  draw?: (resolved: ResolvedListbox<Message>) => Html,
): (render: ListboxRenderInfo) => Html

The listbox's toView: draw receives its bundles with mixins applied. Without one, it draws upstream's markup from them.