kit

Keyboard sheet

Built revision v17.10.0

React
Topics

Human support

Bring a missing role, layout, or state, or a rendering against the standard, to the session working on kit. Name the package and the entry.

On Shell, Help

Keyboard sheet, open

Keyboard shortcuts

Show the open keyboard sheet

Keyboard shortcuts

Find and navigate

  • Find/
  • Todayt

Booking work

  • New bookingn
  • Keyboard sheet?

Keyboard shortcuts

Help carries the link above except where the primary pointer is coarse, where the sheet and the link are both absent. The core composition is open and not modal; Phoenix’s controller and React’s showModal make it modal, on its Backdrop, and return focus.

Source
type event
type detail = {dispatcher: Dom.element}
type request = {detail: detail}
@send external listen: (Dom.element, string, event => unit) => unit = "addEventListener"
@send external unlisten: (Dom.element, string, event => unit) => unit = "removeEventListener"
@new external request: (string, request) => event = "CustomEvent"
@send external dispatch: (Dom.element, event) => bool = "dispatchEvent"
@send @return(nullable) external find: (Dom.element, string) => option<Dom.element> = "querySelector"
@get external isOpen: Dom.element => bool = "open"
@set external disclose: (Dom.element, bool) => unit = "open"

@react.component
let make = () => {
  let caseRef = React.useRef(Nullable.null)
  let sheetRef = React.useRef(Nullable.null)

  React.useEffect0(() => switch (Nullable.toOption(caseRef.current), Nullable.toOption(sheetRef.current)) {
  | (Some(details), Some(sheet)) =>
    let discloseCase = _ => details->disclose(true)
    let openFromSummary = _ =>
      if isOpen(details) && !isOpen(sheet) {
        details
        ->find("summary")
        ->Option.forEach(summary => ignore(sheet->dispatch(request("kit:modal-open", {detail: {dispatcher: summary}}))))
      }
    listen(sheet, "beforetoggle", discloseCase)
    listen(details, "toggle", openFromSummary)
    Some(() => {
      unlisten(sheet, "beforetoggle", discloseCase)
      unlisten(details, "toggle", openFromSummary)
    })
  | _ => None
  })

  let closeCase = () => switch (Nullable.toOption(caseRef.current), Nullable.toOption(sheetRef.current)) {
  | (Some(details), Some(sheet)) => Specimen_leave.after(sheet, () => details->disclose(false))
  | _ => ()
  }

  <>
    <p>
      <KitReact.Roles.KeyboardSheet.Opener
        sheet="shortcut-sheet"
        props={{id: "kit-keyboard-sheet-opener"}}>
        {React.string("Keyboard shortcuts")}
      </KitReact.Roles.KeyboardSheet.Opener>
    </p>
    <details ref={ReactDOM.Ref.domRef(caseRef)}>
      <summary>{React.string("Show the open keyboard sheet")}</summary>
      <KitReact.Roles.KeyboardSheet
        onClose=closeCase
        id="shortcut-sheet"
        props={{
          ref: ReactDOM.Ref.domRef(sheetRef),
          ariaLabelledby: "shortcut-sheet-title",
        }}
        heading={React.string("Keyboard shortcuts")}
        headingProps={{id: "shortcut-sheet-title"}}
        groups=[
          {
            heading: "Find and navigate",
            shortcuts: [
              {name: "Find", keys: ["/"]},
              {name: "Today", keys: ["t"]},
            ],
          },
          {
            heading: "Booking work",
            shortcuts: [
              {name: "New booking", keys: ["n"]},
              {name: "Keyboard sheet", keys: ["?"]},
            ],
          },
        ]
        close={{children: React.string("Close shortcuts"), props: {type_: "button"}}}
      />
    </details>
    <KitReact.Roles.KeyboardSheet
      id="role-keyboard-sheet-open-empty-region"
      props={{ariaLabelledby: "empty-region-shortcut-sheet-title"}}
      heading={React.string("Keyboard shortcuts")}
      headingProps={{id: "empty-region-shortcut-sheet-title"}}
      groups=[]
      close={{children: React.string("Close shortcuts"), props: {type_: "button"}}}
    />
    <p>{React.string("Help carries the link above except where the primary pointer is coarse, where the sheet and the link are both absent. The core composition is open and not modal; Phoenix’s controller and React’s showModal make it modal, on its Backdrop, and return focus.")}</p>
  </>
}

Keyboard sheet, inert

Show the keyboard sheet while it loads

Keyboard shortcuts

Find and navigate

  • Find/
  • Todayt

Close waits until the shortcuts have loaded.

Source
type event
type detail = {dispatcher: Dom.element}
type request = {detail: detail}
@send external listen: (Dom.element, string, event => unit) => unit = "addEventListener"
@send external unlisten: (Dom.element, string, event => unit) => unit = "removeEventListener"
@new external request: (string, request) => event = "CustomEvent"
@send external dispatch: (Dom.element, event) => bool = "dispatchEvent"
@send @return(nullable) external find: (Dom.element, string) => option<Dom.element> = "querySelector"
@get external isOpen: Dom.element => bool = "open"
@set external disclose: (Dom.element, bool) => unit = "open"

@react.component
let make = () => {
  let caseRef = React.useRef(Nullable.null)
  let sheetRef = React.useRef(Nullable.null)

  React.useEffect0(() => switch (Nullable.toOption(caseRef.current), Nullable.toOption(sheetRef.current)) {
  | (Some(details), Some(sheet)) =>
    let discloseCase = _ => details->disclose(true)
    let openFromSummary = _ =>
      if isOpen(details) && !isOpen(sheet) {
        details
        ->find("summary")
        ->Option.forEach(summary => ignore(sheet->dispatch(request("kit:modal-open", {detail: {dispatcher: summary}}))))
      }
    listen(sheet, "beforetoggle", discloseCase)
    listen(details, "toggle", openFromSummary)
    Some(() => {
      unlisten(sheet, "beforetoggle", discloseCase)
      unlisten(details, "toggle", openFromSummary)
    })
  | _ => None
  })

  let closeCase = () => switch (Nullable.toOption(caseRef.current), Nullable.toOption(sheetRef.current)) {
  | (Some(details), Some(sheet)) => Specimen_leave.after(sheet, () => details->disclose(false))
  | _ => ()
  }

  <details ref={ReactDOM.Ref.domRef(caseRef)}>
    <summary>{React.string("Show the keyboard sheet while it loads")}</summary>
    <KitReact.Roles.KeyboardSheet
      onClose=closeCase
      id="shortcut-sheet-inert"
      props={{
        ref: ReactDOM.Ref.domRef(sheetRef),
        ariaLabelledby: "shortcut-sheet-inert-title",
      }}
      heading={React.string("Keyboard shortcuts")}
      headingProps={{id: "shortcut-sheet-inert-title"}}
      groups=[
        {
          heading: "Find and navigate",
          shortcuts: [
            {name: "Find", keys: ["/"]},
            {name: "Today", keys: ["t"]},
          ],
        },
      ]
      close={{
        children: React.string("Close shortcuts"),
        state: Inert({id: "shortcut-sheet-inert-close", words: [KitReact.Words.Text("Close waits until the shortcuts have loaded.")]}),
        props: {type_: "button"},
      }}
    />
  </details>
}