Keyboard sheet, open
Show the open keyboard sheet
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
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>
}