Skip to content

feat: allow screen() fullscreen option to accept props for FullScreen component #164

Description

@zrosenbauer

Description

The screen() helper accepts fullscreen: true to wrap the rendered component in <FullScreen>, but there's no way to pass props (like hideCursor) through to the underlying <FullScreen> component.

This forces consumers into one of two bad patterns:

  1. Double wrapping — Set fullscreen: true AND render <FullScreen hideCursor> internally. This writes \x1B[?1049h (enter alt screen buffer) twice, causing terminal-dependent rendering bugs (blank screen on some terminals, content only visible in scrollback after quit).

  2. Manual management — Set fullscreen: false and handle <FullScreen> internally, bypassing the framework's cleanup logic in the finally block.

Proposed API

fullscreen should accept boolean | FullScreenProps with discriminated typing:

// Simple toggle (current behavior)
screen({ fullscreen: true })
screen({ fullscreen: false })

// Object form — enables fullscreen with props forwarded to <FullScreen>
screen({ fullscreen: { hideCursor: true } })

The type should be a clean discriminated union:

type ScreenFullscreen = boolean | FullScreenProps

interface FullScreenProps {
  readonly hideCursor?: boolean
  // future props go here
}

When fullscreen is an object (truthy), it's treated as enabled and the object is spread as props onto <FullScreen>. When false, disabled. When true, enabled with defaults (current behavior, no breaking change).

Additionally, hideCursor should also be available as a root-level option on screen() as a convenience shorthand — both forms should work:

// Root-level shorthand
screen({ fullscreen: true, hideCursor: true })

// Object form (takes precedence if both specified)
screen({ fullscreen: { hideCursor: true } })

Current behavior

In render-BsTEEL-N.js, screen() wraps with a bare <FullScreen>:

jsx(FullScreen, { children: jsx(ScreenComponent, { ...ctx.args }) })

No props are forwarded.

Additional Context

Discovered while debugging a jog init blank screen issue in @joggr/cli — the init command had fullscreen: true in its screen config AND <FullScreen hideCursor> in the component, causing double alt-screen-buffer entry. Fix was to remove the internal <FullScreen> and accept losing hideCursor.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or improvement

    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