Question presented to candidate: "Our product page shows customer reviews, and some of them are several paragraphs long. Build a component that shows the first part of a long review with a Read more button, expands to the full text on click, and collapses again with Show less. Short reviews should just show in full, with no button."
Requirements:
- A reusable component that takes
textand amaxCharslimit (120 in the demo). - Collapsed: the text cut at a word boundary where possible, with an ellipsis; no broken emoji.
- A Read more / Show less button with the right ARIA state; no button at all when the text fits.
- Each instance keeps its own expanded state, so several reviews can be open independently.
What a strong answer should cover:
- State is one boolean per instance; the preview and "is it truncated" are derived from the props.
- Truncating by characters the user sees (grapheme clusters), not with
sliceon UTF-16 code units, and backing off to the last space. - A real
<button>witharia-expandedandaria-controls, and keeping focus on it when toggling. - The trade-off with CSS
-webkit-line-clamp: it clamps by rendered lines but needs layout measurement (scrollHeight > clientHeight) to decide whether to show the button. - Edge cases: text shorter than the limit, no spaces at all, text that changes after render.
Clarifying questions expected:
- "Is the limit in characters or in visible lines?"
- "Should screen reader and search engine users get the full text even when collapsed?"
- "Does the text ever contain markup, or is it plain text?"
Code / implementation expected: Yes. A component with derived truncation, a toggle button and a small demo list in the framework of your choice.