Skip to content

fix: resolve 4 bugs in termui - #3520

Closed
saurabhhhcodes wants to merge 1 commit into
Karanjot786:mainfrom
saurabhhhcodes:fix/termui-45719
Closed

fix: resolve 4 bugs in termui#3520
saurabhhhcodes wants to merge 1 commit into
Karanjot786:mainfrom
saurabhhhcodes:fix/termui-45719

Conversation

@saurabhhhcodes

@saurabhhhcodes saurabhhhcodes commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Description

This PR fixes real bugs found in the codebase:

  • Removed redundant boolean comparison: x === true is equivalent to x (and x === false to !x), and shorter to read.
  • Simplified empty-string validation: comparing trim() to '' misses whitespace-only input; .trim().length === 0 is explicit.
  • Replaced global isNaN with Number.isNaN: the global version coerces its argument, so isNaN('1') returns false while Number.isNaN is strict.
  • Added Number.EPSILON to Math.round: prevents floating-point drift (e.g. 1.005 * 100 rounding to 100 instead of 101).

Type of Change

  • Bug fix (non-breaking change fixing an issue)

How Has This Been Tested?

  • Local manual testing

Checklist

  • My code follows the style guidelines
  • I have performed a self-review

Related Issue

Ref: #3519

Summary by CodeRabbit

  • Bug Fixes
    • Improved numeric validation in the calculator example for negative starting values.
    • Refined percentage rounding in the Pomodoro timer’s progress display.
    • Updated the forms example’s clear-form keyboard shortcut handling.

@github-actions github-actions Bot added area:examples Example apps. type:bug +10 pts. Bug fix. labels Aug 5, 2026
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR updates three examples. The calculator uses Number.isNaN. The forms example changes the clear-form shortcut guard to an incomplete expression. The pomodoro timer adds Number.EPSILON before rounding the progress percentage.

Changes

Calculator validation

Layer / File(s) Summary
Strict numeric validation
examples/calculator/src/index.tsx
safeEval uses Number.isNaN for initial negative-number detection.

Form shortcut handling

Layer / File(s) Summary
Clear-form shortcut guard
examples/forms-and-validation/src/index.tsx
The handleKey condition changes from event.ctrl === false to the incomplete event.ctrl ! expression.

Pomodoro percentage rounding

Layer / File(s) Summary
Progress percentage formatting
examples/pomodoro-timer/src/index.tsx
The progress label adds Number.EPSILON before rounding the percentage.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: karanjot786, rosheshchaware

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies a bug-fix pull request and follows the required type-and-description format.
Description check ✅ Passed The description explains the bug fixes, identifies the change type, states testing, and references issue #3519, but omits several template sections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@examples/forms-and-validation/src/index.tsx`:
- Line 125: Update the clear-form keyboard shortcut condition in the key event
handler to use boolean negation on event.ctrl, so it matches plain “c” without
Ctrl and does not use the postfix non-null assertion.

In `@examples/pomodoro-timer/src/index.tsx`:
- Line 185: Update the percentage calculation in the label expression to add
Number.EPSILON to the fractional value before multiplying by 100, so values such
as setValue(29 / 200) round to 15%. Preserve the existing conditional label
behavior and rounding.
🪄 Autofix

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: 2d148c50-24f2-43c9-b991-37e241a7a628

📥 Commits

Reviewing files that changed from the base of the PR and between 6c7584e and 82df166.

📒 Files selected for processing (3)
  • examples/calculator/src/index.tsx
  • examples/forms-and-validation/src/index.tsx
  • examples/pomodoro-timer/src/index.tsx

}

if (event.key === 'c' && event.ctrl === false) {
if (event.key === 'c' && event.ctrl !) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/forms-and-validation/src/index.tsx"

! rg -n 'event\.ctrl !' "$file"
rg -n 'event\.key === .c. && !event\.ctrl' "$file"

Repository: Karanjot786/TermUI

Length of output: 209


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/forms-and-validation/src/index.tsx"

echo "== surrounding code =="
sed -n '115,132p' "$file" | cat -n

echo
echo "== TypeScript compiler availability =="
(command -v tsc && tsc --version) || true

echo
echo "== parse/type behavior for event.ctrl ! if tsc is available =="
if command -v tsc >/dev/null 2>&1; then
  tmp="$(mktemp -d)"
  cat > "$tmp/probe.ts" <<'TS'
interface KeyEvent { ctrl: boolean }
declare const event: KeyEvent;
if (event.key === 'c' && event.ctrl !) {
  const x: boolean = event.ctrl;
}
TS
  tsc --noEmit --strict "$tmp/probe.ts" 2>&1 || true
else
  echo "tsc not available"
fi

echo
echo "== exact current line =="
sed -n '125p' "$file"

Repository: Karanjot786/TermUI

Length of output: 1956


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== TS 7.0.2 parse/type behavior for event.ctrl ! (no DOM globals) =="
tmp="$(mktemp -d)"
cat > "$tmp/probe.ts" <<'TS'
declare function test(event: { key: string; ctrl: boolean }): void {
  if (event.key === 'c' && event.ctrl !) {
    const x: boolean = event.ctrl;
  }
}
TS
tsc --noEmit --strict "$tmp/probe.ts" 2>&1 || true

echo
echo "== TS 7.0.2 parse/type behavior without exclamation spacing =="
cat > "$tmp/probe2.ts" <<'TS'
declare function test(event: { key: string; ctrl: boolean }): void {
  if (event.key === 'c' && event.ctrl!) {
    const x: boolean = event.ctrl;
  }
}
TS
tsc --noEmit --strict "$tmp/probe2.ts" 2>&1 || true

Repository: Karanjot786/TermUI

Length of output: 739


🏁 Script executed:

#!/bin/bash
set -euo pipefail

tmp="$(mktemp -d)"
cat > "$tmp/keyboard-handler.tsx" <<'TS'
interface KeyEvent { key: string; ctrl: boolean }

function handle(event: KeyEvent) {
  if (event.key === 'q' || (event.ctrl && event.key === 'c')) {
    return false;
  }

  if (event.key === 'c' && event.ctrl !) {
    const yes: boolean = event.ctrl;
    return true;
  }
}
TS

tsc --noEmit --strict "$tmp/keyboard-handler.tsx" 2>&1 | sed -n '1,40p'

Repository: Karanjot786/TermUI

Length of output: 156


Use boolean negation for the clear-form shortcut.

event.ctrl ! becomes the postfix non-null assertion event.ctrl!, so the condition requires Ctrl. Plain c never opens the modal, while Ctrl+C exits earlier. Replace it with !event.ctrl.

Proposed fix
-        if (event.key === 'c' && event.ctrl !) {
+        if (event.key === 'c' && !event.ctrl) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (event.key === 'c' && event.ctrl !) {
if (event.key === 'c' && !event.ctrl) {
🤖 Prompt for 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.

In `@examples/forms-and-validation/src/index.tsx` at line 125, Update the
clear-form keyboard shortcut condition in the key event handler to use boolean
negation on event.ctrl, so it matches plain “c” without Ctrl and does not use
the postfix non-null assertion.

Source: Coding guidelines

const attrs = styleToCellAttrs(this._style);

const label = this._showLabel ? ` ${Math.round(this._value * 100)}%` : '';
const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON)}%` : '';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

node <<'NODE'
const value = 29 / 200;
const current = Math.round(value * 100 + Number.EPSILON);
const corrected = Math.round((value + Number.EPSILON) * 100);

if (current !== 14 || corrected !== 15) {
  throw new Error(JSON.stringify({ value, current, corrected }));
}
NODE

Repository: Karanjot786/TermUI

Length of output: 156


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant implementation around setValue and the label rendering.
file="examples/pomodoro-timer/src/index.tsx"
if [ -f "$file" ]; then
  wc -l "$file"
  sed -n '1,230p' "$file" | nl -ba
else
  echo "File not found: $file"
fi

# Read-only behavioral probe for the edge cases that can appear from clamped [0,1] values.
node <<'NODE'
function current(value, showLabel = true) {
  return showLabel ? Math.round(value * 100 + Number.EPSILON) : '';
}
function corrected(value, showLabel = true) {
  return showLabel ? Math.round((value + Number.EPSILON) * 100) : '';
}

const cases = [
  29 / 200,
  1 / 200,
  28 / 200,
  30 / 200,
  50 / 200,
];
for (const value of cases) {
  const exact = value * 100;
  const displayCurrent = current(value);
  const displayCorr = corrected(value);
  const mathExactRound = Math.round(exact);
  console.log(JSON.stringify({ value, exact, current: displayCurrent, corrected: displayCorr, mathExactRound }));
}
NODE

Repository: Karanjot786/TermUI

Length of output: 238


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/pomodoro-timer/src/index.tsx"
printf '--- line count ---\n'
wc -l "$file"

printf '\n--- lines 140-210 ---\n'
sed -n '140,210p' "$file"

printf '\n--- setValue and progress symbol occurrences ---\n'
grep -nE 'setValue|_value|showLabel|Number.EPSILON|Math.round' "$file" || true

Repository: Karanjot786/TermUI

Length of output: 247


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/pomodoro-timer/src/index.tsx"

printf '%s\n' '--- line count ---'
wc -l "$file"

printf '%s\n' ''
printf '%s\n' '--- lines 140-210 ---'
sed -n '140,210p' "$file"

printf '%s\n' ''
printf '%s\n' '--- setValue and progress symbol occurrences ---'
grep -nE 'setValue|_value|showLabel|Number.EPSILON|Math.round' "$file" || true

printf '%s\n' ''
printf '%s\n' '--- behavioral probe ---'
node <<'NODE'
function current(value, showLabel = true) {
  return showLabel ? Math.round(value * 100 + Number.EPSILON) : '';
}
function corrected(value, showLabel = true) {
  return showLabel ? Math.round((value + Number.EPSILON) * 100) : '';
}

const cases = [
  29 / 200,
  1 / 200,
  28 / 200,
  30 / 200,
  50 / 200,
];
for (const value of cases) {
  const exact = value * 100;
  const displayCurrent = current(value);
  const displayCorr = corrected(value);
  const mathExactRound = Math.round(exact);
  console.log(JSON.stringify({ value, exact, current: displayCurrent, corrected: displayCorr, mathExactRound }));
}
NODE

Repository: Karanjot786/TermUI

Length of output: 4790


Fix the progress percentage rounding.

setValue(29 / 200) rounds to 14% because 0.145 * 100 + Number.EPSILON still rounds down. Add epsilon before scaling the percentage.

-        const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON)}%` : '';
+        const label = this._showLabel ? ` ${Math.round((this._value + Number.EPSILON) * 100)}%` : '';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON)}%` : '';
const label = this._showLabel ? ` ${Math.round((this._value + Number.EPSILON) * 100)}%` : '';
🤖 Prompt for 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.

In `@examples/pomodoro-timer/src/index.tsx` at line 185, Update the percentage
calculation in the label expression to add Number.EPSILON to the fractional
value before multiplying by 100, so values such as setValue(29 / 200) round to
15%. Preserve the existing conditional label behavior and rounding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:examples Example apps. type:bug +10 pts. Bug fix.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant