GitbookIO / GitbookIO/gitbook

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

Open
#4,336 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
29k
Forks
4k
Avg merge
1d 2h
Merged PRs (30d)
71

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in the @gitbook/embed package at the GitBookFrameClient and createGitBookFrame event protocol, using the existing on('close', …) behavior as the reference. Trace how Escape is received inside the embed and forwarded to the host, then verify that an escape listener fires, its unsubscribe function works, and existing events remain unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.