Components

Angle slider

An angle in degrees from a dial, dragged round or stepped by the keys, with marks.

tone
track
value
size
scheme
direction

Basic #

Heading
export const AngleSliderStyle = forSlots(AngleSliderSlots)(Recipes.AngleSlider({}))

/** What `update` and the view agree on: whole degrees, the compass points marked. */
export const HEADING_LAYOUT: AngleSlider.AngleSliderLayout = {
  step: 1,
  marks: [
    { value: 0, label: 'N' },
    { value: 90, label: 'E' },
    { value: 180, label: 'S' },
    { value: 270, label: 'W' },
  ],
}

/** The angle and the drag are the dial's Model, folded with `AngleSlider.update(HEADING_LAYOUT)`. */
export const angleSlider = <Message>(
  style: NamedStyle<typeof AngleSliderSlots>,
  model: AngleSlider.Model,
  onMessage: (message: AngleSlider.Message) => Message,
  h: HtmlBuilder<Message>,
): Html =>
  AngleSlider.view(
    { ...HEADING_LAYOUT, model, onMessage, label: 'Heading', name: 'heading', style },
    h,
  )

Kept to marks #

Rotation
/** A quarter turn at a time: a drag lands on the nearest mark, and the keys go mark to mark. */
export const ROTATION_LAYOUT: AngleSlider.AngleSliderLayout = {
  step: 90,
  marks: [{ value: 0 }, { value: 90 }, { value: 180 }, { value: 270 }],
  restrictToMarks: true,
}

export const angleSliderMarks = <Message>(
  style: NamedStyle<typeof AngleSliderSlots>,
  model: AngleSlider.Model,
  onMessage: (message: AngleSlider.Message) => Message,
  h: HtmlBuilder<Message>,
): Html =>
  AngleSlider.view(
    {
      ...ROTATION_LAYOUT,
      model,
      onMessage,
      label: 'Rotation',
      format: value => `${value / 90} of 4`,
      valueText: value => `${value} degrees`,
      style,
    },
    h,
  )

Usage

Each example above names the function that drew it, over the theme module Create a theme writes. The preview passes it the style picked above instead of its default.

The recipe ↗This code ↗