Mixins / foldkit-mixins-ui

Tabs

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

export * as Tabs from './tabs.js'

In the guides

Members

Tabs.fluid

const · packages/mixins-ui/src/tabs.ts:57

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

What moves the indicator and highlight: on the tablist, the chosen tab is measured (--fk-tabs-chosen-x, -y, -w, -h, -display) and one highlight follows the pointer to the nearest tab (--fk-tabs-hover-*), growing out of the chosen tab and returning to it. Pass them beside the style; until they run (before a page hydrates, or without them), each tab marks itself and the drawn indicator and highlight show nothing.

Tabs.resolve

function · packages/mixins-ui/src/tabs.ts:86

function resolve<Value extends string, Input, Message>(
  render: RenderInfo<Value>,
  mixins: MixinList<Message>,
  context: ResolveContext<Input, Message>,
): ResolvedTabs<Value, Message>

Resolves the tabs' nested render groups, preserving activeIndex.

Tabs.ResolvedTab

type · packages/mixins-ui/src/tabs.ts:32

type ResolvedTab<Value extends string, Message> = Omit<
  TabInfo<Value>,
  'tab' | 'panel'
> & {
  readonly tab: SlotAttributes<Message>
  readonly panel: SlotAttributes<Message>
}

Tabs.ResolvedTabs

interface · packages/mixins-ui/src/tabs.ts:37

interface ResolvedTabs<Value extends string, Message> {
  readonly tablist: SlotAttributes<Message>
  readonly indicator: SlotAttributes<Message>
  readonly highlight: SlotAttributes<Message>
  readonly tabs: ReadonlyArray<ResolvedTab<Value, Message>>
  readonly activeIndex: number
}

Tabs.TabsSlots

const · packages/mixins-ui/src/tabs.ts:20

const TabsSlots: Slots.Contract<{
  readonly tablist: Slot.UnnamedSlot<
    Capability.Capability<
      'Container',
      readonly [
        Capability.Capability<
          'Interactive',
          readonly [Capability.Capability<'Base', readonly []>]
        >,
      ]
    >,
    readonly Slot.EventName[],
    readonly [Attr.AttrToken<'role'>],
    readonly Slot.RequirementName[],
    boolean
  >
  readonly tab: Slot.UnnamedSlot<
    Capability.Capability<
      'Interactive',
      readonly [Capability.Capability<'Base', readonly []>]
    >,
    readonly [Event.EventToken<'click'>],
    readonly [
      Attr.AttrToken<'role'>,
      Attr.AttrToken<'aria-selected'>,
      Attr.AttrToken<'disabled'>,
      Attr.AttrToken<'aria-disabled'>,
    ],
    readonly Slot.RequirementName[],
    boolean
  >
  readonly panel: Slot.UnnamedSlot<
    Capability.Capability<
      'Container',
      readonly [
        Capability.Capability<
          'Interactive',
          readonly [Capability.Capability<'Base', readonly []>]
        >,
      ]
    >,
    readonly Slot.EventName[],
    readonly [Attr.AttrToken<'role'>],
    readonly Slot.RequirementName[],
    boolean
  >
  readonly indicator: 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 highlight: Slot.UnnamedSlot<
    Capability.Capability<
      'Container',
      readonly [
        Capability.Capability<
          'Interactive',
          readonly [Capability.Capability<'Base', readonly []>]
        >,
      ]
    >,
    readonly Slot.EventName[],
    readonly Slot.AttributeName[],
    readonly Slot.RequirementName[],
    boolean
  >
}>

Tabs is a nested Submodel: one tablist group plus a tab/panel pair per item, so the resolver runs once per group and each base ChildAttribute bundle passes through by identity.

Enabled tabs own click through the base OnClick; a Behavior adding its own click handler is a conflict rather than a second silent owner. Disabled tabs publish no click, so the contract still lists it as allowed.

indicator and highlight have no upstream bundle: they are this package's, drawn first in the tablist, for the marker under the chosen tab and the hover that follows the pointer, which fluid moves.

Tabs.toView

function · packages/mixins-ui/src/tabs.ts:106

function toView<Value extends string, Message>(
  mixins: MixinList<Message>,
  context: ResolveContext<unknown, Message>,
  draw: (resolved: ResolvedTabs<Value, Message>) => Html,
): (render: RenderInfo<Value>) => Html

The tabs' toView: draw receives their bundles with mixins applied.