Mixins / foldkit-mixins-ui

Marquee

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

export * as Marquee from './marquee.js'

In the guides

Members

Marquee.init

function · packages/mixins-ui/src/marquee.ts:64

function init(options: {
  readonly id: string
  readonly paused?: boolean | undefined
}): Model

Marquee.MarqueeSide

type · packages/mixins-ui/src/marquee.ts:99

type MarqueeSide = 'start' | 'end' | 'top' | 'bottom'

Where the content moves to: the inline start or end, or up or down.

Marquee.MarqueeSlots

const · packages/mixins-ui/src/marquee.ts:36

const MarqueeSlots: Slots.Contract<{
  readonly root: Slot.UnnamedSlot<
    Capability.Capability<
      'Container',
      readonly [
        Capability.Capability<
          'Interactive',
          readonly [Capability.Capability<'Base', readonly []>]
        >,
      ]
    >,
    readonly Slot.EventName[],
    readonly [Attr.AttrToken<'role'>, Attr.AttrToken<'aria-label'>],
    readonly Slot.RequirementName[],
    boolean
  >
  readonly viewport: 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 content: 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 item: 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 pause: Slot.UnnamedSlot<
    Capability.Capability<
      'Interactive',
      readonly [Capability.Capability<'Base', readonly []>]
    >,
    readonly [Event.EventToken<'click'>],
    readonly [Attr.AttrToken<'aria-label'>],
    readonly Slot.RequirementName[],
    boolean
  >
}>

Content that scrolls on and on, after Zag's marquee: a region with aria-roledescription="marquee" named by its label, whose content is drawn as many times as it takes to fill the viewport and one more, each copy sliding by its own length and starting again, so the seam never shows. The copies after the first are inert: assistive technology reads the content once, and the keys reach each link in it once.

Resize (content, viewport) -> Measured -> copies, duration = length / speed

The sizes measured and whether it is paused are this Model, which the application keeps and folds with update. The movement itself is CSS: a pointer over it or focus inside it pauses it (pauseOnInteraction), and the pause press, drawn by default as WCAG 2.2.2 asks of anything that moves for more than five seconds, holds it until pressed again. Until the content is measured it moves at the recipe's --fk-marquee-duration.

Its distance travels, so reduced motion stills it; the recipe then lets the viewport scroll and draws one copy. The root carries data-side, data-orientation, data-paused and data-pause-on-interaction, and the timing as --fk-marquee-duration (seconds), --fk-marquee-delay and --fk-marquee-loop-count.

Marquee.MarqueeView

interface · packages/mixins-ui/src/marquee.ts:101

interface MarqueeView<Message> {
  readonly model: Model
  readonly onMessage: (message: typeof Message.Type) => NoInfer<Message>
  readonly label: string
  readonly items: ReadonlyArray<Html>
  readonly side?: MarqueeSide | undefined
  readonly speed?: number | undefined
  readonly delay?: number | undefined
  readonly loopCount?: number | undefined
  readonly pauseOnInteraction?: boolean | undefined
  readonly autoFill?: boolean | undefined
  readonly repeat?: number | undefined
  readonly controls?: boolean | undefined
  readonly pauseLabels?:
    | {
        readonly pause: string
        readonly play: string
      }
    | undefined
  readonly style?: NamedStyle<typeof MarqueeSlots> | undefined
  readonly mixins?: MixinList<Message> | undefined
}

Marquee.Message

const · packages/mixins-ui/src/marquee.ts:74

const Message: MessageUnion<{
  readonly MeasuredContent: { readonly size: Schema.Number }
  readonly MeasuredViewport: { readonly size: Schema.Number }
  readonly Paused: {}
  readonly Resumed: {}
}>

Marquee.Model

const · packages/mixins-ui/src/marquee.ts:52

const Model: Schema.Struct<{
  readonly id: Schema.String
  readonly paused: Schema.Boolean
  readonly content: Schema.Number
  readonly viewport: Schema.Number
}>

Marquee.update

function · packages/mixins-ui/src/marquee.ts:84

function update(model: Model, message: Message): Return<Model, Message>

The marquee after message; the same Model when nothing changes.

Marquee.view

function · packages/mixins-ui/src/marquee.ts:142

function view<Outer>(options: MarqueeView<Outer>, h: HtmlBuilder<Outer>): Html