React Button Component with Variants
This challenge focuses on building a reusable React button component that supports different visual styles (variants) through props. Creating such a component is a common task in UI development, promoting code reusability and maintainability by centralizing button styling and behavior. You'll be using TypeScript to ensure type safety and improve code clarity.
Problem Description
You are tasked with creating a Button component in React using TypeScript. This component should accept the following props:
children: The content to be displayed inside the button (e.g., text, icons).variant: A string representing the button's visual style. Supported variants are:"primary","secondary", and"outline". The default variant should be"primary".onClick: A function to be executed when the button is clicked.disabled: A boolean indicating whether the button is disabled. Defaults tofalse.className: (Optional) A string of CSS class names to apply to the button.
The component should render a <button> element with appropriate styling based on the variant prop. The styling should include different background colors, text colors, and border styles for each variant. When disabled is true, the button should be visually disabled (e.g., grayed out) and prevent clicks. The className prop should be applied to the button element.
Expected Behavior:
- The component should render a button element.
- The button's appearance (background color, text color, border) should change based on the
variantprop. - The
onClickfunction should be called when the button is clicked (unless disabled). - The button should be visually disabled when the
disabledprop is true. - The
classNameprop should be correctly applied. - If no variant is provided, the button should default to the "primary" variant.
Edge Cases to Consider:
- Invalid
variantprop values (handle gracefully, defaulting to "primary"). childrenprop containing React elements or other components.onClickprop being null or undefined (should not cause errors).classNameprop being null or undefined (should not cause errors).
Examples
Example 1:
Input: <Button variant="primary" onClick={() => alert("Primary Button Clicked")}>Click Me</Button>
Output: A button with a blue background, white text, and no border, displaying "Click Me" and triggering an alert on click.
Explanation: The button uses the "primary" variant, applying the default styling.
Example 2:
Input: <Button variant="secondary" disabled>Secondary Button</Button>
Output: A button with a gray background, white text, and no border, displaying "Secondary Button", and appearing disabled (grayed out) and unresponsive to clicks.
Explanation: The button uses the "secondary" variant and is disabled.
Example 3:
Input: <Button className="my-custom-button" onClick={() => console.log("Custom Button Clicked")}>Custom Button</Button>
Output: A button with the "primary" variant styling (default), displaying "Custom Button", triggering a console log on click, and having the CSS class "my-custom-button" applied.
Explanation: The button uses the default "primary" variant and includes a custom CSS class.
Constraints
- The component must be written in TypeScript.
- The styling should be implemented using CSS (either inline styles or a CSS file/module). Avoid using CSS-in-JS libraries for this challenge.
- The component should be reusable and maintainable.
- The component should handle invalid
variantvalues gracefully. - The component should not introduce any unnecessary dependencies.
- The component should be performant and not cause any rendering issues.
Notes
- Consider using a CSS module or a separate CSS file to manage the button styles.
- Think about how to make the component extensible to support additional variants in the future.
- Focus on creating a clean and well-structured component with clear prop types.
- You can use any React and TypeScript best practices you are familiar with.
- The styling is not the primary focus; the core requirement is the functional component with variant handling.