npm package: @lab39/react-ui
Description: A collection of reusable React components for the lab39 ecosystem
Author: lab39
Latest version: 0.2.5

# @lab39/react-ui

A collection of fully customizable, accessible React components for the lab39 ecosystem and beyond.

[![npm version](https://img.shields.io/npm/v/@lab39/react-ui.svg)](https://www.npmjs.com/package/@lab39/react-ui)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## ✨ Features

- 🎨 **Fully Customizable** - Zero hardcoded values, everything configurable via props and CSS variables
- ♿ **Accessible** - WCAG compliant with proper ARIA labels and keyboard navigation
- 📦 **Tree-shakeable** - Import only what you need
- 🎯 **TypeScript** - Full type definitions included
- 🎭 **CSS Modules** - Scoped styles with CSS custom properties for theming
- 🚀 **Lightweight** - Minimal dependencies, optimized bundle size
- 🔧 **Developer Friendly** - Consistent API design across all components

## 📦 Installation

```bash
npm install @lab39/react-ui
```

```bash
yarn add @lab39/react-ui
```

```bash
pnpm add @lab39/react-ui
```

## 🚀 Quick Start

### Toast Notifications

```tsx
import { ToastProvider, useToast } from '@lab39/react-ui';
import '@lab39/react-ui/styles';

function App() {
  return (
    <ToastProvider position="top-right" defaultDuration={3000}>
      <YourApp />
    </ToastProvider>
  );
}

function YourComponent() {
  const { addToast } = useToast();
  
  return (
    <button onClick={() => addToast({ type: 'success', message: 'Done!' })}>
      Show Toast
    </button>
  );
}
```

### Custom Select

```tsx
import { CustomSelect } from '@lab39/react-ui';
import '@lab39/react-ui/styles';

function MyForm() {
  const [value, setValue] = useState('');
  
  const options = [
    { value: 'option1', label: 'Option 1' },
    { value: 'option2', label: 'Option 2' },
  ];
  
  return (
    <CustomSelect
      value={value}
      onChange={setValue}
      options={options}
      placeholder="Select an option"
      label="Choose one"
      showLabel
    />
  );
}
```

### Loading Spinner

```tsx
import { LoadingSpinner } from '@lab39/react-ui';
import '@lab39/react-ui/styles';

function Loading() {
  return <LoadingSpinner size="large" color="#3b82f6" />;
}
```

### Skeleton Loader

```tsx
import { SkeletonLoader } from '@lab39/react-ui';
import '@lab39/react-ui/styles';

function LoadingCard() {
  return (
    <div>
      <SkeletonLoader width="100%" height="200px" borderRadius="8px" />
      <SkeletonLoader width="80%" height="20px" lines={3} gap="8px" />
    </div>
  );
}
```

### Error Boundary

```tsx
import { ErrorBoundary } from '@lab39/react-ui';

function App() {
  return (
    <ErrorBoundary
      errorMessage="Oops! Something went wrong"
      retryText="Try Again"
      icon="⚠️"
      showDetails={false}
      onError={(error, errorInfo) => {
        console.error('Error caught:', error, errorInfo);
      }}
    >
      <YourApp />
    </ErrorBoundary>
  );
}
```

### SEO Component

```tsx
import { SEO } from '@lab39/react-ui';

function MyPage() {
  return (
    <>
      <SEO
        title="My Page Title"
        description="Description of my page"
        keywords="react, components, ui"
        canonical="https://example.com/my-page"
        ogImage="https://example.com/image.jpg"
        twitterCard="summary_large_image"
        twitterSite="@yourhandle"
      />
      <div>Your page content</div>
    </>
  );
}
```

## 🎨 Theming

All components use CSS custom properties for easy theming. You can override these in your global CSS:

```css
:root {
  /* Toast */
  --lab39-toast-gap: 0.75rem;
  --lab39-toast-max-width: 420px;
  --lab39-toast-success-border: #10b981;
  --lab39-toast-success-bg: #ecfdf5;
  --lab39-toast-success-color: #065f46;
  
  /* Select */
  --lab39-select-border: #d1d5db;
  --lab39-select-border-radius: 0.5rem;
  --lab39-select-focus-ring: #3b82f6;
  
  /* Spinner */
  --lab39-spinner-color: #3b82f6;
  --lab39-spinner-size-medium: 2rem;
  
  /* Skeleton */
  --lab39-skeleton-bg: linear-gradient(90deg, #f0f0f0 0%, #e0e0e0 50%, #f0f0f0 100%);
  
  /* Error Boundary */
  --lab39-error-button-bg: #3b82f6;
  --lab39-error-button-bg-hover: #2563eb;
}
```

## 📚 Components

### ToastProvider

Wrap your app with `ToastProvider` to enable toast notifications.

**Props:**

- `children` - React children
- `defaultDuration` - Default duration in ms (default: 3000)
- `maxToasts` - Maximum number of toasts (default: 5)
- `position` - Position on screen (default: 'top-right')
  - Options: `'top-left'`, `'top-right'`, `'top-center'`, `'bottom-left'`, `'bottom-right'`, `'bottom-center'`
- `icons` - Custom icons for toast types

### useToast Hook

```tsx
const { toasts, addToast, removeToast } = useToast();
```

### useToastHelpers Hook

```tsx
const { success, error, warning, info } = useToastHelpers();
success('Operation completed!');
error('Something went wrong');
```

### CustomSelect

Fully accessible dropdown select component with keyboard navigation.

**Props:**

- `value` - Current selected value
- `onChange` - Change callback
- `options` - Array of `{ value, label }` objects
- `placeholder` - Placeholder text
- `disabled` - Disable the select
- `label` - Accessibility label
- `showLabel` - Show label visually
- `icon` - Icon element
- `dropdownPosition` - `'bottom'` or `'top'`

### LoadingSpinner

Simple loading spinner component.

**Props:**

- `size` - `'small'`, `'medium'`, `'large'` (default: 'medium')
- `color` - Custom color
- `label` - Accessibility label (default: 'Loading...')

### SkeletonLoader

Loading placeholder component.

**Props:**

- `width` - Width (string or number)
- `height` - Height (string or number)
- `borderRadius` - Border radius
- `lines` - Number of skeleton lines
- `gap` - Gap between lines
- `variant` - `'text'`, `'circular'`, `'rectangular'`
- `noAnimation` - Disable shimmer animation

### ErrorBoundary

React error boundary component.

**Props:**

- `children` - React children
- `fallback` - Custom fallback render function
- `onError` - Error callback
- `errorMessage` - Custom error message
- `retryText` - Custom retry button text
- `icon` - Icon to display
- `showDetails` - Show error details

### SEO

SEO meta tags management component.

**Props:**

- `title` - Page title
- `description` - Page description
- `keywords` - Meta keywords
- `canonical` - Canonical URL
- `ogTitle` - Open Graph title
- `ogDescription` - Open Graph description
- `ogImage` - Open Graph image
- `ogType` - Open Graph type
- `twitterCard` - Twitter card type
- `twitterSite` - Twitter handle
- `additionalMeta` - Additional meta tags
- `lang` - Page language

## 🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## 📄 License

MIT © [lab39](https://github.com/varmankur/lab39-react-ui)

## 🔗 Links

- [GitHub Repository](https://github.com/varmankur/lab39-react-ui)
- [npm Package](https://www.npmjs.com/package/@lab39/react-ui)
- [Issues](https://github.com/varmankur/lab39-react-ui/issues)

## 💡 Philosophy

This library is built with the following principles:

- **No Hardcoded Values**: Everything is configurable
- **Consistency**: Uniform API design across components
- **Accessibility**: WCAG compliant by default
- **Performance**: Lightweight and optimized
- **Developer Experience**: TypeScript, great documentation, intuitive APIs

---

Made with ❤️ by the lab39 team