Mixins / foldkit-mixins-ui

Sheet

namespace · packages/mixins-ui/src/sheet.ts:27

export * as Sheet from './sheet.js'

A Sheet: a dialog pinned to an edge of the viewport, which its handle drags between resting points and, past the last, away, after vaul's Drawer. It is @foldkit/ui's Dialog (focus trap, Escape, the backdrop's dismissal, scroll lock, stacking) with a small Model of this module's beside it: the edge, the points it rests at, which one it rests at, and the drag running.

handle: Swipe -> Grabbed / Dragged / Released -> update -> point, or close
view: point -> --fk-sheet-snap; a drag -> --fk-sheet-offset -> the recipe's translate

A point is how much of the panel shows, from 0 to 1, so a point is a share of the panel and the CSS needs no measure; a drag is read against the panel's size, which the handle's Swipe measures as it starts. Let go, a flick (faster than FLICK_SPEED) goes on to the next point its way, or away past the last; a slower release rests at the nearest point, or goes away once dragged CLOSE_SHARE of the way out from the lowest. A drag past fully open is damped, as vaul's is. A press on the handle that barely moves steps to the next point, round to the first.

The handle is the only place a drag starts: content stays scrollable and selectable, and a press on a control stays a press. It is hidden from assistive technology, which has Escape and the sheet's own controls. Reduced motion keeps the drag (it follows the finger) and snaps the slide.

In the guides

Members

Sheet.close

function · packages/mixins-ui/src/sheet.ts:146

function close(model: Model): Return

Closes the Sheet; a no-op when it is closed.

Sheet.CLOSE_SHARE

const · packages/mixins-ui/src/sheet.ts:78

const CLOSE_SHARE: 0.25

A share of what shows at the lowest point that a slow drag takes away (vaul's 0.25).

Sheet.dragged

function · packages/mixins-ui/src/sheet.ts:239

function dragged(
  model: Model,
  drag: {
    readonly size: number
    readonly delta: number
  },
): number

How far in from fully open the panel is drawn during a drag: the drag itself, but damped past fully open as vaul's (8 * (ln(x + 1) - 2)), so the sheet gives a little and resists.

Sheet.FLICK_SPEED

const · packages/mixins-ui/src/sheet.ts:76

const FLICK_SPEED: 0.4

A release faster than this, in pixels a millisecond, goes on to the next point (vaul's 0.4).

Sheet.init

function · packages/mixins-ui/src/sheet.ts:98

function init(config: InitConfig): Model

A closed Sheet. Throws on points that are empty, out of order or out of (0, 1], or an opensAt among none.

Sheet.InitConfig

interface · packages/mixins-ui/src/sheet.ts:82

interface InitConfig {
  readonly id: string
  readonly side?: Side
  readonly points?: ReadonlyArray<number>
  readonly opensAt?: number
  readonly dismissible?: boolean
  readonly isAnimated?: boolean
}

Sheet.isOpen

function · packages/mixins-ui/src/sheet.ts:224

function isOpen(model: Model): boolean

Whether the Sheet is open, for a parent's covered or its own reading.

Sheet.Message

const · packages/mixins-ui/src/sheet.ts:64

const Message: MessageUnion<{
  readonly GotDialog: {
    readonly message: MessageUnion<{
      readonly RequestedOpen: {}
      readonly RequestedClose: {}
      readonly SucceededShowDialog: {}
      readonly FailedShowDialog: {}
      readonly SucceededAcquireResources: {}
      readonly FailedAcquireResources: {}
      readonly CompletedCloseDialog: {}
      readonly Unmounted: {}
      readonly CompletedReleaseDialogResources: {}
      readonly GotAnimationMessage: {
        message: import('foldkit/message').MessageUnion<{
          readonly Showed: {}
          readonly Hid: {}
          readonly CompletedWaitForPaint: { generation: Schema.Number }
          readonly EndedAnimation: { generation: Schema.Number }
        }>
      }
    }>
  }
  readonly Grabbed: { readonly size: Schema.Number }
  readonly Dragged: { readonly delta: Schema.Number }
  readonly Released: {
    readonly delta: Schema.Number
    readonly velocity: Schema.Number
    readonly completed: Schema.Boolean
  }
}>

Sheet.Model

const · packages/mixins-ui/src/sheet.ts:42

const Model: Schema.Struct<{
  readonly dialog: Schema.Struct<{
    readonly id: Schema.String
    readonly isOpen: Schema.Boolean
    readonly isAnimated: Schema.Boolean
    readonly animation: Schema.Struct<{
      readonly id: Schema.String
      readonly isShowing: Schema.Boolean
      readonly transitionState: Schema.Literals<
        readonly [
          'Idle',
          'EnterStart',
          'EnterAnimating',
          'LeaveStart',
          'LeaveAnimating',
        ]
      >
      readonly transitionGeneration: Schema.Number
    }>
    readonly maybeFocusSelector: Schema.Option<Schema.String>
  }>
  readonly side: Schema.Literals<readonly ['top', 'right', 'bottom', 'left']>
  readonly points: Schema.$Array<Schema.Number>
  readonly point: Schema.Number
  readonly opensAt: Schema.Number
  readonly dismissible: Schema.Boolean
  readonly drag: Schema.Option<
    Schema.Struct<{
      readonly size: Schema.Number
      readonly delta: Schema.Number
    }>
  >
}>

Sheet.open

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

function open(model: Model): Return

Opens the Sheet at its opensAt point.

Sheet.PRESS_SLOP

const · packages/mixins-ui/src/sheet.ts:80

const PRESS_SLOP: 4

A press on the handle that moves less than this, in pixels, is a press, not a drag.

Sheet.Return

type · packages/mixins-ui/src/sheet.ts:122

type Return = ReturnWithOutMessage<Model, Message, UiDialog.OutMessage>

The Sheet's step: its Model, its Commands, and the Dialog's Opened or Closed.

Sheet.settle

function · packages/mixins-ui/src/sheet.ts:157

function settle(release: {
  readonly points: ReadonlyArray<number>
  readonly at: number
  readonly size: number
  readonly delta: number
  readonly velocity: number
  readonly dismissible: boolean
}): Option.Option<number>

Where a release comes to rest: the index of a point, or none to go away. Pure, for the reasons in the module's comment; delta and velocity are toward the edge.

Sheet.SheetView

interface · packages/mixins-ui/src/sheet.ts:244

interface SheetView<Outer> {
  readonly model: Model
  readonly onMessage: (message: Message) => NoInfer<Outer>
  readonly mixins?: MixinList<Outer>
  readonly hasDescription?: boolean
  readonly covered?: boolean
  readonly scalesPage?: boolean
  readonly draw: (sheet: ResolvedDialog<Outer>) => Html
}

Sheet.Side

const · packages/mixins-ui/src/sheet.ts:39

const Side: Schema.Literals<readonly ['top', 'right', 'bottom', 'left']>

Sheet.update

function · packages/mixins-ui/src/sheet.ts:187

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

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

Sheet.view

function · packages/mixins-ui/src/sheet.ts:269

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

The Sheet: @foldkit/ui's Dialog view, its bundles resolved as the Dialog's are, with the drag on the handle and its place on the panel. Draw handle in the panel; a sheet with points draws its content so that what matters shows at the lowest.