Skip to main content

CodeBooth

The @lqv/codebooth package provides a GUI for interactive coding tutorials. It is based on @lqv/codemirror, and you should use that directly if you need finer-grained control.

This package aims to be very flexible, accommodating a wide variety of use cases. We ship a set of components for you to build-your-own UI, as well as a set of presets demonstrating configuration for common use cases. The easiest way to get started is to clone one of the demos:

Language / LibraryLiqvidRemotionGSAP
HTMLDemoDemoDemo
PythonDemoDemoDemo
TSXDemoDemoDemo
danger

Currently, this package does not work in Strict Mode.

Exports

<Buttons>

Div to hold buttons.

<Clear>

Button for clearing the output/console.

<CodeBooth>

Container for code editing/recording/replaying.

Props

  • recorder?: CodeRecorder
    CodeMirror recorder.

<Console>

Component for displaying console logs.

<Copy>

Button for copying the contents of one buffer to another.

Props

  • from: string
    Source editor group.

  • to: string
    Target editor group.

<Editor>

CodeMirror editor.

Props

  • content?: string
    Initial content for editor.

  • editable?: boolean = true
    Whether the editor is editable or not.

  • extensions?: codemirror.Extension[]
    CodeMirror Extensions to use in the editor.

  • filename?: string
    Filename for the file being edited.

  • group?: string
    Group name for editor. You usually specify this on the parent EditorGroup instead.

<EditorGroup>

Holds a group of editors.

Props

  • id: string
    ID of this group.

<EditorPanel>

Tabpanel containing a single editor.

Props

  • filename: string
    Filename for the panel.

  • group?: string = "default"
    Group name for the panel. You usually specify this on the parent EditorGroup instead.

<FileTabs>

File selector component.

<Record>

Recording editor.

Props

This component extends Editor. In addition to those props, this accepts:

  • captureKeys?: Record<string, string> = {"Mod-Enter": run, "Mod-K": "clear", "Mod-L": "clear"}
    Special key sequences to include in recording.

  • passKeys?: string[] = ["Mod-Alt-2", "Mod-Alt-3", "Mod-Alt-4"]
    Key sequences to pass through to Keymap.

<Replay>

Editor to replay recorded coding.

Props

This component extends Editor. In addition to those props, this accepts:

  • handle?: (useStore, cmd, doc) => void
    Callback to handle special commands. Receives the following parameters:

    • useStore: Store
      The CodeBooth store.
    • cmd: string
      The command to handle.
    • doc: codemirror.Text
      The CodeMirror document.
  • replay?: CodeData | Promise<CodeData>
    Coding data to replay.

  • start?: number = 0
    Time to start replaying.

<ReplayMultiple>

Replay coding to multiple editors.

Props

  • group?: string
    Editor group to replay.

  • handle?: (useStore, key, string) => void
    Callback to handle special commands. Receives the following arguments:

    • useStore: Store
      The CodeBooth store.

    • cmd: string
      The command to handle.

    • docs: Record<string, codemirror.Text>
      CodeMirror documents.

  • replay: CodeData | Promise<CodeData>
    Coding data to replay.

  • start?: number = 0
    Time to start replaying.

<Resize>

Component for adjusting the vertical editor/console split.

<Run>

Button for running the code.

State

CodeBooth store state. Shape:

  • activeGroup: string
    Name of active editor group.

  • classNames: string[]
    Class names to attach to root.

  • groups: Record<string, {activeFile, files}>
    Group of files/editors. Shape:

    • activeFile: string
      Name of active file.

    • files: Record<string, {editable, filename, view}>
      Files contained in this editor group. Shape:

      • editable: boolean
        Whether the buffer can be edited by the viewer.

      • filename: string
        File name.

      • view: codemirror.EditorView
        Reference to CodeMirror EditorView.

  • messages: React.ReactChild[]
    Console logs.

  • recorder: CodeRecorder
    Code recorder.

  • run: number
    Used to broadcast run events.

  • getActiveFile(): {editable, filename, views}
    Get the active file.

  • getActiveView(): codemirror.EditorView
    Get the active view.

<Tab>

Group selection tab.

Props

<TabList>

Holds a list of Tabs.

useBoothStore()

Get a reference to the Zustand store for this CodeBooth. See State for store shape.

Presets

To reduce the need for configuration, we provide presets for a number of common language scenarios. These are not intended to be one-size-fits-all solutions; if you require further customization, the source for these presets will help you get started.

HTML

Preset for recording multifile HTML/CSS/JS demos. Import as @lqv/codebooth/html. Exports:

<HTMLPreview>

Preview of HTML document.

<HTMLRecord>

Record HTML demos. Props:

  • files: Record<string, string>
    Map of filenames to file contents.

<HTMLReplay>

Interactive HTML replay. Props:

  • files: Record<string, string>
    Map of filenames to file contents.

  • replay: ReplayData
    Coding data to replay.

  • start?: number = 0
    When replay should start.

extensionFromFilename()

Get CodeMirror Extension appropriate to filename extension.

Parameters
  • filename: string
    Name of file.
Return value

Either css(), html(), or javascript() from @codemirror/lang-*.

transform()

Inlines scripts and stylesheets in HTML code.

Parameters
  • html: string
    HTML code to transform

  • files: Record<string, string>
    Map of filenames to file contents.

Return value

Transformed HTML code.

Python

Preset for recording Python demos. Import as @lqv/codebooth/python. Uses the Skulpt interpreter. Exports:

<PythonRecord>

Record Python coding. Props:

  • content?: string
    File contents.

<PythonReplay>

Interactive Python replay. Props:

  • content?: string
    File contents.

<PythonRun>

Run Python code.