A reusable React component that displays a list of books with features for managing book descriptions and adding new books.
- Reusable BookItem Component: Displays book title, description, and optional image
- Toggle Description: Show/hide book descriptions with a toggle button
- Add New Books: Dynamically add new books to the list via a form
- Data Persistence: Automatically saves books to browser localStorage
- Error Handling: Gracefully handles invalid image URLs with placeholder images
- Accessibility: WCAG-compliant with proper ARIA attributes and keyboard navigation
- Responsive Design: Works on desktop and mobile devices
- TypeScript: Fully typed for better developer experience
- Testing: Comprehensive test coverage using Jest and React Testing Library
src/
├── components/
│ ├── BookItem/
│ │ ├── BookItem.tsx
│ │ ├── BookItem.css
│ │ └── __tests__/
│ │ └── BookItem.test.tsx
│ ├── BookList/
│ │ ├── BookList.tsx
│ │ ├── BookList.css
│ │ └── __tests__/
│ │ └── BookList.test.tsx
│ └── BookForm/
│ ├── BookForm.tsx
│ ├── BookForm.css
│ └── __tests__/
│ └── BookForm.test.tsx
├── hooks/
│ ├── useLocalStorage.ts
│ └── __tests__/
│ └── useLocalStorage.test.ts
├── types/
│ └── book.ts
├── test/
│ └── setup.ts
├── App.tsx
├── App.css
└── main.tsx
- Node.js (v18 or higher)
- npm or yarn
- Install dependencies:
npm installRun the development server:
npm run devThe application will be available at http://localhost:3000
Build for production:
npm run buildRun tests:
npm testRun tests in watch mode:
npm run test:watchRun tests with coverage:
npm run test:coverageThe BookItem component accepts a book prop with the following structure:
interface Book {
id: string;
title: string;
description?: string;
imageUrl?: string;
}Example usage:
import { BookItem } from './components/BookItem/BookItem';
const book = {
id: '1',
title: 'Example Book',
description: 'This is an example description',
imageUrl: 'https://example.com/image.jpg'
};
<BookItem book={book} />The BookList component manages a list of books and provides functionality to add new books:
import { BookList } from './components/BookList/BookList';
<BookList />- Each book item has a toggle button to show/hide the description
- The button state is managed using React's
useStatehook - Proper ARIA attributes for accessibility
- Displays book cover images when provided
- Falls back to a placeholder image if no image URL is provided
- Handles image load errors gracefully
- Fill out the form with book details (title is required, description and image URL are optional)
- Clicking "Add Book" adds a new book to the top of the list
- New books are automatically assigned unique IDs
- The list updates immediately without page refresh
- All books are automatically saved to browser localStorage
- Books persist across page refreshes and browser sessions
- The next book ID is also persisted to ensure unique IDs
- If localStorage is unavailable or corrupted, the app falls back to initial books
The component follows WCAG 2.1 guidelines:
- Semantic HTML elements (
<article>,<header>,<main>) - ARIA labels and roles where appropriate
- Keyboard navigation support
- Focus indicators for interactive elements
- Screen reader friendly text and descriptions
The component includes comprehensive tests covering:
- Component rendering
- Description toggle functionality
- Image error handling
- Add new book functionality
- Accessibility attributes
- React 18: UI library
- TypeScript: Type safety
- Vite: Build tool and dev server
- Jest: Testing framework
- React Testing Library: Component testing utilities
- CSS3: Styling with modern features
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
This project is created for demonstration purposes.