Hone logo
Hone
Problems

Implement a Reusable Chip Component in React with TypeScript

This challenge requires you to build a versatile "Chip" component in React using TypeScript. Chips are commonly used in UI design to represent distinct pieces of information, such as tags, filters, or user avatars. A well-implemented chip component should be configurable, accessible, and visually appealing.

Problem Description

You need to create a React functional component named Chip that accepts various props to customize its appearance and behavior. The Chip component should be able to display text and optionally an icon. It should also support interactive states like hover and focus, and allow for an optional close button.

Key Requirements:

  1. Basic Rendering: The Chip component must render a div element that visually represents a chip.
  2. Text Content: It should accept a label prop (string) to display as the chip's text.
  3. Icon Support: An optional icon prop should be supported, which can accept a React node (e.g., an SVG component or an <img> tag) to be displayed before the label.
  4. Closable Chips: A closable prop (boolean) should determine if a close button (e.g., an 'x' icon) is rendered next to the label.
  5. On Close Handler: If closable is true, an onClose prop (function) must be provided. This function should be called when the close button is clicked.
  6. Styling: The component should have basic styling applied to make it look like a chip (e.g., rounded corners, padding). You can use CSS Modules, styled-components, or inline styles.
  7. Accessibility:
    • The chip should be focusable.
    • If closable, the close button should be a distinct interactive element with appropriate ARIA attributes.
  8. TypeScript: The component and its props must be defined using TypeScript for strong typing.

Expected Behavior:

  • A chip with only a label should render the text.
  • A chip with label and icon should render the icon followed by the text.
  • A chip with label and closable={true} should render the label and a close button.
  • Clicking the close button on a closable chip should trigger the onClose function.
  • The component should visually indicate hover and focus states.

Edge Cases to Consider:

  • What happens if closable is true but onClose is not provided? (Consider how to handle this, perhaps with a console warning or by disabling the close button).
  • Rendering an empty label.
  • Rendering a very long label (consider truncation or wrapping).

Examples

Example 1: Basic Chip

// Props passed to the Chip component
const chipProps = {
  label: "React Tag",
};

// Expected rendered output (conceptual, actual HTML structure might vary based on styling)
// <div class="chip">React Tag</div>

Explanation: A simple chip with only a text label.

Example 2: Chip with Icon

import { StarIcon } from './icons'; // Assuming you have an icon component

const chipProps = {
  label: "Featured",
  icon: <StarIcon />,
};

// Expected rendered output
// <div class="chip">
//   <span class="chip-icon"><StarIcon /></span>
//   <span class="chip-label">Featured</span>
// </div>

Explanation: A chip displaying an icon before its text label.

Example 3: Closable Chip

const handleClose = () => {
  console.log("Chip closed!");
};

const chipProps = {
  label: "Filter Option",
  closable: true,
  onClose: handleClose,
};

// Expected rendered output
// <div class="chip">
//   <span class="chip-label">Filter Option</span>
//   <button class="chip-close-button" aria-label="Close chip">
//     &times;
//   </button>
// </div>

Explanation: A chip with a label and a close button. Clicking the button calls the onClose handler.

Example 4: Chip with Icon and Close Button

import { UserIcon } from './icons';

const handleClose = () => {
  console.log("User chip closed!");
};

const chipProps = {
  label: "John Doe",
  icon: <UserIcon />,
  closable: true,
  onClose: handleClose,
};

// Expected rendered output
// <div class="chip">
//   <span class="chip-icon"><UserIcon /></span>
//   <span class="chip-label">John Doe</span>
//   <button class="chip-close-button" aria-label="Close chip">
//     &times;
//   </button>
// </div>

Explanation: A chip combining an icon, text, and a close button.

Constraints

  • The Chip component must be a React functional component.
  • All prop types must be explicitly defined using TypeScript interfaces.
  • The icon prop can accept any valid React.ReactNode.
  • The onClose prop should be a function that takes no arguments and returns void.
  • Focus should be managed such that when a closable chip is closed, focus can be shifted appropriately (e.g., to the next focusable element or back to the last active chip).
  • Avoid hardcoding styles directly within the component's JSX. Use a styling solution like CSS Modules, styled-components, or a dedicated CSS file.

Notes

  • Consider using a common pattern for icon components in React (e.g., passing SVG elements directly).
  • For styling, think about how to manage hover and focus states. Pseudo-classes in CSS are your friend here.
  • For accessibility, ensure the close button has a clear aria-label and is keyboard navigable.
  • Consider adding a className prop to allow for external styling overrides or additional custom classes.
  • Think about how the onClose event handler will be integrated into your application's state management. The component itself should only be responsible for calling the handler.
Loading editor...
typescript