feat(widgets): add LoadingDots widget#674
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds a new LoadingDots widget and tests: label + fixed-width cycling dots, tick-driven advancement with wrap at maxDots, Unicode/ASCII glyph selection, color support, and package exports. ChangesLoadingDots Widget Feature
Sequence Diagram(s)sequenceDiagram
participant Host
participant LoadingDots
participant Screen
Host->>LoadingDots: tick()
LoadingDots->>LoadingDots: update dot counter and mark dirty
Host->>LoadingDots: render(screen)
LoadingDots->>Screen: write label and padded dots
Screen->>Host: updated back buffer row
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🎉 Thanks for your first PR to TermUI, @realtushartyagi.
Before your PR merges:
- ⭐ Star the repo. Required. The
star-checkjob blocks your merge otherwise. - ✅ All checks green:
build,test,typecheck. - 🏷 PR title follows
type: short description. Example:fix: handle empty list. - 🔗 Link your closing issue in the description.
GSSoC 2026 points come from labels after merge:
gssoc:approved. +50 base points.level:beginner/intermediate/advanced/critical. +20 / +35 / +55 / +80.quality:clean/exceptional. x 1.2 / x 1.5.type:*. Stackable bonus.
Your reviewer responds within 48 hours. Ping @Karanjot786 on Discord for urgent help.
🚀 Welcome to the cohort.
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a new LoadingDots feedback widget to @termuijs/widgets and exposes it from the package entrypoint, along with a Vitest test suite.
Changes:
- Export
LoadingDotsandLoadingDotsOptionsfrom the widgets package index. - Implement
LoadingDotswidget with label + animated dot cycle and unicode/ASCII dot selection. - Add unit tests covering rendering, ticking behavior, label updates, and ASCII fallback.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| packages/widgets/src/index.ts | Exposes LoadingDots widget and its options via public package exports. |
| packages/widgets/src/feedback/LoadingDots.ts | Implements the LoadingDots widget rendering and tick/label update behavior. |
| packages/widgets/src/feedback/LoadingDots.test.ts | Adds Vitest coverage for rendering and unicode/ASCII behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| it('tick adds a dot', () => { | ||
| const screen = new Screen(20, 1); | ||
| const ld = new LoadingDots({}, { label: 'Thinking', maxDots: 3 }); | ||
| ld.updateRect({ x: 0, y: 0, width: 20, height: 1 }); | ||
| ld.tick(); | ||
| ld.render(screen); | ||
| const row = screen.back[0].map(c => c.char).join(''); | ||
| expect(row).toContain('Thinking· '); | ||
| }); |
| constructor(style: Partial<Style> = {}, opts: LoadingDotsOptions = {}) { | ||
| super({ height: 1, ...style }); | ||
| this._label = opts.label ?? ''; | ||
| this._maxDots = opts.maxDots ?? 3; |
| tick(): void { | ||
| this._dotCount = (this._dotCount + 1) % (this._maxDots + 1); | ||
| this.markDirty(); | ||
| } |
| const dots = dotChar.repeat(this._dotCount); | ||
| const padding = ' '.repeat(this._maxDots - this._dotCount); |
| if (this._label) { | ||
| screen.writeString(currentX, y, this._label, attrs); | ||
| currentX += this._label.length; | ||
| } |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/widgets/src/feedback/LoadingDots.ts`:
- Line 5: The _renderSelf method must early-return when height <= 0 and use
display-width-safe cursor advancement for the label: add a guard at the start of
_renderSelf to return when this.height <= 0, and replace any label cursor
increments that use label.length with a call to the core stringWidth utility
(import it from '`@termuijs/core`' alongside
Style/Color/Screen/caps/styleToCellAttrs) so the dot region stays aligned for
wide Unicode characters; update all occurrences (around the label advance logic
and the blocks noted) to use stringWidth(label) instead of .length.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: cabb8077-9d90-493d-a5fd-6ee584c49bc6
📒 Files selected for processing (3)
packages/widgets/src/feedback/LoadingDots.test.tspackages/widgets/src/feedback/LoadingDots.tspackages/widgets/src/index.ts
Review: Two fixes needed in LoadingDots1. Missing height guard (line 5 of _renderSelf): protected _renderSelf(screen: Screen): void {
const { x, y, width, height } = this._getContentRect();
if (width <= 0 || height <= 0) return;2. Use stringWidth for label cursor advancement: import { stringWidth } from '@termuijs/core';
// replace label.length with:
cursor += stringWidth(label);This prevents layout corruption when the label contains wide Unicode characters. |
16fdf8f to
27996ae
Compare
Description
Adds a LoadingDots widget for inline loading states. The component animates dots through tick(), maintains a fixed width to prevent layout shifts, and supports ASCII fallbacks when Unicode is unavailable.
Related Issue
Closes #479
Which package(s)?
@termuijs/widgets
Type of Change
type:bug)type:feature)type:docs)type:testing)type:refactor)type:design)type:accessibility)type:performance)type:devops)type:security)Checklist
needs-starcheck blocks your merge otherwise.bun vitest runbun run buildbun run typecheckCONTRIBUTING.md.type: short description.markDirty()(if your change affects rendering).anytypes without an inline comment explaining why.GSSoC 2026 Participation
https://gssoc.girlscript.org/profile/f49aa65e-aab2-4e9f-99d6-2174f339ecfeScreenshots / Recordings (UI changes)
N/A There is no UI changes
Notes for the Reviewer
Summary by CodeRabbit
New Features
Tests