# @tagaddod-design/react
> Modern, accessible React component library built on Radix UI primitives with comprehensive theming, RTL support, and TypeScript integration. Features 18+ production-ready components following WCAG 2.1 AA accessibility standards.
This design system provides a complete solution for building consistent, accessible user interfaces with support for multiple brands (Tagaddod, GreenPan) and bi-directional languages (English LTR, Arabic RTL). All components are built on proven Radix UI primitives for maximum reliability and accessibility.
## Installation
**NPM 7+ / PNPM / Yarn Berry:**
```bash
npm i @tagaddod-design/react \
@radix-ui/react-avatar @radix-ui/react-checkbox @radix-ui/react-dialog \
@radix-ui/react-form @radix-ui/react-popover @radix-ui/react-radio-group \
@radix-ui/react-select @radix-ui/react-switch @radix-ui/react-tabs \
@tabler/icons-react @tanstack/react-table
```
**Yarn 1.x:**
```bash
yarn add @tagaddod-design/react @radix-ui/react-avatar @radix-ui/react-checkbox @radix-ui/react-dialog @radix-ui/react-form @radix-ui/react-popover @radix-ui/react-radio-group @radix-ui/react-select @radix-ui/react-switch @radix-ui/react-tabs @tabler/icons-react @tanstack/react-table
```
**Required Setup:**
```jsx
// 1. Import CSS (required)
import '@tagaddod-design/react/styles.css';
// 2. Wrap app with ThemeProvider
import { ThemeProvider } from '@tagaddod-design/react';
function App() {
return (
);
}
```
**Google Fonts Setup (Required):**
```html
```
## Components
### AspectRatio
Maintains consistent proportions for content like images, videos, or embedded media. Ensures content keeps its aspect ratio when container dimensions change.
**Category** | Layout
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| ratio | number | 1 | Width/height ratio (e.g., 16/9 = 1.78) |
| children | ReactNode | - | Content to maintain aspect ratio |
**Available Ratios:** 1:1 (square), 16:9 (video), 4:3 (photo), 3:2 (landscape)
```jsx
1:1 Square Content
```
---
### Avatar
Displays user profile pictures, initials, or fallback icons. Handles image loading states and provides accessible alternatives.
**Category** | Data Display
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| type | 'image' \| 'initial' \| 'icon' | 'icon' | Avatar display type |
| src | string | - | Image URL (when type='image') |
| alt | string | - | Alt text for image |
| initial | string | - | Single character (when type='initial') |
| size | 'sm' \| 'md' \| 'lg' \| 'xl' | 'md' | Avatar size |
| delayMs | number | 600 | Fallback delay in milliseconds |
**Sizes:** sm (24px), md (32px), lg (40px), xl (64px)
**RTL Support:** Automatic Arabic text alignment for initials
```jsx
```
---
### Badge
Compact status indicators for categorizing, labeling, or showing counts. High-contrast elements that stand out from surrounding content.
**Category** | Data Display
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| children | ReactNode | - | Badge content |
| tone | 'default' \| 'success' \| 'warning' \| 'critical' \| 'info' | 'default' | Visual tone |
| size | 'sm' \| 'md' | 'md' | Badge size |
**Tones:** default (brand), success (green), warning (orange), critical (red), info (blue)
```jsx
Active
Urgent
Pending
```
---
### Button
Primary interactive element for triggering actions, form submissions, navigation, or selections. Supports multiple variants, states, and accessibility features.
**Category** | Actions
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| variant | 'primary' \| 'secondary' \| 'tertiary' \| 'plain' | 'primary' | Button visual style |
| tone | 'default' \| 'critical' \| 'success' \| 'neutral' \| 'magic' | 'default' | Color treatment |
| size | 'micro' \| 'medium' \| 'large' | 'medium' | Button size |
| loading | boolean | false | Shows loading spinner |
| disabled | boolean | false | Disables interaction |
| fullWidth | boolean | false | Expands to container width |
| prefixIcon | ReactNode | - | Icon before text |
| suffixIcon | ReactNode | - | Icon after text |
**Variants:** primary (filled), secondary (outlined), tertiary (subtle), plain (minimal)
**States:** default, hover, focus, loading, disabled
**RTL Support:** Automatic icon positioning for Arabic
```jsx
// Basic usage
// With icons
}
suffixIcon={}
>
Add Item
// Loading state
```
---
### Checkbox
Binary choice form control with checked, unchecked, and indeterminate states. Used in forms, settings, and multi-selection lists.
**Category** | Form Controls
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| label | string | - | Checkbox label text |
| helpText | string | - | Additional description |
| errorMessage | string | - | Error message display |
| checked | boolean | - | Controlled checked state |
| defaultChecked | boolean | false | Initial checked state |
| indeterminate | boolean | false | Indeterminate state |
| disabled | boolean | false | Disables interaction |
| required | boolean | false | Marks as required |
**States:** unchecked, checked, indeterminate, disabled, error
**Accessibility:** Full keyboard navigation and screen reader support
```jsx
```
---
### Drawer
Sliding panel overlay for supplementary content, forms, or detailed information while preserving main context visibility.
**Category** | Overlays
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| open | boolean | - | Controls drawer visibility |
| onOpenChange | function | - | Callback when state changes |
| title | string | - | Drawer header title |
| size | 'small' \| 'medium' \| 'large' | 'medium' | Drawer width |
| position | 'left' \| 'right' | 'right' | Slide direction |
| children | ReactNode | - | Drawer content |
**Sizes:** small (320px), medium (480px), large (640px)
**RTL Support:** Automatic position adjustment for Arabic layouts
```jsx
```
---
### Listbox
Selectable option list for dropdowns, menus, and selection interfaces. Supports rich content with icons, descriptions, and grouping.
**Category** | Form Controls
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| options | Array | - | List of selectable options |
| selectedValue | string | - | Currently selected option |
| onSelect | function | - | Selection callback |
| placeholder | string | - | Placeholder text |
| disabled | boolean | false | Disables interaction |
**Option Format:** `{ label: string, value: string, icon?: ReactNode, disabled?: boolean }`
```jsx
},
{ label: 'Analytics', value: 'analytics', icon: },
{ label: 'Settings', value: 'settings', icon: }
]}
selectedValue={selectedValue}
onSelect={setSelectedValue}
placeholder="Choose an option..."
/>
```
---
### Modal
Focus-grabbing overlay for confirmations, alerts, forms, and important interactions without page navigation.
**Category** | Overlays
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| trigger | ReactNode | - | Element that opens modal |
| title | string | - | Modal header title |
| showTitle | boolean | true | Display title header |
| showFooter | boolean | true | Display action footer |
| cancelLabel | string | 'Cancel' | Cancel button text |
| confirmLabel | string | 'Confirm' | Confirm button text |
| onCancel | function | - | Cancel callback |
| onConfirm | function | - | Confirm callback |
| children | ReactNode | - | Modal content |
**Features:** Focus management, escape key handling, backdrop click closing
**Accessibility:** ARIA dialog implementation with proper focus trapping
```jsx
Delete Item}
title="Confirm Deletion"
cancelLabel="Keep"
confirmLabel="Delete"
onCancel={() => console.log('Cancelled')}
onConfirm={() => console.log('Deleted')}
>
This action cannot be undone. Are you sure?
```
---
### Pagination
Navigation component for large datasets split across multiple pages. Provides page numbers, prev/next controls, and page info.
**Category** | Navigation
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| currentPage | number | 1 | Active page number |
| totalPages | number | - | Total page count |
| onPageChange | function | - | Page change callback |
| showFirstLast | boolean | true | Show first/last buttons |
| showPrevNext | boolean | true | Show prev/next buttons |
| siblingCount | number | 1 | Adjacent page numbers shown |
**Features:** Ellipsis for large page ranges, keyboard navigation, responsive design
```jsx
```
---
### Popover
Contextual content overlay anchored to trigger elements. Used for tooltips, menus, additional information, and quick actions.
**Category** | Overlays
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| content | ReactNode | - | Popover content |
| type | 'default' \| 'tooltip' | 'default' | Popover behavior type |
| placement | string | 'bottom' | Positioning relative to trigger |
| trigger | 'hover' \| 'click' | 'click' | Activation method |
| children | ReactNode | - | Trigger element |
**Placements:** top, bottom, left, right (with -start/-end variants)
**Features:** Auto-positioning, collision detection, portal rendering
```jsx
Rich content with actions
}
>
```
---
### RadioButton
Single-selection form control for mutually exclusive options. Used in groups where only one option can be selected.
**Category** | Form Controls
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| value | string | - | Radio button value |
| label | string | - | Display label |
| helpText | string | - | Additional description |
| disabled | boolean | false | Disables interaction |
**Usage Pattern:** Always use with RadioGroup wrapper for proper behavior
```jsx
import { RadioGroup, RadioButtonItem } from '@tagaddod-design/react';
```
---
### Select
Dropdown selection control for choosing from 4+ options. Provides search, grouping, and custom option rendering.
**Category** | Form Controls
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| label | string | - | Field label |
| placeholder | string | - | Placeholder text |
| options | Array | - | Selectable options |
| value | string | - | Selected value |
| onChange | function | - | Selection callback |
| disabled | boolean | false | Disables interaction |
| required | boolean | false | Marks as required |
| errorMessage | string | - | Error state message |
**Option Format:** `{ value: string, label: string, group?: string }`
**Features:** Keyboard navigation, search filtering, grouping support
```jsx
const fruits = [
{ value: 'apple', label: 'Apple', group: 'Common' },
{ value: 'banana', label: 'Banana', group: 'Common' },
{ value: 'dragonfruit', label: 'Dragon Fruit', group: 'Exotic' }
];
```
---
### Separator
Visual divider for organizing content sections, menu items, or layout boundaries. Provides clear content separation.
**Category** | Layout
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| orientation | 'horizontal' \| 'vertical' | 'horizontal' | Separator direction |
| decorative | boolean | true | Whether separator is decorative |
**Usage:** Use `decorative={false}` when separator provides semantic meaning
```jsx
{/* Content separation */}
First section content
Second section content
{/* Vertical in flex layouts */}
Item 1
Item 2
```
---
### Switch
Toggle control for binary settings and preferences. Provides clear on/off states with smooth animations.
**Category** | Form Controls
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| checked | boolean | - | Controlled checked state |
| defaultChecked | boolean | false | Initial state |
| onCheckedChange | function | - | State change callback |
| disabled | boolean | false | Disables interaction |
| required | boolean | false | Marks as required |
**States:** on, off, disabled
**Accessibility:** Proper switch role and keyboard support
```jsx
```
---
### Table
Advanced data table with sorting, filtering, search, pagination, and selection. Built on TanStack Table for performance.
**Category** | Data Display
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| data | Array | - | Table data array |
| columns | Array | - | Column definitions |
| title | string | - | Table title |
| showSearch | boolean | false | Enable search functionality |
| showFilters | boolean | false | Enable filtering |
| showExport | boolean | false | Enable export button |
| searchQuery | string | - | Current search value |
| onSearchChange | function | - | Search callback |
| activeFilters | object | - | Applied filters |
| onFilterChange | function | - | Filter callback |
Column Definition Format
```jsx
const columns = [
{
accessorKey: 'name',
header: 'Name',
enableSorting: true
},
{
accessorKey: 'status',
header: 'Status',
cell: ({ getValue }) => (
{getValue()}
)
}
];
```
**Features:** Row selection, bulk actions, responsive design, virtual scrolling
```jsx
```
---
### Tabs
Tabbed navigation for organizing related content into separate views without page changes.
**Category** | Navigation
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| variant | 'primary' \| 'secondary' | 'primary' | Visual style |
| defaultValue | string | - | Initially active tab |
| value | string | - | Controlled active tab |
| onValueChange | function | - | Tab change callback |
| ariaLabel | string | - | Accessibility label |
**Components:** Tabs (wrapper), TabsList (navigation), TabsTrigger (button), TabsContent (panel)
```jsx
Overview
Analytics
Settings
Overview content here
Analytics dashboard
```
---
### TextInput
Text input field with validation, icons, and multiple input types. Supports controlled and uncontrolled usage.
**Category** | Form Controls
**Status** | Stable
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| label | string | - | Field label |
| placeholder | string | - | Placeholder text |
| type | string | 'text' | HTML input type |
| value | string | - | Controlled value |
| onChange | function | - | Change callback |
| disabled | boolean | false | Disables input |
| required | boolean | false | Marks as required |
| errorMessage | string | - | Error message |
| helpText | string | - | Help description |
| prefixIcon | ReactNode | - | Icon before input |
| suffixIcon | ReactNode | - | Icon after input |
**Input Types:** text, email, password, number, tel, url, search
**States:** default, focus, error, disabled, readonly
**Features:** Password visibility toggle, auto-validation
```jsx
}
errorMessage={errors.email}
/>
}
suffixIcon={}
/>
```
---
## API Reference
* [Full Component Documentation](https://tagaddod-design-system.vercel.app/)
* [Storybook Interactive Examples](https://tagaddod-design-system.vercel.app/)
* [GitHub Repository](https://github.com/ahmedamr-r/tagaddod-design-system)
## Common Usage Patterns
### Form Layouts
```jsx
import { TextInput, Select, Checkbox, Button, Separator } from '@tagaddod-design/react';
function ContactForm() {
return (
);
}
```
### Dashboard Interface
```jsx
import {
Tabs, TabsList, TabsTrigger, TabsContent,
Table, Badge, Avatar, Button, Modal
} from '@tagaddod-design/react';
function UserDashboard() {
return (
Users
Analytics
Settings
{/* More analytics cards */}
);
}
```
### Modal Workflows
```jsx
import { Modal, Button, TextInput, Drawer } from '@tagaddod-design/react';
function ActionModals() {
return (
{/* Confirmation Modal */}
Delete Item}
title="Confirm Deletion"
cancelLabel="Keep Item"
confirmLabel="Delete"
onConfirm={handleDelete}
>
This action cannot be undone. The item will be permanently deleted.
{/* Form Drawer */}
Edit Profile}
title="Edit Profile"
size="medium"
>
);
}
```
### Responsive Layouts
```jsx
import { AspectRatio, Badge, Avatar, Separator } from '@tagaddod-design/react';
function ProductCard({ product }) {
return (
{product.name}
{product.inStock ? 'In Stock' : 'Out of Stock'}
{product.description}
);
}
```
## Theming & Customization
### Theme Provider Configuration
```jsx
import { ThemeProvider, useTheme } from '@tagaddod-design/react';
function App() {
return (
);
}
function ThemeSwitcher() {
const { theme, setTheme, direction, setDirection } = useTheme();
return (
);
}
```
### Custom CSS Variables
```css
/* Access design tokens directly */
.custom-component {
background-color: var(--t-color-surface-primary);
padding: var(--t-space-400);
border-radius: var(--t-border-radius-200);
color: var(--t-color-text-primary);
font-family: var(--t-font-family-primary);
}
/* Responsive utilities */
@media (max-width: 768px) {
.custom-component {
padding: var(--t-space-200);
}
}
```
### Advanced Theming
```jsx
// Programmatic theme detection
function AppWithThemeDetection() {
const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
const prefersRTL = useMediaQuery('(dir: rtl)');
return (
);
}
```
## Accessibility Guidelines
### Keyboard Navigation
- All interactive components support Tab/Shift+Tab navigation
- Arrow keys for radio groups, tabs, and menus
- Enter/Space for activation
- Escape for closing modals/popovers
### Screen Reader Support
- Semantic HTML structure with proper headings
- ARIA labels, descriptions, and roles
- Live regions for dynamic content updates
- Focus management for overlays
### Visual Accessibility
- WCAG 2.1 AA color contrast compliance
- Focus indicators with 3px minimum thickness
- No color-only information conveying
- Reduced motion support via `prefers-reduced-motion`
### Implementation Examples
```jsx
// Proper form labeling
// Icon-only buttons require labels
}
aria-label="Close dialog"
onClick={closeModal}
/>
// Complex widgets with ARIA
```
## TypeScript Integration
### Component Props
```tsx
import type {
ButtonProps,
TextInputProps,
SelectOption,
TableColumn
} from '@tagaddod-design/react';
// Extend component props
interface CustomButtonProps extends ButtonProps {
analyticsId?: string;
}
// Table column definitions
const userColumns: TableColumn[] = [
{
accessorKey: 'name',
header: 'Name',
cell: ({ getValue, row }) => (
().charAt(0)}
size="sm"
/>
{getValue()}
)
}
];
// Select options with proper typing
const statusOptions: SelectOption[] = [
{ value: 'active', label: 'Active User' },
{ value: 'inactive', label: 'Inactive User' },
{ value: 'pending', label: 'Pending Approval' }
];
```
### Theme Type Safety
```tsx
import type { Theme, Direction } from '@tagaddod-design/react';
interface AppConfig {
theme: Theme; // 'tagaddod' | 'greenpan'
direction: Direction; // 'ltr' | 'rtl'
locale: string;
}
// Theme-aware component
function ThemedComponent({ config }: { config: AppConfig }) {
return (
{/* Components automatically adapt */}
);
}
```
## Performance Optimization
### Tree Shaking
```jsx
// ✅ Recommended: Named imports for tree shaking
import { Button, TextInput, Modal } from '@tagaddod-design/react';
// ❌ Avoid: Imports entire library
import * as TagaddodDesign from '@tagaddod-design/react';
```
### Bundle Size Optimization
```jsx
// ✅ Import only needed components
import { Button } from '@tagaddod-design/react';
// ✅ Lazy load heavy components
const Table = lazy(() =>
import('@tagaddod-design/react').then(mod => ({ default: mod.Table }))
);
function DataPage() {
return (
Loading table...}>
);
}
```
### CSS Loading Strategy
```jsx
// ✅ Load CSS once at app entry
import '@tagaddod-design/react/styles.css';
// ✅ Or dynamic import for code splitting
const loadStyles = () => import('@tagaddod-design/react/styles.css');
// Load styles when components are needed
useEffect(() => {
loadStyles();
}, []);
```
## Framework Integration
### Next.js App Router
```jsx
// app/layout.tsx
import '@tagaddod-design/react/styles.css';
import { ThemeProvider } from '@tagaddod-design/react';
export default function RootLayout({ children }) {
return (
{children}
);
}
```
### Vite + React
```jsx
// main.tsx
import '@tagaddod-design/react/styles.css';
import { ThemeProvider } from '@tagaddod-design/react';
ReactDOM.createRoot(document.getElementById('root')!).render(
);
```
### Create React App
```jsx
// src/index.js
import '@tagaddod-design/react/styles.css';
import { ThemeProvider } from '@tagaddod-design/react';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
);
```
## Changelog
See [CHANGELOG.md](https://github.com/ahmedamr-r/tagaddod-design-system/blob/main/packages/react/CHANGELOG.md) for detailed version history.
## License
MIT - see [LICENSE](https://github.com/ahmedamr-r/tagaddod-design-system/blob/main/LICENSE) for details.