Skip to content

@gitbook/embed: emit an "escape" event from the frame client #4336

Description

@oolaoluwatobi

Feature request: emit an escape event from the GitBook embed

Package: @gitbook/embed (observed on v0.5.1)
Area: GitBookFrameClient event protocol (createGitBookFrame)

Summary

Add a dedicated event — e.g. escape — that the embed emits when the user
presses Escape while focus is inside the embed, so the host page can decide
how to respond (typically: close the surrounding panel).

client.on('escape', () => {
  // host decides what to do, e.g. close its own panel
});

Why the host cannot do this today

We render the embed inside our own dismissible help panel. The embed is served
in a cross-origin iframe, which means:

  • Keystrokes that happen while focus is inside the iframe are handled by the
    embed and never reach the host page. A host-side keydown listener for
    Escape only fires while focus is still on the host (i.e. before the user
    interacts with the embed). Once the search/assistant input is focused,
    pressing Escape does nothing on our side.
  • We cannot reach into the iframe (contentDocument access is blocked) to
    observe or intercept the key.
  • postMessage is not an option because the embed only honors its own
    documented protocol.

So there is no host-side workaround for Escape across the cross-origin
boundary. This is unlike focus handling, where iframe.contentWindow.focus()
at least gives the iframe window focus.

Current protocol surface (for reference)

The frame client today exposes:

Member Purpose
navigateToPage command
navigateToAssistant command
postUserMessage command
clearChat command
configure command
on('close', …) event — fires when the built-in close button is clicked

There is an event for the close button, but nothing for Escape, and no
way for the host to learn that the user pressed it.

Requested behavior

When the user presses Escape while focus is inside the embed, emit an event the
host can subscribe to:

type GitBookFrameClient = {
  // ...existing members
  on(event: 'escape', listener: () => void): () => void;
};

The host stays in control of what happens (close, blur, ignore) — the embed only
needs to forward the intent.

Acceptance criteria

  • Pressing Escape while the embed (search or assistant input) is focused fires
    the escape event on the host's client.
  • The listener returned unsubscribe function works like the existing
    on('close', …) handler.
  • No change to existing events; this is purely additive.

Use case

A modal-style help panel (search-only, tabs: ['search']) opened from the app
sidebar. Escape should close the panel for keyboard users, consistent with other
modals in the app — including after the user has started typing in search, which
is exactly when the host can no longer see the key.

Notes / alternatives considered

  • Embed handles Escape internally and emits the existing close event.
    Acceptable, but less flexible — some hosts may want to clear input first, or
    not close at all. A dedicated escape event leaves the policy to the host.
  • A programmatic close() command (separate request) would let the host close
    the embed, but does not solve this issue on its own, because the host
    still never learns that Escape was pressed inside the iframe.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions