Hone logo
Hone
Problems

React Icon Button Component

This challenge focuses on building a reusable IconButton component in React using TypeScript. Icon buttons are common UI elements that use an icon instead of text to represent an action. This is particularly useful for saving space and providing a visually intuitive user experience.

Problem Description

Your task is to create a functional and accessible IconButton component. This component should accept an icon element (or a string representing an icon name) and an onClick handler. It should also support standard button attributes and accessibility features.

Key Requirements:

  1. Component Structure: Create a React functional component named IconButton.
  2. Icon Rendering: The component must be able to render an icon. This could be achieved by accepting a React element (e.g., <FaBeer />) or a string that your application's icon library can interpret. For this challenge, assume you will receive a React.ReactNode for the icon.
  3. Click Handler: The component must accept an onClick prop of type () => void which will be triggered when the button is clicked.
  4. Standard Button Attributes: The IconButton should forward any other standard HTML button attributes (e.g., disabled, aria-label, title, className) to the underlying <button> element.
  5. Accessibility:
    • Ensure the button is focusable and can be activated via keyboard (e.g., pressing Enter or Space).
    • If an aria-label is not provided, the component should attempt to infer one if a title is present, or indicate that an accessible label is recommended. For this challenge, we will explicitly require an aria-label for accessibility.
  6. Styling: The component should be easily stylable, either through a className prop or by allowing inline styles. For this challenge, prioritize the className prop for external styling.

Expected Behavior:

  • When the IconButton is rendered with an icon and an onClick handler, clicking the button should execute the provided onClick function.
  • The button should visually indicate its interactive state (e.g., hover, focus, active).
  • When the disabled attribute is passed, the button should be visually disabled and not trigger the onClick handler.

Edge Cases to Consider:

  • What happens if no icon is provided? (The component should still render as a button, perhaps with a placeholder or an error). For this challenge, assume an icon will always be provided.
  • What happens if the onClick handler is not provided? (The button should still be renderable but not interactive).
  • Ensuring proper ARIA attributes for screen reader users.

Examples

Example 1: Basic Icon Button

// Assuming you have an icon component like this (simplified)
const MyIcon = () => <span>ICON</span>;

// In your application:
<IconButton icon={<MyIcon />} onClick={() => alert('Clicked!')} aria-label="Close" />

Output: A button element visually displaying MyIcon and having the accessible label "Close". Clicking it triggers an alert.

Explanation: The IconButton component renders a <button> element. It places the provided icon React node inside the button and attaches the onClick handler and aria-label.

Example 2: Disabled Icon Button

// Assuming you have an icon component like this (simplified)
const MyDisabledIcon = () => <span>DISABLED ICON</span>;

// In your application:
<IconButton icon={<MyDisabledIcon />} onClick={() => alert('This should not fire!')} aria-label="Settings" disabled />

Output: A button element visually displaying MyDisabledIcon with the accessible label "Settings". The button is visually distinct as disabled and does not respond to clicks.

Explanation: The disabled prop is passed to the underlying <button> element, preventing interaction and providing visual feedback.

Example 3: Button with Additional ClassName

// Assuming you have an icon component like this (simplified)
const MyStyledIcon = () => <span>STYLED ICON</span>;

// In your application:
<IconButton icon={<MyStyledIcon />} onClick={() => console.log('Styled clicked')} aria-label="Favorite" className="my-custom-icon-button" />

Output: A button element with the my-custom-icon-button class applied, displaying MyStyledIcon and having the accessible label "Favorite".

Explanation: The className prop is added to the <button> element, allowing for custom styling via CSS.

Constraints

  • The IconButton component must be implemented using React and TypeScript.
  • The icon prop must be of type React.ReactNode.
  • The onClick prop must be of type () => void.
  • The aria-label prop is mandatory for accessibility and must be a string.
  • The disabled prop must be a boolean.
  • The component should be designed for reusability and minimal styling opinions out-of-the-box, relying on className for customization.

Notes

  • Consider how you will forward arbitrary HTML attributes to the underlying <button> element. The ...rest operator is a common pattern for this.
  • Think about the best way to structure your component's props.
  • For accessibility, aria-label is crucial. Ensure it's always present when the button doesn't contain visible text.
  • You might want to add a default type="button" to the underlying button element to prevent accidental form submissions if used within a form.
Loading editor...
typescript