This project implements the "Toggle Button" component from the provided Figma design as part of an application for the Design System Engineer role at Investec.
links
- Figma Design: Link to Figma file
- Live Demo: Link to Chromatic
- Framework: Next.js was chosen for its performance optimizations, server-side rendering capabilities, and strong typing support with TypeScript. These features are beneficial for building scalable and maintainable design systems.
- Component Design: The
ToggleSwitch
component is designed for reusability and theming. It accepts props to control its state and appearance, allowing for easy integration within a larger design system. - TypeScript: TypeScript ensures type safety and improves code maintainability.
- Accessibility: The component adheres to accessibility best practices, including keyboard navigation and ARIA attributes, to ensure it is usable by everyone.
The ToggleSwitch component is a customizable UI element that provides a toggleable switch control with various styling and functionality options.
role="switch"
: Identifies the component as a toggle switcharia-checked
: Reflects the current statearia-label
: Provides accessible namearia-describedby
: Links to description elementaria-controls
: Indicates what element this switch controls
- Added onKeyDown handler for Enter and Space keys
- Proper tabIndex management
- Disabled elements are removed from tab order (tabIndex={-1})
- Default tabIndex={0} for enabled elements
This component includes comprehensive documentation covering:
- Basic usage
- Available props
- Different variants and options
- Clone the repository:
git clone [repository URL]
- Install dependencies:
yarn install
- Start the development server:
yarn dev
- View the component in Storybook:
yarn storybook
// Simplified example of the component
function ToggleSwitch(props: ToggleSwitchProps): React.ReactElement {
return (
<button
className={getToggleClasses(options, isChecked ?? false) + " " + toggleClasses.outerSize[options.size ?? "sm"]}
onClick={handleClick}
disabled={options.disabled}
>
{(options.iconOnly || options.leadingIcon) && renderIcon()}
{!options.iconOnly && (
<span className={[
toggleClasses.innerSize[options.size ?? "sm"],
options.leadingIcon && "ml-2",
options.trailingIcon && "mr-2",
].filter(Boolean).join(" ")}>
{options.label}
</span>
)}
{options.trailingIcon && renderIcon()}
</button>
);
}
<div className="flex flex-row gap-8 row-start-2 items-center sm:items-center">
<ToggleSwitch iconOnly />
<ToggleSwitch label="Create" trailingIcon isChevron size="sm" />
<ToggleSwitch label="Filter" trailingIcon isChevron size="md" />
<ToggleSwitch label="Export" trailingIcon isChevron size="lg" />
<ToggleSwitch label="Sort" leadingIcon isChevron disabled={true} />
<ToggleSwitch
appearance="subtle"
label="Subtle"
trailingIcon
isChevron
/>
</div>
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
npm run storybook
# or
yarn storybook
# or
pnpm storybook
# or
bun storybook