noorui-rtl 0.10.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/CONTRIBUTING.md +31 -5
- package/LICENSE +1 -1
- package/README.md +48 -407
- package/dist/index.d.mts +8 -139
- package/dist/index.d.ts +8 -139
- package/dist/index.js +1370 -1691
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1368 -1686
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
|
+
- **Comprehensive Unit Test Suite**: 690+ tests across 69 test files covering all components
|
|
12
|
+
- Props, variant CSS class assertions, and size validation
|
|
13
|
+
- RTL behavior: bilingual props (titleAr/descriptionAr), logical properties, directional icons (rtl:rotate-180), separator flipping
|
|
14
|
+
- Accessibility: ARIA attributes, keyboard navigation (Tab/Arrow/Escape), focus management (trap + restore on Dialog/Sheet), aria-selected/aria-current
|
|
15
|
+
- User interactions via userEvent (click, type, toggle, controlled/uncontrolled)
|
|
16
|
+
- Edge cases: empty arrays, zero/negative values, disabled states, boundary values, missing optional props
|
|
17
|
+
- Regional components: Arabic numeral formatting, Hijri holiday detection, prayer time highlighting, Zakat calculation
|
|
18
|
+
- AI/LLM components: streaming text with fake timers, token thresholds, conversation filtering
|
|
19
|
+
- Composite components: carousel loop/keyboard/dots, stepper step state transitions, dashboard nav
|
|
20
|
+
- **Test infrastructure**: ResizeObserver, pointer capture, and scrollIntoView mocks in `vitest.setup.ts` for Radix UI compatibility
|
|
21
|
+
|
|
22
|
+
## [0.11.0] - 2026-03-23
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- **MJML Email Template System**: 21 production-ready bilingual email templates with LTR, RTL, and bilingual variants. Auto-themed from `globals.css` with light/dark mode support. 504 compiled HTML files across 4 themes (cozy, minimal, futuristic, artistic).
|
|
26
|
+
- **Transactional**: Order Confirmation, Shipping Update, Invoice/Receipt, Bank Transfer Receipt, Hotel Booking Confirmation, Payment Reminder
|
|
27
|
+
- **Auth**: Welcome/Onboarding, Password Reset, OTP Verification
|
|
28
|
+
- **Notifications**: Notification Alert, Appointment Reminder, Assignment Notification, Support Ticket
|
|
29
|
+
- **Marketing**: Newsletter, Event Invitation, Feedback Request
|
|
30
|
+
- **Industry**: Real Estate (Dar Al Khaleej), Marketplace (Souq Al Noor), Government (Noor Gov Portal), Esports (Gulf Stars Esports), Islamic Finance (Al Baraka Finance)
|
|
31
|
+
- **Email Templates Showcase Page** (`/email-templates`): Interactive preview with variant/device/theme/dark toggles, URL deep linking, copy/download HTML, and category filtering (Transactional, Auth, Notifications, Marketing, Industry)
|
|
32
|
+
- **Build Script** (`emails/build.js`): Auto-extracts theme colors from `styles/globals.css` — no static JSON config files. Supports `--theme` flag and `--theme-file` for custom brands. Post-processes RTL HTML with `dir="rtl" lang="ar"`
|
|
33
|
+
- **15 Phosphor Duotone Inline SVGs**: Theme-colored icons (Lock, Key, CheckCircle, Lightning, MagnifyingGlass, ChatCircle, CalendarBlank, Clock, Timer, Stethoscope, GraduationCap, MapPin, Microphone, Lightbulb, Package) with `fill="{{primary}}"` for automatic theming
|
|
34
|
+
- **RTL Email Fixes**: Mobile table stacking with `.stack-table-rtl` CSS class, RLM marks (`‏`) on mixed bidi content, truck icon mirrored for Arabic (SVG transform), `direction: rtl !important` on stacked cells
|
|
35
|
+
- **Site Navigation**: Email Templates added to header (More dropdown + mobile menu), footer (Resources), global search, sitemap, documentation hub, examples page cross-link, and components "Need Help?" card
|
|
36
|
+
- **`pnpm build:emails`** script in package.json
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
- Removed "default" theme (`:root` values now serve as base for named themes only). 4 themes: minimal, futuristic, cozy, artistic
|
|
40
|
+
- `.gitattributes` marks `public/emails/preview/**/*.html` as `linguist-generated`
|
|
41
|
+
|
|
42
|
+
## [0.10.0] - 2026-03-14
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
- **Carousel component**: Direction-aware swipeable content carousel using `react-swipeable` + `framer-motion`. Generic `<T>` typing with `renderItem` pattern for content-agnostic slides. Features: auto-play with pause on hover/focus, arrow and dot navigation, swipe gestures (touch + mouse), keyboard navigation (ArrowLeft/Right, Home, End — all RTL-aware), looping toggle, `dotSize` prop (`'sm'` | `'lg'`) for WCAG 2.5.8 touch target compliance. Accessible with `role="region"`, `aria-roledescription="carousel"`, `aria-live="polite"` announcements, `role="tab"` dot indicators, `prefers-reduced-motion` support, and Eastern Arabic numerals in RTL mode.
|
|
11
46
|
- **Timeline component**: Vertical event timeline with connecting lines, status-based styling (complete/current/upcoming), custom icons, date labels, and alternating layout. Supports compact mode for sidebar use, card wrapping for changelogs, and full RTL support via CSS logical properties. Accessible with `role="list"`, unique `aria-label`, and sr-only status text.
|
|
12
47
|
- **Chart component**: Unified charting component with line, bar, area, and donut variants. Built on Chart.js for proper canvas rendering. Fully RTL-aware with automatic axis flipping, Arabic-Indic numeral formatting, and theme-aware colors. Includes configurable `strokeWidth`, `fontSize`, `thickness` (donut), and `direction` override prop. Accessible with visually hidden data tables, `role="img"` figure wrappers, locale-aware sr-only summaries, multi-series dash patterns (WCAG 1.4.1), and `prefers-reduced-motion` support.
|
|
13
48
|
|
package/CONTRIBUTING.md
CHANGED
|
@@ -145,12 +145,38 @@ All components must:
|
|
|
145
145
|
|
|
146
146
|
### Testing
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
All components have comprehensive unit tests in `components/ui/__tests__/`. New components or changes must include tests.
|
|
149
149
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
-
|
|
150
|
+
**Test files go in:** `components/ui/__tests__/{component-name}.test.tsx`
|
|
151
|
+
|
|
152
|
+
**What to test:**
|
|
153
|
+
- Renders without crashing with default props
|
|
154
|
+
- All variants/sizes apply correct CSS classes
|
|
155
|
+
- RTL behavior: bilingual props (titleAr, descriptionAr), logical properties, directional icons
|
|
156
|
+
- Accessibility: ARIA attributes, keyboard navigation, focus management, label associations
|
|
157
|
+
- User interactions: click, toggle, type, controlled/uncontrolled state
|
|
158
|
+
- Edge cases: empty data, disabled state, boundary values, missing optional props
|
|
159
|
+
|
|
160
|
+
**Run tests:**
|
|
161
|
+
```bash
|
|
162
|
+
pnpm test --run # Run all 690+ tests
|
|
163
|
+
pnpm test --run -- button # Run tests matching "button"
|
|
164
|
+
pnpm test:coverage # Coverage report
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Pattern to follow:** See `components/ui/__tests__/button.test.tsx` for a complete example.
|
|
168
|
+
|
|
169
|
+
Components using `useDirection()` need a `DirectionProvider` wrapper in tests:
|
|
170
|
+
```tsx
|
|
171
|
+
const renderWithDirection = (ui: React.ReactElement, direction: 'ltr' | 'rtl' = 'ltr') => {
|
|
172
|
+
const locale = direction === 'rtl' ? 'ar' : 'en';
|
|
173
|
+
return render(
|
|
174
|
+
<DirectionProvider controlledDirection={direction} controlledLocale={locale}>
|
|
175
|
+
{ui}
|
|
176
|
+
</DirectionProvider>
|
|
177
|
+
);
|
|
178
|
+
};
|
|
179
|
+
```
|
|
154
180
|
|
|
155
181
|
## RTL Guidelines
|
|
156
182
|
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
# Noor UI
|
|
1
|
+
# Noor UI
|
|
2
2
|
|
|
3
|
-
> نور
|
|
3
|
+
> نور — "Light" in Arabic
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/noorui-rtl)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://github.com/ositaka/noor-ui)
|
|
7
8
|
[](https://storybook.noorui.com)
|
|
8
9
|
|
|
9
10
|

|
|
@@ -12,223 +13,26 @@ Beautiful RTL-first React components for bilingual applications. Built with Radi
|
|
|
12
13
|
|
|
13
14
|
**[Documentation](https://noorui.com)** · **[Storybook](https://storybook.noorui.com)** · **[Examples](https://noorui.com/examples)** · **[npm](https://www.npmjs.com/package/noorui-rtl)**
|
|
14
15
|
|
|
15
|
-
##
|
|
16
|
+
## Features
|
|
16
17
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
18
|
+
- **RTL-First** — Perfect Arabic/Persian support with logical CSS properties
|
|
19
|
+
- **77+ Components** — Complete UI toolkit from buttons to dashboards
|
|
20
|
+
- **Well-Tested** — 690+ unit tests covering props, variants, RTL behavior, a11y, and keyboard navigation
|
|
21
|
+
- **Accessible** — WCAG AA compliant with full keyboard navigation
|
|
22
|
+
- **TypeScript** — Full type safety and IntelliSense
|
|
23
|
+
- **Themeable** — 4 built-in themes, light/dark mode, customizable design tokens
|
|
24
|
+
- **Regional & Islamic** — Prayer Times, Hijri Calendar, Arabic Numbers, Zakat Calculator
|
|
25
|
+
- **AI/LLM Components** — Chat, Streaming Text, Model Selector, Token Counter
|
|
26
|
+
- **Tree-shakeable** — Only bundle what you use
|
|
25
27
|
|
|
26
|
-
##
|
|
28
|
+
## Quick Start
|
|
27
29
|
|
|
28
30
|
```bash
|
|
29
31
|
npm install noorui-rtl
|
|
30
|
-
# or
|
|
31
|
-
yarn add noorui-rtl
|
|
32
|
-
# or
|
|
33
|
-
pnpm add noorui-rtl
|
|
34
32
|
```
|
|
35
33
|
|
|
36
|
-
## 🚀 Quick Start
|
|
37
|
-
|
|
38
|
-
### 1. Install the package
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npm install noorui-rtl
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### 2. Import the CSS
|
|
45
|
-
|
|
46
|
-
**Option A: Pre-compiled CSS (Recommended - No Tailwind setup needed)**
|
|
47
|
-
|
|
48
|
-
Import the pre-compiled CSS in your root layout or app entry point:
|
|
49
|
-
|
|
50
34
|
```tsx
|
|
51
|
-
// app/layout.tsx or _app.tsx
|
|
52
35
|
import 'noorui-rtl/dist/styles.css'
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
This includes all component styles, CSS variables, theme definitions, and RTL support. **No Tailwind configuration required!**
|
|
56
|
-
|
|
57
|
-
**Option B: Tailwind v4 CSS-first Configuration (For custom Tailwind setups)**
|
|
58
|
-
|
|
59
|
-
If you're already using Tailwind and want to customize the configuration:
|
|
60
|
-
|
|
61
|
-
1. Set up `globals.css` with CSS-first Tailwind v4 config:
|
|
62
|
-
|
|
63
|
-
```css
|
|
64
|
-
@import "tailwindcss";
|
|
65
|
-
|
|
66
|
-
/* Dark mode: class-based toggle */
|
|
67
|
-
@custom-variant dark (&:where(.dark, .dark *));
|
|
68
|
-
|
|
69
|
-
@theme {
|
|
70
|
-
/* Colors — semantic tokens via CSS vars */
|
|
71
|
-
--color-border: hsl(var(--border));
|
|
72
|
-
--color-input: hsl(var(--input));
|
|
73
|
-
--color-ring: hsl(var(--ring));
|
|
74
|
-
--color-background: hsl(var(--background));
|
|
75
|
-
--color-foreground: hsl(var(--foreground));
|
|
76
|
-
--color-primary: hsl(var(--primary));
|
|
77
|
-
--color-primary-foreground: hsl(var(--primary-foreground));
|
|
78
|
-
--color-secondary: hsl(var(--secondary));
|
|
79
|
-
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
|
80
|
-
--color-destructive: hsl(var(--destructive));
|
|
81
|
-
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
|
82
|
-
--color-muted: hsl(var(--muted));
|
|
83
|
-
--color-muted-foreground: hsl(var(--muted-foreground));
|
|
84
|
-
--color-accent: hsl(var(--accent));
|
|
85
|
-
--color-accent-foreground: hsl(var(--accent-foreground));
|
|
86
|
-
--color-popover: hsl(var(--popover));
|
|
87
|
-
--color-popover-foreground: hsl(var(--popover-foreground));
|
|
88
|
-
--color-card: hsl(var(--card));
|
|
89
|
-
--color-card-foreground: hsl(var(--card-foreground));
|
|
90
|
-
|
|
91
|
-
/* Semantic status colors */
|
|
92
|
-
--color-success: hsl(var(--success));
|
|
93
|
-
--color-success-foreground: hsl(var(--success-foreground));
|
|
94
|
-
--color-warning: hsl(var(--warning));
|
|
95
|
-
--color-warning-foreground: hsl(var(--warning-foreground));
|
|
96
|
-
--color-info: hsl(var(--info));
|
|
97
|
-
--color-info-foreground: hsl(var(--info-foreground));
|
|
98
|
-
|
|
99
|
-
/* Border radius */
|
|
100
|
-
--radius-lg: var(--radius);
|
|
101
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
102
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
103
|
-
|
|
104
|
-
/* Font families */
|
|
105
|
-
--font-sans: 'Inter', system-ui, sans-serif;
|
|
106
|
-
--font-arabic: 'IBM Plex Sans Arabic', sans-serif;
|
|
107
|
-
--font-mono: 'JetBrains Mono', monospace;
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
2. Add CSS variables for light/dark themes:
|
|
112
|
-
|
|
113
|
-
```css
|
|
114
|
-
:root {
|
|
115
|
-
/* Core palette */
|
|
116
|
-
--background: 220 13% 99%;
|
|
117
|
-
--foreground: 222.2 84% 4.9%;
|
|
118
|
-
--card: 0 0% 100%;
|
|
119
|
-
--card-foreground: 222.2 84% 4.9%;
|
|
120
|
-
--popover: 0 0% 100%;
|
|
121
|
-
--popover-foreground: 222.2 84% 4.9%;
|
|
122
|
-
--primary: 239 84% 67%;
|
|
123
|
-
--primary-foreground: 210 40% 98%;
|
|
124
|
-
--secondary: 174 72% 56%;
|
|
125
|
-
--secondary-foreground: 174 100% 10%;
|
|
126
|
-
--muted: 210 40% 96.1%;
|
|
127
|
-
--muted-foreground: 215.4 16.3% 46.9%;
|
|
128
|
-
--accent: 210 40% 96.1%;
|
|
129
|
-
--accent-foreground: 222.2 47.4% 11.2%;
|
|
130
|
-
--destructive: 0 84.2% 60.2%;
|
|
131
|
-
--destructive-foreground: 210 40% 98%;
|
|
132
|
-
--border: 214.3 31.8% 91.4%;
|
|
133
|
-
--input: 214.3 31.8% 91.4%;
|
|
134
|
-
--ring: 239 84% 67%;
|
|
135
|
-
--radius: 0.5rem;
|
|
136
|
-
|
|
137
|
-
/* Semantic status colors */
|
|
138
|
-
--success: 142 76% 36%;
|
|
139
|
-
--success-foreground: 143 64% 24%;
|
|
140
|
-
--warning: 38 92% 50%;
|
|
141
|
-
--warning-foreground: 32 81% 29%;
|
|
142
|
-
--info: 217 91% 60%;
|
|
143
|
-
--info-foreground: 224 76% 48%;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
.dark {
|
|
147
|
-
--background: 222.2 84% 4.9%;
|
|
148
|
-
--foreground: 210 40% 98%;
|
|
149
|
-
/* ... rest of dark mode variables */
|
|
150
|
-
}
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
3. Set up `postcss.config.js`:
|
|
154
|
-
|
|
155
|
-
```js
|
|
156
|
-
module.exports = {
|
|
157
|
-
plugins: {
|
|
158
|
-
'@tailwindcss/postcss': {},
|
|
159
|
-
},
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### 3. Wrap your app with providers
|
|
164
|
-
|
|
165
|
-
Add the theme and direction providers to enable all features:
|
|
166
|
-
|
|
167
|
-
```tsx
|
|
168
|
-
import { ThemeProvider } from 'next-themes'
|
|
169
|
-
import { DirectionProvider, DesignSystemProvider } from 'noorui-rtl'
|
|
170
|
-
|
|
171
|
-
export default function RootLayout({ children }) {
|
|
172
|
-
return (
|
|
173
|
-
<html>
|
|
174
|
-
<body>
|
|
175
|
-
<ThemeProvider attribute="class" enableSystem={true}>
|
|
176
|
-
<DirectionProvider>
|
|
177
|
-
<DesignSystemProvider defaultTheme="cozy">
|
|
178
|
-
{children}
|
|
179
|
-
</DesignSystemProvider>
|
|
180
|
-
</DirectionProvider>
|
|
181
|
-
</ThemeProvider>
|
|
182
|
-
</body>
|
|
183
|
-
</html>
|
|
184
|
-
)
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
**What each provider does:**
|
|
189
|
-
- **`ThemeProvider`** (next-themes): Light/Dark mode with system preference support
|
|
190
|
-
- **`DirectionProvider`**: RTL/LTR direction and locale switching (ar/en)
|
|
191
|
-
- **`DesignSystemProvider`**: Design theme variants (minimal/futuristic/cozy/artistic)
|
|
192
|
-
|
|
193
|
-
**Switching themes programmatically:**
|
|
194
|
-
|
|
195
|
-
```tsx
|
|
196
|
-
import { useDesignSystem } from 'noorui-rtl'
|
|
197
|
-
import { useTheme } from 'next-themes'
|
|
198
|
-
import { useDirection } from 'noorui-rtl'
|
|
199
|
-
|
|
200
|
-
function Settings() {
|
|
201
|
-
const { designTheme, setDesignTheme } = useDesignSystem()
|
|
202
|
-
const { theme, setTheme } = useTheme()
|
|
203
|
-
const { direction, setDirection } = useDirection()
|
|
204
|
-
|
|
205
|
-
return (
|
|
206
|
-
<div>
|
|
207
|
-
{/* Design theme */}
|
|
208
|
-
<select value={designTheme} onChange={(e) => setDesignTheme(e.target.value)}>
|
|
209
|
-
<option value="minimal">Minimal</option>
|
|
210
|
-
<option value="futuristic">Futuristic</option>
|
|
211
|
-
<option value="cozy">Cozy</option>
|
|
212
|
-
<option value="artistic">Artistic</option>
|
|
213
|
-
</select>
|
|
214
|
-
|
|
215
|
-
{/* Light/Dark mode */}
|
|
216
|
-
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
|
|
217
|
-
Toggle {theme === 'dark' ? 'Light' : 'Dark'} Mode
|
|
218
|
-
</button>
|
|
219
|
-
|
|
220
|
-
{/* Direction */}
|
|
221
|
-
<button onClick={() => setDirection(direction === 'rtl' ? 'ltr' : 'rtl')}>
|
|
222
|
-
Switch to {direction === 'rtl' ? 'LTR' : 'RTL'}
|
|
223
|
-
</button>
|
|
224
|
-
</div>
|
|
225
|
-
)
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### 4. Start using components
|
|
230
|
-
|
|
231
|
-
```tsx
|
|
232
36
|
import { Button, Card, CardHeader, CardTitle, CardContent } from 'noorui-rtl'
|
|
233
37
|
|
|
234
38
|
export default function App() {
|
|
@@ -245,225 +49,62 @@ export default function App() {
|
|
|
245
49
|
}
|
|
246
50
|
```
|
|
247
51
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
### Core UI (71 components)
|
|
251
|
-
|
|
252
|
-
**Forms**: Button, Input, Label, Textarea, Checkbox, Radio, Select, Switch, Slider, Form
|
|
253
|
-
|
|
254
|
-
**Layout**: Card, Separator, Tabs, Accordion, Collapsible
|
|
255
|
-
|
|
256
|
-
**Navigation**: Breadcrumb, Pagination, Command
|
|
257
|
-
|
|
258
|
-
**Feedback**: Alert, Toast, Progress, Skeleton, Badge, Avatar, Loading Spinner
|
|
259
|
-
|
|
260
|
-
**Overlays**: Dialog, Sheet, Popover, Tooltip, Dropdown Menu, Context Menu
|
|
261
|
-
|
|
262
|
-
**Data**: Table, DataTable, Chart, Stats Card, Feature Card, Empty State, Listing Card
|
|
263
|
-
|
|
264
|
-
**Advanced**: File Upload, Rich Text Editor, Date Picker, Time Picker, Number Input, Dashboard Shell, User Menu, Notification Center, Stepper, Timeline
|
|
265
|
-
|
|
266
|
-
### GCC-Specific (5 components)
|
|
267
|
-
|
|
268
|
-
- **Prayer Times**: Display Islamic prayer times with countdown and Adhan notifications
|
|
269
|
-
- **Hijri Date**: Dual Gregorian/Hijri calendar display
|
|
270
|
-
- **Arabic Number**: Arabic-Indic numeral utilities and SAR currency formatting
|
|
271
|
-
- **Zakat Calculator**: Calculate Islamic Zakat with export/sharing
|
|
272
|
-
- **Calendar**: Date picker with Hijri support and event markers
|
|
273
|
-
|
|
274
|
-
### AI/LLM Components (10 experimental) 🧪
|
|
275
|
-
|
|
276
|
-
Chat Message, Streaming Text, Prompt Input, Thinking Indicator, Message Actions, Model Selector, Parameter Slider, Token Counter, Conversation History, Workflow Canvas
|
|
277
|
-
|
|
278
|
-
> Note: AI/LLM components are functional but APIs may evolve based on feedback.
|
|
279
|
-
|
|
280
|
-
## 🎨 RTL Support
|
|
281
|
-
|
|
282
|
-
All components support RTL out of the box:
|
|
283
|
-
|
|
284
|
-
```tsx
|
|
285
|
-
'use client'
|
|
286
|
-
|
|
287
|
-
import { useState } from 'react'
|
|
288
|
-
import { Button, Tabs, TabsList, TabsTrigger } from 'noorui-rtl'
|
|
289
|
-
|
|
290
|
-
export default function App() {
|
|
291
|
-
const [direction, setDirection] = useState<'ltr' | 'rtl'>('ltr')
|
|
292
|
-
|
|
293
|
-
return (
|
|
294
|
-
<div dir={direction}>
|
|
295
|
-
<Button onClick={() => setDirection(d => d === 'ltr' ? 'rtl' : 'ltr')}>
|
|
296
|
-
Toggle Direction
|
|
297
|
-
</Button>
|
|
298
|
-
|
|
299
|
-
<Tabs defaultValue="tab1">
|
|
300
|
-
<TabsList>
|
|
301
|
-
<TabsTrigger value="tab1">Tab 1</TabsTrigger>
|
|
302
|
-
<TabsTrigger value="tab2">Tab 2</TabsTrigger>
|
|
303
|
-
</TabsList>
|
|
304
|
-
</Tabs>
|
|
305
|
-
</div>
|
|
306
|
-
)
|
|
307
|
-
}
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
Components automatically adapt to text direction using logical properties.
|
|
311
|
-
|
|
312
|
-
## 🎨 Custom Themes
|
|
313
|
-
|
|
314
|
-
The theme system is powered by CSS custom properties. You can create your own themes by defining a CSS class that overrides these variables.
|
|
315
|
-
|
|
316
|
-
### 1. Define your theme CSS
|
|
317
|
-
|
|
318
|
-
Add a `.theme-yourname` class to your `globals.css` with light and dark mode variants:
|
|
319
|
-
|
|
320
|
-
```css
|
|
321
|
-
/* Light mode */
|
|
322
|
-
.theme-ocean {
|
|
323
|
-
--color-background: hsl(200 20% 98%);
|
|
324
|
-
--color-foreground: hsl(210 40% 10%);
|
|
325
|
-
--color-primary: hsl(200 80% 50%);
|
|
326
|
-
--color-primary-foreground: hsl(0 0% 100%);
|
|
327
|
-
--color-secondary: hsl(180 60% 45%);
|
|
328
|
-
--color-secondary-foreground: hsl(180 100% 10%);
|
|
329
|
-
--color-muted: hsl(200 20% 94%);
|
|
330
|
-
--color-muted-foreground: hsl(200 10% 40%);
|
|
331
|
-
--color-accent: hsl(200 20% 94%);
|
|
332
|
-
--color-accent-foreground: hsl(210 40% 10%);
|
|
333
|
-
--color-card: hsl(0 0% 100%);
|
|
334
|
-
--color-card-foreground: hsl(210 40% 10%);
|
|
335
|
-
--color-popover: hsl(0 0% 100%);
|
|
336
|
-
--color-popover-foreground: hsl(210 40% 10%);
|
|
337
|
-
--color-border: hsl(200 20% 88%);
|
|
338
|
-
--color-input: hsl(200 20% 88%);
|
|
339
|
-
--color-ring: hsl(200 80% 50%);
|
|
340
|
-
--color-destructive: hsl(0 84% 60%);
|
|
341
|
-
--color-destructive-foreground: hsl(0 0% 100%);
|
|
342
|
-
--radius: 0.75rem;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/* Dark mode */
|
|
346
|
-
.dark .theme-ocean,
|
|
347
|
-
.theme-ocean.dark {
|
|
348
|
-
--color-background: hsl(210 40% 8%);
|
|
349
|
-
--color-foreground: hsl(200 20% 95%);
|
|
350
|
-
--color-primary: hsl(200 80% 60%);
|
|
351
|
-
--color-primary-foreground: hsl(210 40% 8%);
|
|
352
|
-
--color-card: hsl(210 35% 12%);
|
|
353
|
-
--color-card-foreground: hsl(200 20% 95%);
|
|
354
|
-
--color-border: hsl(210 30% 20%);
|
|
355
|
-
--color-input: hsl(210 30% 20%);
|
|
356
|
-
}
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
See `styles/globals.css` in the package for all 4 built-in themes as a reference.
|
|
360
|
-
|
|
361
|
-
### 2. Use your theme
|
|
362
|
-
|
|
363
|
-
Pass your custom theme name to the `DesignSystemProvider`:
|
|
364
|
-
|
|
365
|
-
```tsx
|
|
366
|
-
<DesignSystemProvider defaultTheme="ocean">
|
|
367
|
-
{children}
|
|
368
|
-
</DesignSystemProvider>
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
The provider accepts any string as a theme name and applies the corresponding `.theme-{name}` CSS class to `<html>`.
|
|
52
|
+
For RTL support, Tailwind setup, theming, and provider configuration, see the **[Getting Started guide](https://noorui.com/getting-started)**.
|
|
372
53
|
|
|
373
|
-
|
|
54
|
+
## Components
|
|
374
55
|
|
|
375
|
-
|
|
376
|
-
|----------|-------------|
|
|
377
|
-
| `--color-background` / `--color-foreground` | Page background and text |
|
|
378
|
-
| `--color-primary` / `--color-primary-foreground` | Brand/accent color and its contrast |
|
|
379
|
-
| `--color-secondary` / `--color-secondary-foreground` | Secondary accent |
|
|
380
|
-
| `--color-muted` / `--color-muted-foreground` | Muted backgrounds and subdued text |
|
|
381
|
-
| `--color-accent` / `--color-accent-foreground` | Hover/active states |
|
|
382
|
-
| `--color-card` / `--color-card-foreground` | Card surfaces |
|
|
383
|
-
| `--color-popover` / `--color-popover-foreground` | Popover/dropdown surfaces |
|
|
384
|
-
| `--color-border` / `--color-input` / `--color-ring` | Borders, inputs, focus rings |
|
|
385
|
-
| `--color-destructive` / `--color-destructive-foreground` | Destructive actions |
|
|
386
|
-
| `--color-success` / `--color-warning` / `--color-info` | Semantic status colors (optional) |
|
|
387
|
-
| `--radius` | Base border radius |
|
|
56
|
+
**Forms** — Button, Input, Textarea, Checkbox, Radio, Select, Switch, Slider, DatePicker, TimePicker, FileUpload, NumberInput, Calendar, Form
|
|
388
57
|
|
|
389
|
-
|
|
58
|
+
**Layout** — Card, Separator, Tabs, Accordion, Collapsible, DashboardShell, Stepper
|
|
390
59
|
|
|
391
|
-
|
|
60
|
+
**Navigation** — Breadcrumb, Pagination, Command
|
|
392
61
|
|
|
393
|
-
|
|
62
|
+
**Feedback** — Alert, Callout, Toast, Progress, Skeleton, Badge, Avatar, LoadingSpinner, Kbd
|
|
394
63
|
|
|
395
|
-
|
|
396
|
-
import { DirectionProvider, useDirection } from 'noorui-rtl'
|
|
397
|
-
|
|
398
|
-
function App() {
|
|
399
|
-
return (
|
|
400
|
-
<DirectionProvider>
|
|
401
|
-
<YourApp />
|
|
402
|
-
</DirectionProvider>
|
|
403
|
-
)
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function YourComponent() {
|
|
407
|
-
const { direction, setDirection, locale } = useDirection()
|
|
408
|
-
|
|
409
|
-
return (
|
|
410
|
-
<button onClick={() => setDirection(direction === 'ltr' ? 'rtl' : 'ltr')}>
|
|
411
|
-
Current: {direction}
|
|
412
|
-
</button>
|
|
413
|
-
)
|
|
414
|
-
}
|
|
415
|
-
```
|
|
64
|
+
**Overlays** — Dialog, Sheet, Popover, Tooltip, DropdownMenu, ContextMenu
|
|
416
65
|
|
|
417
|
-
|
|
66
|
+
**Data** — Table, DataTable, Chart, StatsCard, ListingCard, FeatureCard, EmptyState, Timeline, Blockquote
|
|
418
67
|
|
|
419
|
-
|
|
68
|
+
**Regional & Islamic** — PrayerTimes, HijriDate, ArabicNumber, ZakatCalculator
|
|
420
69
|
|
|
421
|
-
|
|
422
|
-
- [Components](https://noorui.com/components)
|
|
423
|
-
- [Storybook](https://storybook.noorui.com) - **Interactive component playground with 749 stories**
|
|
424
|
-
- [RTL Guide](https://noorui.com/rtl-guide)
|
|
425
|
-
- [Utilities & Hooks](https://noorui.com/utilities)
|
|
426
|
-
- [Examples](https://noorui.com/examples)
|
|
427
|
-
- [Design Tokens](https://noorui.com/tokens)
|
|
70
|
+
**AI/LLM** — ChatMessage, PromptInput, StreamingText, ThinkingIndicator, ModelSelector, TokenCounter, ParameterSlider, ConversationHistory, MessageActions
|
|
428
71
|
|
|
429
|
-
|
|
72
|
+
**Composite** — Carousel, NotificationCenter, UserMenu, ReactionPicker, UserBadge
|
|
430
73
|
|
|
431
|
-
|
|
74
|
+
Browse all components at **[noorui.com/components](https://noorui.com/components)** or in **[Storybook](https://storybook.noorui.com)**.
|
|
432
75
|
|
|
433
|
-
##
|
|
76
|
+
## Documentation
|
|
434
77
|
|
|
435
|
-
|
|
436
|
-
-
|
|
437
|
-
-
|
|
438
|
-
-
|
|
439
|
-
-
|
|
78
|
+
- [Getting Started](https://noorui.com/getting-started) — Installation, CSS setup, providers
|
|
79
|
+
- [Components](https://noorui.com/components) — All 77+ components with live examples
|
|
80
|
+
- [RTL Guide](https://noorui.com/rtl-guide) — Logical properties, bidirectional patterns
|
|
81
|
+
- [Themes](https://noorui.com/themes) — Built-in themes and custom theme creation
|
|
82
|
+
- [Design Tokens](https://noorui.com/tokens) — CSS variables reference
|
|
83
|
+
- [Examples](https://noorui.com/examples) — Full application demos (Healthcare, Banking, Hotel, Esports, MyMantras)
|
|
84
|
+
- [Email Templates](https://noorui.com/email-templates) — 21 bilingual MJML templates
|
|
85
|
+
- [Storybook](https://storybook.noorui.com) — Interactive component playground
|
|
86
|
+
- [llms.txt](https://noorui.com/llms.txt) — AI assistant integration
|
|
440
87
|
|
|
441
|
-
|
|
88
|
+
## Contributing
|
|
442
89
|
|
|
443
|
-
|
|
90
|
+
Contributions are welcome! See the [Contributing Guide](CONTRIBUTING.md).
|
|
444
91
|
|
|
445
|
-
|
|
92
|
+
This project includes [Claude Code agents](.claude/) for component creation, story generation, visual QA, and i18n validation.
|
|
446
93
|
|
|
447
|
-
##
|
|
94
|
+
## Support
|
|
448
95
|
|
|
449
|
-
|
|
450
|
-
- [
|
|
451
|
-
- [
|
|
452
|
-
- [Phosphor Icons](https://phosphoricons.com/) - Beautiful duotone icons
|
|
453
|
-
- [Next.js](https://nextjs.org/) - React framework
|
|
96
|
+
- [Discord](https://discord.gg/gvrqU2WG)
|
|
97
|
+
- [GitHub Discussions](https://github.com/ositaka/noor-ui/discussions)
|
|
98
|
+
- [GitHub Issues](https://github.com/ositaka/noor-ui/issues)
|
|
454
99
|
|
|
455
|
-
##
|
|
100
|
+
## Credits
|
|
456
101
|
|
|
457
|
-
-
|
|
458
|
-
- 📧 Email: info@ositaka.com
|
|
459
|
-
- 🐛 Issues: [GitHub Issues](https://github.com/ositaka/noor-ui/issues)
|
|
460
|
-
- 💬 Discussions: [GitHub Discussions](https://github.com/ositaka/noor-ui/discussions)
|
|
461
|
-
- 🌐 Website: [noorui.com](https://noorui.com)
|
|
102
|
+
Built with [Radix UI](https://www.radix-ui.com/), [Tailwind CSS](https://tailwindcss.com/), [Phosphor Icons](https://phosphoricons.com/), and [Next.js](https://nextjs.org/).
|
|
462
103
|
|
|
463
|
-
##
|
|
104
|
+
## License
|
|
464
105
|
|
|
465
|
-
|
|
106
|
+
[MIT](LICENSE)
|
|
466
107
|
|
|
467
108
|
---
|
|
468
109
|
|
|
469
|
-
**Built with
|
|
110
|
+
**Built with love by [Nuno Marques](https://ositaka.com)**
|