Skip to the solution
EasyFrontend13 min read

Build a Character Counter (textarea with limit)

919 views

The problem

Question presented to candidate: "We are adding a short status message box to our app, a bit like a post composer. Build a textarea that shows how many characters the user has typed out of a limit of 50, turns amber near the limit and red when they go over, and disables the Post button when the text is empty or too long. Then add an option that stops the user typing past the limit at all."

Requirements:

  • A labelled textarea with a live counter such as 42 / 50 ยท 8 left, or 3 over past the limit.
  • Three visual states: normal, warning (10 or fewer left) and over the limit.
  • A Post button that is disabled for empty, whitespace-only or over-limit text; posting clears the box.
  • A "Block typing past the limit" option that truncates input to the limit.
  • "Character" means what a person sees: an emoji with a skin tone or an accented letter counts as one.

What a strong answer should cover:

  • One piece of state (the text); the count, remaining, status and button state are derived, not stored.
  • Why string.length is wrong for emoji (it counts UTF-16 code units) and how Intl.Segmenter with grapheme granularity fixes it.
  • Why the native maxlength attribute is not a safe hard limit: it counts code units and can cut an emoji in half.
  • Soft limit (allow typing, show negative count) versus hard limit (truncate), and not truncating during IME composition.
  • Accessibility: aria-describedby linking the counter, aria-invalid when over, and a polite live region that speaks only when the state changes.

Clarifying questions expected:

  • "Is the limit about what users see, or about bytes or code units the backend stores?"
  • "Should we block typing at the limit, or let people go over and fix it before posting?"
  • "Do we need to support languages typed with an input method editor, such as Chinese or Japanese?"

Code / implementation expected: Yes. A working component with derived counter state, grapheme-aware counting and truncation, and a disabled submit, in the framework of your choice.

  • Forms
  • State
  • Accessibility

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

13 min read ยท 9 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import { useState } from "react";
import CharacterCounter from "./src/components/CharacterCounter";

export default function App() {
  const [posts, setPosts] = useState([]);
  return (
    <main className="app">
      <h1>Character counter</h1>
      <CharacterCounter
        limit={50}
        warnAt={10}
        onPost={(t) => setPosts((p) => [t, ...p])}
      />
      <ul className="posts" data-testid="posts">
        {posts.map((p, i) => (
          <li key={posts.length - i}>{p}</li>
        ))}
      </ul>
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 14 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextEasy

Build a Typewriter Effect

Continue