Skip to content

fix(tui): register the spinner element by value so the bundler keeps it - #225

Merged
nikomatt69 merged 1 commit into
live-mainfrom
fix/tui-spinner-registration
Aug 18, 2026
Merged

fix(tui): register the spinner element by value so the bundler keeps it#225
nikomatt69 merged 1 commit into
live-mainfrom
fix/tui-spinner-registration

Conversation

@SandroHub013

Copy link
Copy Markdown
Collaborator

Issue for this PR

Closes #224

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

spinner is not a built-in opentui element — it comes from opentui-spinner, which registers it by calling extend({ spinner }) when opentui-spinner/solid is evaluated. Both files that render <spinner> pulled it in with a bare import "opentui-spinner/solid", i.e. an import with no bindings, kept only for that side effect.

Bun's bundler drops that import. In a compiled binary the registration never runs, the component catalogue has no spinner, and the first createElement("spinner") throws [Reconciler] Unknown component type: spinner — which is the prompt's thinking indicator, so the TUI dies right after start. bun dev never showed it because nothing bundles there.

The fix imports the registerSpinner binding the package already exports and calls it. A binding that is called cannot be tree-shaken, so the registration survives the bundle. extend is Object.assign onto a module-level object, so calling it from both files is idempotent.

How did you verify your code works?

Built live-main (12c9fac, v1.292.0) twice on Windows and grepped the executable for a string that only exists inside opentui-spinner:

# without the patch
$ bun run --cwd packages/nikcli build:single
$ grep -c "Spinner interval must be a finite number" packages/nikcli/dist/nikcli-ai-windows-x64/bin/nikcli.exe
0

# with the patch
$ grep -c "Spinner interval must be a finite number" packages/nikcli/dist/nikcli-ai-windows-x64/bin/nikcli.exe
1

The patched binary starts into the TUI and the spinner animates; the unpatched one hits the fatal-error screen. bun run --cwd packages/tui typecheck is clean.

A reviewer can reproduce with the same two builds and that grep, no Windows needed — the import is dropped on every platform.

Screenshots / recordings

Not a UI change beyond the spinner rendering again; the crash screen is quoted in #224.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

`import "opentui-spinner/solid"` was there only for its side effect, the
`extend({ spinner })` call that puts `spinner` in the component catalogue.
Bun's bundler drops that import, so compiled binaries reach
`createElement("spinner")` with an empty catalogue entry and throw
`[Reconciler] Unknown component type: spinner` as soon as the prompt renders.

Import `registerSpinner` and call it instead: a called binding cannot be
tree-shaken. `extend` is `Object.assign` on a module-level object, so calling
it from both files that render `<spinner>` is idempotent.
@github-actions github-actions Bot added the size/XS PR touches 4 lines label Aug 18, 2026
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

import "opentui-spinner/solid"
import { registerSpinner } from "opentui-spinner/solid"

registerSpinner()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@nikomatt69 nikomatt69 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review (local verification, 2026-08-18)

This is the right fix for #224. opentui-spinner/solid already calls extend({ spinner }) on import and exports registerSpinner as that same function. A binding that is called cannot be tree-shaken, and a second extend is Object.assign so calling it from both spinner.tsx and prompt/index.tsx is idempotent.

Verified

  • CI typecheck passed
  • registerSpinner is exported from opentui-spinner@0.0.7 (dist/solid.d.mts / dist/solid.mjs) and is the same extend({ spinner }) the side-effect import used to rely on
  • No overlap with #227 / #233
  • Merges clean onto current live-main (fdf92f6bf6, no conflicts)

CI that is red is not this PR

  • test (windows): Bun remap crash (could not create process / exit 255) while running bun test:e2e:local — infrastructure, same class of failure on the other PRs
  • check-duplicates: Executable not found in $PATH: "nikcli" in script/duplicate-pr.ts — pre-existing
  • test (linux) has been queued for hours, not a test failure

Merge: yes. This is the compiled-TUI crash. Merge first of the three.

@nikomatt69
nikomatt69 merged commit fbfecf1 into live-main Aug 18, 2026
20 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XS PR touches 4 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TUI: compiled binaries crash with "Unknown component type: spinner"

2 participants