React Switch Component
Develop a reusable and accessible switch component in React using TypeScript. This component will allow users to toggle between two states, similar to a light switch, providing a clear visual indicator of its current state. This is a fundamental UI element found in many applications for settings, preferences, and more.
Problem Description
Your task is to create a functional React component named Switch. This component should visually represent a toggle switch that can be in either an "on" or "off" state.
Key Requirements:
- State Management: The component should internally manage its "on" or "off" state.
- Prop for Initial State: Accept a prop
initialState(boolean) to set the initial state of the switch. - Prop for State Change Callback: Accept a prop
onToggle(function) that is called whenever the switch's state changes, passing the new state (boolean) as an argument. - Visual Representation:
- The switch should have a distinct visual appearance for both the "on" and "off" states.
- It should be clickable to toggle between states.
- Accessibility:
- The component should be keyboard navigable and operable (e.g., togglable using the Space key).
- It should have appropriate ARIA attributes (e.g.,
role,aria-checked) to be understood by assistive technologies.
- Styling: The component should be stylable. You can achieve this by allowing CSS classes to be passed in or by using a CSS-in-JS solution. For this challenge, assume basic styling will be applied externally or via a default stylesheet.
Expected Behavior:
- When the component mounts, it should reflect the
initialState. - Clicking or activating the switch with the Space key should toggle its state.
- When the state changes, the
onTogglecallback function should be invoked with the new state.
Edge Cases:
- What happens if
initialStateis not provided? (Assumefalseby default). - What happens if
onToggleis not provided? (The component should still function internally, but the callback won't be executed).
Examples
Example 1:
// App.tsx
import React, { useState } from 'react';
import Switch from './Switch'; // Assuming Switch component is in './Switch'
function App() {
const [isEnabled, setIsEnabled] = useState(false);
const handleToggle = (newState: boolean) => {
setIsEnabled(newState);
console.log(`Switch is now: ${newState}`);
};
return (
<div>
<h1>My App Settings</h1>
<Switch initialState={isEnabled} onToggle={handleToggle} />
<p>Current Setting: {isEnabled ? 'Enabled' : 'Disabled'}</p>
</div>
);
}
export default App;
Output (when initially rendered):
The Switch component will be displayed in its "off" state. The console will log "Switch is now: true" when the switch is clicked. The text "Current Setting: Enabled" will be displayed.
Explanation:
The App component initializes its isEnabled state to false. This is passed as initialState to the Switch component. The handleToggle function is provided to onToggle. When the switch is clicked, handleToggle is called with true, isEnabled updates to true, and the paragraph text changes.
Example 2:
// App.tsx
import React from 'react';
import Switch from './Switch';
function App() {
return (
<div>
<h2>Another Feature</h2>
<Switch initialState={true} onToggle={(isOn) => console.log(`Feature toggled: ${isOn}`)} />
</div>
);
}
export default App;
Output (when initially rendered):
The Switch component will be displayed in its "on" state. The console will log "Feature toggled: false" when the switch is clicked.
Explanation:
Here, initialState is true, so the switch starts in the "on" position. The onToggle prop is an inline arrow function that logs the new state.
Example 3: Default Behavior
// App.tsx
import React from 'react';
import Switch from './Switch';
function App() {
return (
<div>
<h3>Default Switch</h3>
<Switch onToggle={(isOn) => console.log(`Default switch state: ${isOn}`)} />
</div>
);
}
export default App;
Output (when initially rendered):
The Switch component will be displayed in its "off" state (default initialState is false). The console will log "Default switch state: true" when the switch is clicked.
Explanation:
This example shows the default behavior when initialState is omitted. The switch defaults to false and the onToggle callback is executed as expected.
Constraints
- The component must be implemented in React using TypeScript.
- The
Switchcomponent should acceptinitialStateandonToggleas props. - The
onToggleprop should be an optional function. - Focus management for keyboard interaction must be handled correctly.
- Basic CSS should be sufficient for visual representation; complex styling frameworks are not required for the core logic.
Notes
- Consider using
useStatehook for internal state management. - Pay attention to ARIA roles and properties like
aria-checked,role="switch", and potentiallyaria-labelledbyif you decide to add a label (though a label is not strictly required for this challenge). - Think about how to attach event listeners for both click and keyboard events.
- The visual representation can be achieved with simple CSS (e.g., a div with background colors, borders, and a pseudo-element or child div for the slider).