Using the PlayerReader Interface

Reader Interface

What readers see and can do in the PanelWave Player — viewport, toolbar controls, navigation, autoplay, modals, keyboard and touch input.

This page describes the player from the reader's point of view: every visible control and input method, as implemented in the shell, viewport, and toolbar components.

Layout

The player fills its host container with three UI layers:

  1. Viewport (pw-viewport) — renders the current panel (panel view) or the current page with all its placed panels (page view), including image/video/text layers and speech bubbles. Works with an infinite-canvas chapter render on the canvas stage instead.
  2. Toolbar (pw-toolbar) — a bottom bar with all reader controls, from the release after 1.2.0 a solid bar with a clear top edge. Hidden by default unless the integrator sets [showToolbar]="true".
  3. Modals and overlays — table of contents, settings, language picker, character roster, extras viewer, branch chooser, share modal, comments drawer, paywall and age gate, and a thumbnail strip.

While the toolbar is hidden, a floating button in the bottom-right corner lets readers bring it back — it shows the PanelWave icon from the player release after 1.2.0 (a hamburger icon before). Clicking anywhere on the viewport also shows the toolbar temporarily — it auto-hides again after 5 seconds.

The player fills whatever container the embedding application gives it. From the release after 1.2.0 the toolbar's Fullscreen button shows it fullscreen (browser Fullscreen API) and returns to the browser view; where the browser has no fullscreen (iPhone Safari) the button is hidden.

Page background

From the release after 1.2.0 the page's background color — visual.background_color, else the work's default_page_bg_color, else dark gray #1a1a1a — fills the space between the panels in page view and the space around the page. In panel view it frames the panel: the color of the page the panel belongs to, so when page 1 is white and page 2 black, the frame turns black with the first panel of page 2. The page runs edge to edge, without an inset border.

Panel view

Panel view shows one panel at a time and follows the chapter's graph:

  • Next follows the outgoing edge of the current panel. When several edges match, their JSON Logic conditions are evaluated against the current variables and the highest-priority valid edge wins — this is how branching narratives resolve.
  • Previous follows an incoming edge back.
  • An edge (or a hotspot jump) into another chapter continues in that chapter: from the release after 1.2.0 the player switches to the target's chapter, so the next Next goes on from there (1.2.0 kept the old chapter and showed the new chapter's entry panel again). A panel with no outgoing edge ends its chapter, and reading continues with the next chapter.
  • A chapter without any edges (allowed from format 1.7) is read in its reading order: the entry panel, then the remaining panels in the order the chapter lists them. From the player release after 1.2.0, next and previous follow that order (1.2.0 stopped on the entry panel).
  • Hovering the left/right edge of the viewport reveals navigation arrow zones (chevron icons); panels larger than the viewport additionally show overflow arrows for panning.
  • From the release after 1.2.0, double-clicking the panel returns to page view, on the page that holds it.

Page view

If the manifest defines page layouts, the View toolbar button toggles between panel view and page view. From the release after 1.2.0 a work opens in page view (after the cover); hosts can start in panel view with initialViewMode. Page view renders all panels of a page in their placed positions; next/previous then move page by page, and the current panel follows the page's reading order.

From the release after 1.2.0:

  • Hovering the left/right edge shows the same navigation arrows as in panel view; they turn the page.
  • Double-clicking a panel opens it large in panel view.
  • Video panels on a page play one after another in reading order (see video sequencing behavior). Image panels between two videos pause the sequence for their display duration (the CMS timeline's durationMs, else the reader's autoplay seconds), so the art gets read before the next video starts: video A (3 s), image B (2 s), image C (4 s), video D (6 s) plays A, waits 6 s, then plays D. Image panels before the first video delay it; image panels after the last one delay the autoplay page turn.
  • Hovering a video that is not playing (waiting for its turn, or finished) plays it while the pointer rests on it. Clicking a video that is not playing plays it, in page and panel view.

From the player release after 1.2.0, page view also adapts to the screen:

  • One page sequence per screen. A work authored for several output formats carries one page sequence per format. The player shows the one that suits the screen — mobile-portrait on a phone, tablet-portrait on a portrait tablet, a wide format on a desktop, bigscreen-landscape on a 4K display — and picks again when the window is resized or the device rotated, re-opening the page that shows the current panel. The host can force a format with the pageFormat input.
  • The page fills the screen in its format's aspect ratio (1.2.0 used a fixed 16:9 box of at most 1400 px for every format). On a phone (narrower than 768 px) the page is fitted to the panels it shows, so they use the full width without dark margins.
  • Lettering scales with the page, as in the editor, so balloons keep their place on the artwork on every screen. Text never renders below 9 px: a balloon that would get smaller re-wraps to fit its panel instead.
  • Paging crosses chapters: next on a chapter's last page opens the next chapter's first page, previous on its first page the previous chapter's last page.
  • Thumbnails and table-of-contents entries open the page that shows the panel.

Choices in page view

A page shows every panel placed on it — in a branching story that can include the outcome of an option the reader did not pick, or of a choice still ahead. From the release after 1.2.0 page view shows only the reader's path:

  • Before a choice is made, the panels that only some of its options lead to (up to where the branches meet again) are grey placeholders in their place on the page, so the layout keeps its shape.
  • Picking an option reveals its path. Panels that only the other options lead to stay grey.
  • Turning pages skips pages made up only of panels off the chosen path, in both directions and across chapters, so the reader lands on a page with a panel of their path. The last page on the path ends the work. A page of a choice not made yet is not skipped: it shows its placeholders until the reader chooses.

A choice here is a panel whose hotspots jump to two or more different panels; a single "continue" hotspot is not one. Panels picked by a condition on an edge — a variant panel, an ending reached through a stat check — are not affected. Placeholders show no artwork, speech bubbles or hotspots, are skipped by screen readers and the keyboard, and take no time in autoplay. The reader's choices last for the reading session; panel view and canvas view are unaffected (they follow the graph).

Cover

From the player release after 1.2.0, a work that starts from the beginning opens on its cover — meta.cover, else the image of the work's cover extras block. Clicking the cover, next, a swipe or autoplay starts the story; previous on the first panel (or page) goes back to it. The cover is the first entry of the thumbnail strip and the table of contents. From the release after 1.2.0 a work always starts on the cover, also when reading resumes at a bookmark (the bookmarked page waits behind it); leaving the cover opens page view. It is skipped when the reader follows a link to a page or panel (see below) or the host opens a specific chapter or panel, and the host can turn it off with the showCover input.

From the release after 1.2.0 every page and every panel has its own address in the public reader, so readers can bookmark and share exactly what they see:

AddressOpens
…/team/workThe cover, then page view
…/team/work?page=pg-D3That page in page view
…/team/work?panel=ch1-p022That panel in panel view

The address bar follows the reader while they read (without adding a browser history entry per panel). A page link opened on a screen with another page format (a desktop link on a phone) opens the page that shows the same panels. The Share dialog offers this link; its QR code is drawn in the browser. Embedders get the same behavior with the locationChange output.

Interactive hotspots

Panels can carry hotspots — clickable regions the creator drew in the CMS. In panel and page view they render as invisible click targets with a gentle pulsing outline so readers can discover them (the pulse is disabled under reduced motion); hovering or focusing a hotspot shows its outline. From the release after 1.2.0, a hotspot can show its label as a button instead — set by the hotspot's display (button; area keeps the invisible target). With the default auto, the hotspots of a choice (their goTo actions lead to two or more panels) are buttons, so readers see the options even when the artwork does not paint them. Activating a hotspot runs its action:

  • Navigate (goTo) — jumps to the target panel, applying any variable changes and playing the configured transition. This is how in-panel story choices work. The target may be in another chapter (from the release after 1.2.0 the player then continues in that chapter); in page view the jump also reveals the chosen path (Choices in page view).
  • Set variables — changes story state in place (conditional hotspots, edges, and variants react immediately).
  • Open extras — opens the extras viewer at a specific bonus item.
  • Open modal — shows a small dialog with localized title and text.
  • Plugin event — hands the interaction to an embedded plugin.

Hotspots are keyboard-accessible: Tab moves between them, Enter/Space activates, and each announces its localized label (or ariaLabel) to screen readers. Clicks on a hotspot never double as tap-to-advance.

In canvas view the hotspots of the current panel are interactive in the same way (click, tap and keyboard, tracked like in panel view); hotspots on the other panels visible on the canvas are drawn but inert, so tapping a neighbouring panel keeps its navigation meaning.

Branch choices

When at least two paths lead on from the current panel — outgoing edges whose conditions pass right now — the toolbar shows a Choices button. A panel with several edges of which only one is open shows no button. The button opens the branch chooser, which lists exactly those open paths — labelled with the edge's label, else the target panel's title, else a translated "Option 1", "Option 2", … Picking one follows that edge exactly as a normal navigation would: its transition (or camera move in canvas view) plays and its action mutations are applied. The choice is tracked as branch_choice.

Next still resolves the graph on its own (highest-priority valid edge), so the chooser is an additional way to pick a path, not a required step. From the release after 1.2.0 one case differs: when at least two open paths carry an authored label — a decision the author wants the reader to make — Next opens the chooser instead of picking a path, and in page view, turning past a page with a decision the reader has not made yet does the same.

Input methods

InputAction
→ (Arrow Right)Next panel (or next page in page view)
← (Arrow Left)Previous panel (or previous page in page view)
TToggle toolbar
EscClose the open dialog; with no dialog open, hide the toolbar
Click / tap viewportShow toolbar temporarily (5 s)
Double-click a panel (page view)Open it in panel view (from the release after 1.2.0)
Double-click (panel view)Back to page view (from the release after 1.2.0)
Swipe leftNavigate forward
Swipe rightNavigate backward

Keyboard shortcuts are ignored while typing in an input field, text area or select. Enter/Space activate the focused viewport element for keyboard users. Canvas view adds O (overview) and +/- (zoom) — see Canvas View.

While a dialog is open (table of contents, settings, language, characters, extras, branch chooser, share, comments, or a hotspot's modal), the story behind it does not react: Escape closes the topmost dialog, and arrow keys and T are ignored until it is closed. The paywall and the age gate block the story completely: while either is open, arrow keys, T and swipes do nothing. Each keeps its own Escape — it dismisses the paywall (like Maybe later) and closes the age gate — and a dismissed gate leaves the reader on the panel they were on.

Toolbar controls

From left to right (labels are translatable UI strings; icons are Lucide glyphs):

ControlBehavior
ViewToggle page/panel view. Disabled when the manifest defines no pages.
Language (globe)Opens the language modal. Only shown when the work has more than one language: meta.locales plus, from the release after 1.2.0, every language the work's speech bubbles and text layers are translated into and the active languages of the localization block.
FullscreenFrom the release after 1.2.0. Shows the player in fullscreen; in fullscreen the button returns to the browser view (Esc does too). Hidden where the browser has no fullscreen (iPhone Safari).
SpeechToggle speech bubbles on/off. Seeded from settings.ui.speechDefault; hides all bubbles implicitly (schema 1.3) — no per-bubble visibleIf boilerplate involved. Off also mutes the voiceover bus (spoken lines belong to the bubbles they voice).
AudioMaster mute for the whole player: every audio-engine bus (ambient, music, voiceover, sfx) and video sound. Seeded from settings.ui.audioDefault. While off, video layers stay muted and show no unmute affordance.
SFXMute/unmute the sfx bus (which also carries ui sounds); the rest of the mix is untouched. Seeded from settings.ui.sfxDefault.
AutoplayStart/stop automatic advancing. While active, the button shows a progress bar and −/+ controls to adjust the seconds-per-panel (0.5–120 s in 1-s steps). From the player release after 1.2.0 the value is tagged Author while the creator's timing plays; after the reader picks a speed, an Author button switches back to it (see Autoplay).
ThumbsToggle the thumbnail strip (jump to any panel by its thumbnail).
ToCOpen the table of contents (chapters, pages and panels; selecting one navigates there).
SettingsOpen the settings modal.
CharactersOpen the character roster built from meta.characters in the manifest.
AltCycle alternative panels — only shown when alternatives exist.
ChoicesOpen the branch chooser — only shown when the current panel has more than one outgoing edge.
ExtrasOpen the extras viewer (covers, character sheets, bonus art — see Extras).
LikeLike / unlike the work (see below). Highlighted while liked.
BookmarkSet a bookmark on the current panel, or clear it when you're on the bookmarked panel. Highlighted on the bookmarked panel.
Share / CommentsShare opens the share modal (native share sheet where available, else copy link); Comments opens the comments drawer. From the release after 1.2.0 the shared link points at what the reader sees (?page= in page view, ?panel= in panel view) and the QR code is drawn in the browser.
Made with PanelWave / ?From the release after 1.2.0. PanelWave links to panelwave.org; the help icon opens this documentation.
✕Close the toolbar.

The three sound toggles (Speech, Audio, SFX) share one rule for their initial state: a preference the reader set explicitly — from the toolbar or the settings modal, in this or an earlier session (persisted in localStorage under pw-preferences) — wins; otherwise the work's settings.ui.speechDefault / audioDefault / sfxDefault applies (default: on). Mutes and volumes are independent in the engine, so toggling never loses a stored level. Each toggle emits an audio_toggle / sfx_toggle / speech_toggle tracking event with { enabled }. What the toggles act on — the panel's manifest audio, started and stopped by the shell — is described in Audio.

All toolbar labels, tooltips and the comments drawer's timestamps are translated; English and German ship with the package.

Like and bookmark

Both are stored on the reader's device, per work (localStorage key pw-social, keyed by the manifest's meta.id), so they work without accounts:

  • Like toggles; the state is restored the next time the work opens.
  • Bookmark marks the current panel. Pressing it again on the same panel clears it; pressing it on another panel moves it there. The next time the work opens without an explicit start position from the host, reading resumes at the bookmark.

Each toggle is tracked (like, bookmark events, subject to consent and the manifest's whitelist) and emitted to the host as likeChange / bookmarkChange, so a platform with accounts can mirror them server-side. See Inputs & Outputs.

Autoplay

Readers start and stop autoplay from the toolbar or Settings. The host can also start a work in autoplay with the autoplay input; the reader's toggle takes over from there.

Autoplay advances automatically using, in order of precedence:

  1. the current panel's own durationMs from the manifest (the timing the creator set on the CMS timeline),
  2. otherwise the reader-adjustable seconds per panel (default 5 s).

From the player release after 1.2.0:

  • The reader's speed wins once chosen. The toolbar marks the creator's timing with an Author tag. Picking a speed with −/+ switches to the reader's seconds per panel for every panel, including those with a durationMs; the Author button switches back.
  • Page view keeps a page up for the sum of its panels' times (1.2.0 used the current panel's time only).
  • The cover stays for the seconds per panel, then the story starts.
  • Autoplay stops at the end of the work (its last panel, or last page in page view).
  • Video panels no longer stall autoplay: in 1.2.0 the panel after a video was sometimes selected but not painted, so it showed late or not at all.

From the player release after 1.2.0, autoplay also waits for a panel's animation in panel and canvas view: the panel stays at least as long as a non-looping layer or viewport animation runs, so a shorter dwell time no longer cuts it off. Looping animations, reduced motion and page view keep the plain dwell time.

Autoplay is video-aware: when the current panel contains videos that start on view, the player waits for each video to complete one full pass (media-event driven) instead of running a wall-clock timer — buffering can never cut a video short. A stall watchdog force-advances if a video source never finishes (and emits a videoEnded tracking event with reason stall-skip). In page view with on-view videos, the page advances when the whole video sequence completes.

Settings modal

The settings modal (pw-settings-modal) has two tabs:

  • Preferences — speech bubbles, audio, SFX, autoplay and seconds-per-panel, manga mode (right-to-left reading), reduced motion, high contrast. Includes a reset-to-defaults action. Speech, audio, SFX, autoplay and seconds-per-panel go through the same code paths as the toolbar controls (and are persisted like them). Reduced motion takes effect immediately (see Accessibility). Manga mode and high contrast are persisted but not applied yet.
  • Variables — shows the work's variables whose definition has visibility: "public", with type-appropriate editors (checkbox for booleans, number input with min/max, select for enums, text otherwise) and per-variable reset. This lets readers change story-affecting switches the creator exposed.

The modal edits a working copy: changes apply on Save; Cancel, a backdrop click or Esc discards them, and reopening the modal always starts from the saved values.

Modals and overlays

  • Table of Contents (pw-toc-overlay) — chapter/panel navigation. From the player release after 1.2.0 it starts with the cover, shows each panel's artwork as a small thumbnail (none for locked panels), and in a work with pages lists only the pages of the format on screen (1.2.0 listed every format's pages).
  • Language modal (pw-language-modal) — pick from the work's languages (see the toolbar's Language control); switching updates content and player UI immediately (Localization).
  • Character roster (pw-character-roster) — characters with portrait and description from the manifest.
  • Extras viewer (pw-extras-viewer) — the work's extras with their real media: image galleries (with thumbnails), videos (with their poster), audio tracks, and PDFs or text documents (opened with an Open document link); text-only extras render as text. A filter by type (including Other) narrows the list. An openExtras hotspot opens it directly at the targeted item. A block locked by an extras paywall rule is shown with a lock and does not open until the reader has the entitlement. From the player release after 1.2.0, an extra that carries only a direct url (as CMS exports do) shows that image as its thumbnail.
  • Action modal (pw-action-modal) — the small localized dialog an openModal hotspot shows.
  • Branch chooser (pw-branch-chooser) — the paths open from the current panel; see Branch choices.
  • Thumbnail strip (pw-thumbnail-strip) — quick visual navigation; it scrolls to the current panel when shown and follows along as you read. From the player release after 1.2.0 it shows each panel's artwork (a small rendition from the asset catalog) in reading order, starts with the cover, separates chapters with a title card (clicking one opens the chapter's first panel), and marks locked panels with a lock instead of their artwork. In page view, the current page's panels are highlighted.
  • Share modal and comments drawer — social features (surface only; persistence is up to the host application).
  • Paywall overlay and age gate — shown when the reader reaches content the work's paywall rules lock for them. The paywall offers the rule's Buy / Subscribe options plus Sign in and Maybe later, and hands the choice to the host app; the age gate asks for a birth date and, once passed, continues where the reader was going and doesn't ask again on that device. From the player release after 1.2.0, a locked panel shows a lock placeholder ("This panel is part of the full edition.") wherever it would appear — also on a page next to readable panels, and as the first panel when a work or chapter starts behind a gate. In page view the placeholder is a button ("Unlock this panel"; click, Enter or Space) that opens the age gate or the paywall for that panel; a page with age-locked panels asks for the age once when you turn to it. See Paywall & Entitlement.
  • Loading & error states — the shell shows a spinner while the manifest loads and an error screen with a retry button if loading or validation fails.

Accessibility

  • Every toolbar button carries a translated aria-label; toggles expose aria-pressed.
  • The viewport is a labelled region with keyboard activation (Enter/Space); page-view panels are focusable buttons with visible focus indicators.
  • Reduced motion is on when any of three sources asks for it: the operating system (prefers-reduced-motion, followed live while reading), the reader's Reduced motion switch in Settings, or the host's [reducedMotion] input. It makes panel/page transitions and canvas camera glides instant, stops the hotspot pulse, and degrades on-view video autostart to click-to-play. From the release after 1.2.0 it also shows layer keyframe animations and viewport moves at their end state instead of playing them.
  • Small screens (from the release after 1.2.0): in panel view a panel larger than the screen is cropped around its minimalFocusRect (of the format closest to the screen's shape) rather than around its centre, so the important part of the artwork stays visible. See Panels.
  • Every dialog closes with Esc and a backdrop click, and keeps keyboard input away from the story behind it.
  • The current panel's artwork loads first, at high priority, so the page is readable as early as possible (see Performance).
  • An automated accessibility sweep (axe) runs over every dialog, overlay and view mode in the player's test suite.