@asafarim/paginated-project-grid
Version:
A responsive React component for displaying paginated project cards with built-in search functionality
308 lines (253 loc) • 8.87 kB
Markdown
A responsive React component for displaying paginated project cards with built-in search functionality.
- 📱 **Responsive Design**: Adapts to different screen sizes
- 🔍 **Built-in Search**: Collapsible search with customizable fields
- 📄 **Pagination**: Traditional pagination or load-more functionality
- 🎨 **Theme Support**: Light/dark themes with CSS variables (dark theme default)
- 🚀 **TypeScript**: Full TypeScript support with type definitions
- 📦 **CSS Modules**: Scoped CSS with no external dependencies
- ⚛️ **React 17/18**: Compatible with modern React versions
- 🏷️ **Enhanced Tags**: Support for interactive tags with navigation and click handlers
- 📊 **Project Management**: Support for priority, budget, progress tracking, and due dates
## Installation
```bash
npm install @asafarim/paginated-project-grid
```
**Note**: This package requires `@asafarim/project-card` as a peer dependency.
## Usage
```tsx
import { PaginatedProjectGrid } from '@asafarim/paginated-project-grid';
const projects = [
{
id: '1',
title: 'E-commerce Platform',
description: 'A full-stack e-commerce solution with React and Node.js',
image: '/images/ecommerce.jpg',
techStacks: [
{ name: 'React', color: '#61dafb', icon: '⚛️' },
{ name: 'Node.js', color: '#339933', icon: '🟢' },
{ name: 'MongoDB', color: '#47A248', icon: '🍃' }
],
links: [
{ type: 'demo', url: 'https://demo.example.com' },
{ type: 'repo', url: 'https://github.com/user/repo' }
],
tags: [
{ name: 'Fullstack', onClick: () => alert('Fullstack') },
{ name: 'Ecommerce', onClick: () => alert('Ecommerce') }
],
category: 'web-development',
status: 'active',
featured: true,
priority: 'high',
budget: 15000,
progress: 75,
dateCreated: '2024-01-15',
dueDate: '2024-06-15',
lastUpdated: '2024-01-15',
isPublic: true
},
// ... more projects
];
function ProjectShowcase() {
return (
<PaginatedProjectGrid
projects={projects}
cardsPerPage={6}
currentTheme="dark"
enableSearch={true}
showTechStackIcons={true}
onProjectClick={(project) => {
console.log('Clicked project:', project.title);
}}
/>
);
}
```
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `projects` | `Project[]` | - | **Required**. Array of project objects |
| `cardsPerPage` | `number` | `6` | Number of cards to display per page |
| `currentTheme` | `'light' \| 'dark' \| 'auto'` | `'dark'` | Theme for the grid |
| `className` | `string` | `''` | Additional CSS classes |
| `onProjectClick` | `(project: Project) => void` | - | Click handler for project cards |
| `showTechStackIcons` | `boolean` | `false` | Show icons in tech stack tags |
| `maxDescriptionLength` | `number` | `150` | Maximum description length |
| `enableSearch` | `boolean` | `true` | Enable search functionality |
| `searchPlaceholder` | `string` | `"Search projects..."` | Search input placeholder |
| `noResultsMessage` | `string` | `"No projects found..."` | Message when no results |
| `loadingMessage` | `string` | `"Loading projects..."` | Loading state message |
| `isLoading` | `boolean` | `false` | Show loading state |
| `searchFields` | `Array` | `['title', 'description', 'techStacks', 'tags']` | Fields to search in |
| `responsive` | `object` | `{mobile: 1, tablet: 2, desktop: 3, largeDesktop: 4, extraLargeDesktop: 5}` | Responsive breakpoints |
| `showLoadMore` | `boolean` | `false` | Use load more instead of pagination |
| `loadMoreText` | `string` | `"Load More"` | Load more button text |
| `animationDuration` | `number` | `300` | Animation duration in ms |
```tsx
interface Project {
id: string;
title: string;
description: string;
image?: string | ProjectImage;
techStacks: TechStackItem[]; // Required - from @asafarim/project-card
links: ProjectLink[]; // Required - from @asafarim/project-card
tags?: ProjectTag[]; // Enhanced tags with navigation and click handlers
category?: string;
status?: 'active' | 'archived' | 'in-progress' | 'completed' | 'draft' | 'coming-soon' | 'planning';
featured?: boolean;
priority?: 'low' | 'medium' | 'high' | 'critical';
budget?: number;
progress?: number; // Progress percentage (0-100)
dateCreated?: string; // ISO date string
dueDate?: string; // ISO date string
lastUpdated?: string; // ISO date string
isPublic?: boolean; // Public/private project flag
currentTheme?: Theme; // Individual project theme override
}
// ProjectTag interface for enhanced tag functionality
interface ProjectTag {
name: string;
navigateTo?: string; // URL to navigate to when tag is clicked
onClick?: () => void; // Function to execute when tag is clicked
}
// Import types from @asafarim/project-card
import type { TechStackItem, ProjectLink, Theme, ProjectImage } from '@asafarim/project-card';
```
The component now supports interactive tags with navigation and click handlers:
```tsx
const projects = [
{
// ... other properties
tags: [
{ name: 'React', navigateTo: 'https://reactjs.org' },
{ name: 'TypeScript', navigateTo: 'https://typescriptlang.org' },
{ name: 'Custom Action', onClick: () => alert('Custom action!') }
]
}
];
```
- `low`: Low priority projects
- `medium`: Medium priority projects
- `high`: High priority projects
- `critical`: Critical priority projects
- `active`: Currently active projects
- `archived`: Archived projects
- `in-progress`: Projects in development
- `completed`: Finished projects
- `draft`: Draft projects
- `coming-soon`: Upcoming projects
- `planning`: Projects in planning phase
Track project completion with a progress percentage (0-100):
```tsx
{
progress: 75, // 75% complete
// ... other properties
}
```
The component includes a collapsible search feature that can search across multiple fields:
- **title**: Project title
- **description**: Project description
- **techStacks**: Technology names
- **tags**: Project tags
- **category**: Project category
```tsx
<PaginatedProjectGrid
projects={projects}
enableSearch={true}
searchFields={['title', 'techStacks', 'tags']}
searchPlaceholder="Search by title, tech, or tags..."
/>
```
The grid automatically adapts to different screen sizes:
- **Mobile**: 1 column
- **Tablet**: 2 columns
- **Desktop**: 3 columns
- **Large Desktop**: 4 columns
- **Extra Large Desktop**: 5 columns
You can customize this behavior:
```tsx
<PaginatedProjectGrid
projects={projects}
responsive={{
mobile: 1,
tablet: 2,
desktop: 4,
largeDesktop: 5,
extraLargeDesktop: 6
}}
/>
```
The component supports light and dark themes with dark theme as default:
```tsx
// Dark theme (default)
<PaginatedProjectGrid
projects={projects}
currentTheme="dark"
/>
// Light theme
<PaginatedProjectGrid
projects={projects}
currentTheme="light"
/>
```
Choose between traditional pagination or load more functionality:
```tsx
// Traditional pagination (default)
<PaginatedProjectGrid
projects={projects}
cardsPerPage={6}
/>
// Load more functionality
<PaginatedProjectGrid
projects={projects}
cardsPerPage={6}
showLoadMore={true}
loadMoreText="Show More Projects"
/>
```
The component uses CSS modules for styling. You can override styles by targeting the CSS classes:
```css
/* Custom styles */
.custom-grid {
max-width: 1400px;
}
.custom-grid .projectCard {
border-radius: 16px;
}
```
The package includes full TypeScript definitions:
```tsx
import type { PaginatedProjectGridProps, Project } from '@asafarim/paginated-project-grid';
const MyComponent: React.FC<{projects: Project[]}> = ({ projects }) => {
const handleProjectClick = (project: Project) => {
// project is fully typed
console.log(project.title);
console.log(project.priority);
console.log(project.progress);
};
return (
<PaginatedProjectGrid
projects={projects}
onProjectClick={handleProjectClick}
/>
);
};
```
MIT © Ali Safari