A React button component for the Isolate UI library. This is a presentational component built with React 19 and TypeScript.
libs/react/button/
├── src/
│ ├── index.ts # Public API exports
│ └── lib/
│ ├── button.tsx # Button component
│ ├── button.spec.tsx # Component tests
│ └── button.module.css # Component styles
├── vite.config.mts # Vite + Vitest configuration
├── tsconfig.json # TypeScript config
├── tsconfig.lib.json # Build config
├── tsconfig.spec.json # Test config
└── package.json
# Run tests for this component
nx test react-button
# Run tests in watch mode
nx test react-button --watch
# Run tests with UI
nx test react-button --ui
# Run tests with coverage
nx test react-button --coverage# Build the component library
nx build react-button
# Build outputs to: dist/libs/react/button/Test the component in isolation with Storybook:
# Start Storybook dev server (http://localhost:6006)
nx storybook react-button
# Build Storybook for static deployment
nx build-storybook react-button
# Output: dist/storybook/react-button/# Lint the component
nx lint react-button
# Lint with auto-fix
nx lint react-button --fix# Publish to npm (CI)
nx release publishTo publish to a local Verdaccio instance for testing, add the following to .npmrc before running:
@isolate-ui:registry=http://localhost:4873Remove the .npmrc entry before committing or publishing to npm.
interface ButtonProps extends HTMLAttributes<HTMLButtonElement> {
// Extends all standard HTML button attributes
}import { Button } from '@isolate-ui/button';
function App() {
return <Button onClick={() => console.log('clicked')}>Click me</Button>;
}vite.config.mts is configured with:
- React plugin: JSX transformation and Fast Refresh
- TypeScript: Type declarations generated via
vite-plugin-dts - Build format: ESM (ES modules)
- Externals: React and React DOM are not bundled
Test configuration in vite.config.mts:
- Environment:
jsdom(simulates browser environment) - Globals:
true- no need to importdescribe,it,expect - Test pattern:
{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx} - Coverage: Reports to
../../../coverage/libs/react/button
- Strict mode: Enabled for type safety
- JSX: React 19 JSX transform
- Path mappings: Import as
@isolate-ui/button - React types: Includes
@types/reactand@types/react-dom
-
Update the component:
// src/lib/button.tsx export interface ButtonProps extends HTMLAttributes<HTMLButtonElement> { variant?: 'primary' | 'secondary'; } export function Button({ variant = 'primary', children, ...props }: ButtonProps) { return ( <button className={variant} {...props}> {children} </button> ); }
-
Update tests:
// src/lib/button.spec.tsx describe('Button', () => { it('should render with primary variant', () => { const { getByRole } = render(<Button variant="primary">Click</Button>); expect(getByRole('button')).toHaveClass('primary'); }); });
-
Run tests:
nx test react-button
The component uses CSS modules for styling:
/* src/lib/button.module.css */
.button {
padding: 8px 16px;
border-radius: 4px;
}
.primary {
background: blue;
color: white;
}// src/lib/button.tsx
import styles from './button.module.css';
export function Button({ children, ...props }: ButtonProps) {
return (
<button className={styles.button} {...props}>
{children}
</button>
);
}- ✅ Render tests: Verify component renders correctly
- ✅ Prop tests: Test different prop combinations
- ✅ Event tests: Test click handlers and other events
- ✅ Accessibility: Test ARIA attributes and keyboard navigation
- ✅ Snapshot tests: Optionally use snapshots for complex markup
Tests use @testing-library/react:
import { render, fireEvent } from '@testing-library/react';
import Button from './button';
describe('Button', () => {
it('should call onClick when clicked', () => {
const handleClick = vi.fn();
const { getByRole } = render(<Button onClick={handleClick}>Click</Button>);
fireEvent.click(getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});The component requires these in consuming applications:
react: ^19.0.0react-dom: ^19.0.0
Can depend on other workspace libraries:
import { utils } from '@isolate-ui/utils';The build creates:
- ESM bundle:
dist/libs/react/button/index.js - Type declarations:
dist/libs/react/button/index.d.ts - Source maps: For debugging
# In a consuming app
pnpm add @isolate-ui/buttonimport { Button } from '@isolate-ui/button';
function App() {
return <Button>Hello World</Button>;
}Tests and builds are automatically run:
- On every commit (via Nx affected)
- In pull requests
- Before releases
Make sure environment: 'jsdom' is set in the test config
Ensure React version matches across all packages (use pnpm's peer dependency resolution)
Check that the component is exported from src/index.ts
Run nx typecheck react-button to see all type errors
- Root AGENTS.md - Overall project setup
- React Documentation
- Vitest Documentation
- Testing Library
- Nx React Plugin
Last updated: March 4, 2026