Last Updated: 2026-02-07 Project Type: React/Next.js Design System with RTL-First Architecture Project Name: Noor UI (نور - "Light" in Arabic)
Before starting any work, review these essential files:
- CHECKLIST.md - Pre-commit verification checklist (USE THIS BEFORE EVERY COMMIT!)
- Component Template - Copy-paste ready component structure
- Documentation Template - Complete doc page template
These files are your primary references. The checklist will catch 99% of common mistakes.
- ALWAYS use logical properties (never use
ml-,mr-,pl-,pr-,text-left,text-right) - USE:
ms-*(margin-inline-start),me-*(margin-inline-end),ps-*(padding-inline-start),pe-*(padding-inline-end) - USE:
text-startandtext-endinstead oftext-leftandtext-right - Icons: Position icons using
ms-*orme-*so they flip naturally in RTL
All components MUST follow these patterns:
- ✅ Use
React.forwardReffor all components - ✅ Use
cn()utility for className merging - ✅ Export
displayNamefor debugging - ✅ Include TypeScript types for all props
- ✅ Use CVA (class-variance-authority) for components with variants
- ✅ Support RTL out of the box (no special RTL prop needed)
Use the complete template: .claude/templates/component.template.tsx
The template includes:
- ✅ Full forwardRef pattern with TypeScript types
- ✅ CVA variants setup
- ✅ Composition pattern with sub-components
- ✅ RTL-compliant classes
- ✅ Usage notes and examples
For direction-aware components, use the useDirection() hook from our direction provider:
import { useDirection } from '@/components/providers/direction-provider'
const Component = (props) => {
const { direction, locale } = useDirection()
// direction: 'ltr' | 'rtl'
// locale: 'en' | 'ar'
return <RadixPrimitive.Root dir={direction} {...props} />
}Benefits:
- ✅ Centralized direction management
- ✅ No MutationObserver setup in each component
- ✅ Access to both direction and locale
- ✅ Automatic font switching (Inter for English, IBM Plex Sans Arabic for Arabic)
Example: Direction-aware Tabs component
const TabsRoot = React.forwardRef<...>(({ dir, ...props }, ref) => {
const { direction } = useDirection()
return (
<TabsPrimitive.Root
ref={ref}
dir={dir || direction} // Allow override, fallback to context
{...props}
/>
)
})CRITICAL: Every new component or page MUST be made discoverable and include proper SEO metadata.
👉 USE THE CHECKLIST: See CHECKLIST.md for the complete pre-commit verification list.
Quick overview:
- Add component file in
/components/ui/[name].tsx - Use the component template above
- Ensure full RTL support with logical properties
- Add TypeScript types
- Create
/app/(docs)/components/[name]/page.tsxin the (docs) route group - CRITICAL: Add 'use client' directive at the top
- DO NOT export metadata - Client components cannot have metadata exports (Next.js limitation)
- DO NOT add manual header/footer - the (docs) layout provides these
- Include: Preview, Installation, Usage, Examples, Props, Accessibility, RTL Considerations
- Add interactive ComponentShowcase with LTR/RTL toggle
- Show at least 2-3 real-world examples
- Include mobile and desktop examples where relevant
- Add Loading State section if component has
isLoadingorloadingprop
Required Page Structure (Route Groups Pattern):
'use client'
import * as React from 'react'
import Link from 'next/link'
import { ComponentShowcase } from '@/components/docs/component-showcase'
import { PropsTable } from '@/components/docs/props-table'
import { CodeBlock } from '@/components/docs/code-block'
import { YourComponent } from '@/components/ui/your-component'
export default function ComponentPage() {
return (
<div className="min-h-screen">
<main id="main-content" className="container py-12">
{/* Page Header */}
<div className="max-w-3xl mb-12">
<h1 className="text-4xl font-bold tracking-tight mb-4">Component Name</h1>
<p className="text-xl text-muted-foreground">
Brief description of the component and its purpose.
</p>
</div>
{/* Component sections */}
<ComponentShowcase>
<ComponentShowcase.Demo>
<YourComponent />
</ComponentShowcase.Demo>
</ComponentShowcase>
<PropsTable props={[...]} />
<CodeBlock code="..." language="tsx" />
</main>
</div>
)
}Why this structure?
- ✅ Client component for interactivity
- ✅ Header/footer provided by
app/(docs)/layout.tsx - ✅ Cleaner code - no navigation boilerplate
- ✅ DRY principle - layout changes propagate automatically
- ✅ Consistent navigation across all doc pages
- Add to
/app/components/page.tsx- Add to appropriate category - Add to
/lib/search-data.ts- Add searchable entry with keywords - Test search - Verify it appears in command palette
- Update component count if adding new components
- Add to feature list if adding significant capability
Use the complete template: .claude/templates/component-doc.template.tsx
Every component documentation page MUST include:
- 'use client' directive at the very top (required for interactive components)
NOTE: Client components cannot export metadata in Next.js 14+. For SEO, use layout files or create server component wrappers.
'use client' - Page title and description
- Live Preview with interactive demo
- Installation instructions (CLI + Manual)
- Usage examples with code
- Multiple Examples (minimum 3 variants)
- Loading State section (if component supports
isLoadingorloadingprop)- Show skeleton/loading state example
- Include code example
- Demonstrate loading state in ComponentShowcase
- Props Documentation with complete table
- Accessibility section with keyboard navigation
- RTL Considerations with best practices
- Related Components section with links
The template includes all sections with proper structure and real Arabic content examples.
Location: /lib/search-data.ts
When adding any new page or component, ALWAYS add an entry:
{
title: 'Component Name',
description: 'Clear, concise description',
href: '/components/component-name',
category: 'Component' | 'Documentation' | 'Example' | 'Token' | 'Theme',
keywords: ['keyword1', 'keyword2', 'synonym1', 'use-case'],
}Categories:
Component- UI componentsDocumentation- Guides and docsExample- Real-world examplesToken- Design tokensTheme- Theme pages
Good Keywords:
- Component name variations
- Use cases (e.g., 'form', 'navigation', 'data')
- Related terms (e.g., 'modal' for Dialog)
- RTL-specific terms where relevant
- Use
ResponsiveTablecomponent for data tables - Shows 2-column layout (label | value) on mobile
- Prevents horizontal scrolling
- Test all components at mobile breakpoints
- Use responsive grid classes:
grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 - Consider stacked layouts for mobile
- Ensure touch targets are at least 44x44px
Location: /lib/i18n/ directory with separate EN and AR files
All user-facing text MUST use the centralized i18n system. NO hardcoded bilingual ternaries allowed.
import { useDirection } from '@/components/providers/direction-provider'
import { content } from '@/lib/i18n'
export default function Component() {
const { locale } = useDirection()
const t = content[locale]
return (
<div>
<h1>{t.section.title}</h1>
<p>{t.section.description}</p>
</div>
)
}// ❌ NEVER use hardcoded ternaries for text content
{isRTL ? 'النص العربي' : 'English text'}
{locale === 'ar' ? 'مرحبا' : 'Hello'}The isRTL variable should ONLY be used for:
-
CSS Classes:
className={isRTL ? 'font-arabic' : 'font-latin'}
-
Layout/Alignment Props:
<DropdownMenu align={isRTL ? 'start' : 'end'} /> <Component dir={isRTL ? 'rtl' : 'ltr'} />
-
Locale Parameters:
formatDate(date, isRTL ? 'ar' : 'en')
NEVER use isRTL ternaries for user-facing strings.
When accessing nested translation objects, TypeScript may create overly strict union types. Use explicit type assertion:
const { locale } = useDirection()
const t = content[locale]
// For deeply nested component translations:
const componentT = content[locale].componentName as any
// Then use componentT for component-specific strings:
{componentT.examples.title}
{componentT.features.description}Each function scope needs its own translation constant:
function ParentComponent() {
const { locale } = useDirection()
const t = content[locale]
return <div>{t.parent.title}</div>
}
function ChildComponent() {
// ✅ Define t in this scope too
const { locale } = useDirection()
const t = content[locale]
return <div>{t.child.title}</div>
}When adding new UI strings:
- Add the key to both
/lib/i18n/en/common.tsAND/lib/i18n/ar/common.ts - Ensure the object structure matches exactly in both files
- Use descriptive, hierarchical keys:
section.subsection.key - Test in both languages to verify translations appear
- All user-facing text should support English and Arabic
- Provide bilingual examples in documentation
- Test every component in both LTR and RTL modes
- Real Arabic content preferred over lorem ipsum
- LTR: Inter (sans-serif)
- RTL: IBM Plex Sans Arabic
- Monospace: JetBrains Mono (both directions)
Location: /lib/tokens.ts
- Use design tokens for all styling
- Never hardcode colors, spacing, or typography
- Reference tokens via Tailwind classes
- All 4 themes (Minimal, Futuristic, Cozy, Artistic) share the same tokens
Before committing component work, verify:
- Component works in LTR mode
- Component works in RTL mode
- Icons flip correctly in RTL
- No
ml-,mr-,text-left,text-rightclasses used - Component appears in search data
- Component appears in components index
- Documentation page is complete
- Mobile view works (no horizontal scroll)
- Keyboard navigation works
- Focus indicators are visible
/app
layout.tsx # Root layout with providers
page.tsx # Homepage
/(docs)/ # Route group for documentation
layout.tsx # Shared header/footer layout
/components/ # Component documentation (32 pages)
page.tsx # Components index (UPDATE THIS!)
/[name]/page.tsx # Individual component docs
/documentation/ # Guides (installation, RTL, etc.)
/tokens/ # Design tokens reference
/themes/ # Theme customization
/getting-started/ # Getting started guide
/rtl-guide/ # RTL development guide
/examples/ # Examples listing page
/examples/ # Standalone examples (no layout)
/dashboard/page.tsx # Dashboard example
/ecommerce/page.tsx # E-commerce example
/registration/page.tsx # Registration form example
/components
/ui/ # UI components library (32 components)
/layout/ # Layout components
site-header.tsx # Global navigation
site-footer.tsx # Global footer
/docs/ # Documentation components
component-showcase.tsx # Live demo with LTR/RTL toggle
props-table.tsx # API documentation
code-block.tsx # Syntax highlighting
global-search.tsx # Command palette (Cmd+K)
/providers/ # Context providers
direction-provider.tsx # RTL/LTR and locale context
design-system-provider.tsx # Theme management
client-providers.tsx # Combined providers
/lib
tokens.ts # Design tokens
i18n.ts # Internationalization
utils.ts # Utilities
search-data.ts # Search data (UPDATE THIS!)
Key Points:
(docs)is a route group - invisible in URLs, provides shared layout- Standalone examples live outside (docs) for full-screen experience
- All doc pages automatically get header/footer from layout
- SiteHeader includes command palette for quick navigation
- Use directional classes (
ml-,mr-,pl-,pr-) - Use text alignment classes (
text-left,text-right) - Use hardcoded bilingual ternaries (
isRTL ? 'Arabic' : 'English') - Add manual header/footer to doc pages (use route group layout)
- Set up MutationObserver for direction (use
useDirection()hook) - Forget to update search-data.ts when adding components
- Forget to update components index page
- Create components without documentation
- Export metadata from 'use client' components (Next.js 14+ doesn't allow this)
- Skip mobile testing
- Hardcode colors or spacing
- Use
position: leftorposition: right(usestart/end) - Create new pages outside the (docs) route group for documentation
- Use logical properties (
ms-,me-,ps-,pe-) - Use
text-startandtext-end - Use centralized i18n system (
const t = content[locale]) - Place documentation pages in the (docs) route group
- Start client components with 'use client' only (no metadata exports)
- Use
useDirection()hook for direction-aware components - Use CodeBlock component for syntax highlighting
- Update ALL navigation/search when adding features
- Test in both LTR and RTL modes
- Use design tokens via Tailwind
- Add comprehensive documentation
- Think mobile-first
- Use
position: inline-startorposition: inline-end
type: Brief description
Detailed explanation:
- What was changed
- Why it was changed
- Any breaking changes
- Links to related issues
Examples:
feat: Add Table component with mobile-responsive layout
fix: Correct RTL orientation for dropdown menus
docs: Add documentation for 4 remaining components
chore: Update search data with new components
Types: feat, fix, docs, style, refactor, test, chore
- All new components in search-data.ts
- All new pages in navigation
- Documentation is complete
- Tested in LTR and RTL
- Mobile view verified
Component Count: 74+ components ✅ Documentation Pages: 74+ component pages documented ✅ Examples: 17+ complete examples ✅ Starters: 2 production-ready (Blog Dashboard, E-commerce) ✅ Themes: 4 (Minimal, Futuristic, Cozy, Artistic) ✅ Architecture: Route groups with shared layouts ✅
- Core (8): Button, Card, FeatureCard, Input, Label, Badge, Separator, Avatar
- Forms (10): Form, Checkbox, Radio Group, Select, Switch, Slider, Textarea, DatePicker, TimePicker, NumberInput
- Data Display (6): Table, DataTable, Command, StatsCard, EmptyState, ListingCard
- Feedback (6): Alert, Toast, Dialog, Tooltip, Progress, Skeleton
- Navigation (5): Tabs (direction-aware), Breadcrumb, Pagination, Dropdown Menu, Context Menu
- Overlays & Layout (6): Sheet, Accordion, Collapsible, Popover, DashboardShell, Stepper
- GCC-Specific (5): PrayerTimes, HijriDate, ArabicNumber, ZakatCalculator, Calendar
- Advanced Forms (3): FileUpload, RichTextEditor, Scroll Area
- User Interface (2): UserMenu, NotificationCenter
- AI/LLM (Experimental) (10): ChatMessage, StreamingText, PromptInput, ThinkingIndicator, MessageActions, ModelSelector, ParameterSlider, TokenCounter, ConversationHistory, WorkflowCanvas
- ✅ Tailwind CSS v3 → v4.1 migration (CSS-first configuration with
@themeblocks) - ✅ Custom themes system with extensible DesignSystemProvider
- ✅
--color-*variable refactoring for proper theme scoping - ✅ ~50 hardcoded English strings replaced with i18n translations (EN/AR)
- ✅ Published noorui-rtl v0.8.2 to npm
- Radix UI Docs: https://www.radix-ui.com/docs/primitives
- Tailwind CSS: https://tailwindcss.com/docs
- RTL Styling: https://rtlstyling.com/posts/rtl-styling
- Logical Properties: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties
| Physical | Logical | Usage |
|---|---|---|
ml-4 |
ms-4 |
Margin start |
mr-4 |
me-4 |
Margin end |
pl-4 |
ps-4 |
Padding start |
pr-4 |
pe-4 |
Padding end |
text-left |
text-start |
Text alignment start |
text-right |
text-end |
Text alignment end |
left-0 |
start-0 |
Position start |
right-0 |
end-0 |
Position end |
// ✅ Correct - will flip in RTL
<Icon className="me-2 h-4 w-4" />
<span>Text</span>
// ❌ Wrong - will not flip
<Icon className="mr-2 h-4 w-4" />
<span>Text</span>Remember: When in doubt, check existing components for patterns. Consistency is key!