Skip to content

feat(bio-editor): live word counter with target/warning/error zones#197

Merged
JohnRDOrazio merged 1 commit into
mainfrom
feat/bio-editor-word-counter
Jun 7, 2026
Merged

feat(bio-editor): live word counter with target/warning/error zones#197
JohnRDOrazio merged 1 commit into
mainfrom
feat/bio-editor-word-counter

Conversation

@JohnRDOrazio

Copy link
Copy Markdown
Member

Summary

  • Bios should land around 80 words. Add a live word counter below the editor so the author can target the right length without guessing.
  • Color zones: red for <60 or >100, orange for 60–69 or 91–100, green for 70–90. The 70/90 boundaries belong to green so those numbers read as "good", not "borderline".
  • ICU-plural i18n key (wordCount) so locales pick singular vs plural correctly. Seeded translations for it / es / fr / pt / de — Weblate will refine.

Test plan

  • npm run lint — clean.
  • npm run build — clean.
  • All 6 message files parse as valid JSON.
  • Manual smoke on /my-bio:
    • Open the editor, type → counter updates live.
    • Cross each boundary (59→60, 69→70, 90→91, 100→101) and confirm color flips.
    • Switch languages → counter resyncs to the loaded content (the setContent({ emitUpdate: false }) path).

Notes

  • countWords() is a plain whitespace split — fine for our 6 European languages. CJK / Arabic would need Intl.Segmenter, deferred until those locales actually exist.
  • aria-live="polite" on the count span so screen readers announce changes without yanking focus.
  • Frontend-only change — no theme/REST bundle, so this is a staging-only deploy concern (gh workflow run deploy.yml defaults to staging is fine; -f environment=production to ship to prod).

🤖 Generated with Claude Code

Bios should land around 80 words. Show the author live feedback as
they type so they can target the right length without guessing or
re-saving to see translation behaviour.

Color zones (boundaries inclusive on the green side):

  count                  zone     colour
  ─────────────────────  ──────   ──────
  count < 60              red     text-red-700
  60 ≤ count < 70         orange  text-orange-600
  70 ≤ count ≤ 90         green   text-green-700
  90 < count ≤ 100        orange  text-orange-600
  count > 100             red     text-red-700

Implementation:

* countWords() is a plain whitespace split — sufficient for the 6
  European languages we support. CJK / Arabic would need
  Intl.Segmenter, deferred until those locales actually exist.
* wordCountZone() returns 'green' | 'orange' | 'red' for the styling.
* Targets are file-level consts (BIO_TARGET_MIN/MAX,
  BIO_WARNING_MIN/MAX) so tweaks land in one place.
* Sync the count on three events: onCreate (initial paint),
  onUpdate (live edits), and after the language-switch
  setContent({ emitUpdate: false }) call which deliberately
  suppresses onUpdate to avoid flipping isDirty.
* aria-live="polite" on the count span so a screen reader announces
  the new count without yanking focus.

i18n: wordCount uses ICU plural so each locale can pick singular
vs plural correctly (no awkward "1 words"). wordCountTarget shows
the green-zone bounds verbatim ("target 70-90 words"). Seeded
translations for it/es/fr/pt/de; Weblate will refine.

Test plan: no automated coverage (component is purely visual);
manual smoke is opening /my-bio, typing into the editor, and
watching the counter live-update through the colour zones.
@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@JohnRDOrazio, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 5 minutes and 26 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2861fcc6-9f0d-4069-b6ba-05429eec31ca

📥 Commits

Reviewing files that changed from the base of the PR and between cedbc2f and 5791113.

📒 Files selected for processing (7)
  • components/BioEditor.tsx
  • messages/de.json
  • messages/en.json
  • messages/es.json
  • messages/fr.json
  • messages/it.json
  • messages/pt.json
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/bio-editor-word-counter

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 and usage tips.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 9 complexity · 0 duplication

Metric Results
Complexity 9
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@JohnRDOrazio JohnRDOrazio merged commit b08d5c3 into main Jun 7, 2026
11 checks passed
@JohnRDOrazio JohnRDOrazio deleted the feat/bio-editor-word-counter branch June 7, 2026 14:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant