Skip to content

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

@zrosenbauer

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions