topiray-auth-react 1.0.0-alpha.7

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/README.md ADDED
@@ -0,0 +1,769 @@
1
+ # Topiray Auth React Component Library
2
+
3
+ A comprehensive, themeable React component library for authentication flows. Built with TypeScript, CSS Modules, and designed for maximum customization and accessibility.
4
+
5
+ ## Features
6
+
7
+ - 🎨 **Fully Themeable** - Customize colors, fonts, spacing, and more
8
+ - 🔧 **CSS Modules** - Strongly-typed, scoped styling
9
+ - 📱 **Responsive Design** - Mobile-first approach with breakpoint support
10
+ - ♿ **Accessible** - ARIA labels, keyboard navigation, focus management
11
+ - 🔐 **Complete Auth Flow** - Sign in/up, 2FA, email verification, password reset
12
+ - ⚡ **TypeScript** - Full type safety and IntelliSense support
13
+ - 🎯 **Tree Shakeable** - Import only what you need
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install topiray-auth-react
19
+ # or
20
+ yarn add topiray-auth-react
21
+ ```
22
+
23
+ ### Peer Dependencies
24
+
25
+ ```bash
26
+ npm install react react-dom lucide-react @mui/material
27
+ ```
28
+
29
+ ### CSS Import
30
+
31
+ **Important**: You must import the CSS file for proper styling:
32
+
33
+ ```tsx
34
+ // Import the CSS file in your main App component or index file
35
+ import 'topiray-auth-react/dist/topiray-auth-react.css'
36
+ ```
37
+
38
+ Or if you're using a bundler that supports CSS imports:
39
+
40
+ ```css
41
+ /* In your main CSS file */
42
+ @import 'topiray-auth-react/dist/topiray-auth-react.css';
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ```tsx
48
+ import React from 'react'
49
+ import {
50
+ ThemeProvider,
51
+ defaultTheme,
52
+ TwoPanelLayout,
53
+ AuthCard,
54
+ SignInForm
55
+ } from 'topiray-auth-react'
56
+
57
+ // Import the CSS file
58
+ import 'topiray-auth-react/dist/topiray-auth-react.css'
59
+
60
+ function App() {
61
+ const handleSignIn = (email: string, password: string) => {
62
+ console.log('Sign in:', { email, password })
63
+ }
64
+
65
+ return (
66
+ <ThemeProvider theme={defaultTheme}>
67
+ <TwoPanelLayout
68
+ rightContent={
69
+ <AuthCard>
70
+ <SignInForm
71
+ onSubmit={handleSignIn}
72
+ onForgotPassword={() => console.log('Forgot password')}
73
+ onSignUp={() => console.log('Sign up')}
74
+ onSocialLogin={(provider) => console.log('Social:', provider)}
75
+ authProviders={['google', 'apple', 'facebook']}
76
+ />
77
+ </AuthCard>
78
+ }
79
+ />
80
+ </ThemeProvider>
81
+ )
82
+ }
83
+ ```
84
+
85
+ ## Components
86
+
87
+ ### Auth Components
88
+
89
+ #### AuthCard
90
+ Container wrapper for auth forms with consistent styling.
91
+
92
+ ```tsx
93
+ import { AuthCard } from 'topiray-auth-react'
94
+
95
+ <AuthCard>
96
+ {/* Your auth form content */}
97
+ </AuthCard>
98
+ ```
99
+
100
+ #### SignInForm
101
+ Complete sign-in form with email/password and customizable social login options.
102
+
103
+ ```tsx
104
+ import { SignInForm } from 'topiray-auth-react'
105
+
106
+ <SignInForm
107
+ onSubmit={(email, password) => handleSignIn(email, password)}
108
+ onForgotPassword={() => navigate('/forgot-password')}
109
+ onSignUp={() => navigate('/sign-up')}
110
+ onSocialLogin={(provider) => handleSocialLogin(provider)}
111
+ authProviders={['google', 'apple', 'facebook']}
112
+ isLoading={isSigningIn}
113
+ logoSrc="/your-logo.png"
114
+ />
115
+ ```
116
+
117
+ #### SignUpForm
118
+ Account creation form with business/individual selection and customizable social login.
119
+
120
+ ```tsx
121
+ import { SignUpForm } from 'topiray-auth-react'
122
+
123
+ <SignUpForm
124
+ onSubmit={(email, password, accountType) => handleSignUp(email, password, accountType)}
125
+ onSignIn={() => navigate('/sign-in')}
126
+ onSocialLogin={(provider) => handleSocialLogin(provider)}
127
+ authProviders={['google', 'apple', 'facebook']}
128
+ isLoading={isSigningUp}
129
+ logoSrc="/your-logo.png"
130
+ />
131
+ ```
132
+
133
+ #### ForgottenPasswordForm
134
+ Password reset request form.
135
+
136
+ ```tsx
137
+ import { ForgottenPasswordForm } from 'topiray-auth-react'
138
+
139
+ <ForgottenPasswordForm
140
+ onSubmit={(email) => handlePasswordReset(email)}
141
+ isLoading={isLoading}
142
+ />
143
+ ```
144
+
145
+ #### VerifyEmailForm
146
+ Email verification flow with resend functionality.
147
+
148
+ ```tsx
149
+ import { VerifyEmailForm } from 'topiray-auth-react'
150
+
151
+ <VerifyEmailForm
152
+ onSubmit={() => navigate('/sign-in')}
153
+ onResendEmail={() => handleResendEmail()}
154
+ email="user@example.com"
155
+ isLoading={isLoading}
156
+ />
157
+ ```
158
+
159
+ ### Two-Factor Authentication
160
+
161
+ #### TwoFactorSetupForm
162
+ QR code setup for authenticator apps.
163
+
164
+ ```tsx
165
+ import { TwoFactorSetupForm } from 'topiray-auth-react'
166
+
167
+ <TwoFactorSetupForm
168
+ onNext={() => navigate('/2fa/verify')}
169
+ onCancel={() => navigate('/dashboard')}
170
+ qrCodeUri="otpauth://totp/App:user@example.com?secret=SECRET&issuer=App"
171
+ sharedKey="JBSWY3DPEHPK3PXP"
172
+ isLoading={isLoading}
173
+ />
174
+ ```
175
+
176
+ #### TwoFactorSetupEnterVerificationForm
177
+ 6-digit code entry with auto-focus and paste support.
178
+
179
+ ```tsx
180
+ import { TwoFactorSetupEnterVerificationForm } from 'topiray-auth-react'
181
+
182
+ <TwoFactorSetupEnterVerificationForm
183
+ onVerify={(code) => handleVerification(code)}
184
+ isLoading={isVerifying}
185
+ error={error}
186
+ backRoute="/2fa/setup"
187
+ />
188
+ ```
189
+
190
+ #### TwoFactorSetupCompleteForm
191
+ Backup codes display with copy/download functionality.
192
+
193
+ ```tsx
194
+ import { TwoFactorSetupCompleteForm } from 'topiray-auth-react'
195
+
196
+ <TwoFactorSetupCompleteForm
197
+ onDone={() => navigate('/dashboard')}
198
+ backupCodes={recoveryCodes}
199
+ isLoading={isLoading}
200
+ />
201
+ ```
202
+
203
+ ### Layout Components
204
+
205
+ #### TwoPanelLayout
206
+ Responsive layout with left branding panel and right content area.
207
+
208
+ ```tsx
209
+ import { TwoPanelLayout } from 'topiray-auth-react'
210
+
211
+ <TwoPanelLayout
212
+ leftContent={<YourBrandingContent />}
213
+ rightContent={<YourAuthForm />}
214
+ leftBackgroundImage="/background.jpg"
215
+ logoSrc="/logo.png"
216
+ />
217
+ ```
218
+
219
+ #### NavLinksLayout
220
+ Flexible content layout for pages with navigation.
221
+
222
+ ```tsx
223
+ import { NavLinksLayout } from 'topiray-auth-react'
224
+
225
+ <NavLinksLayout
226
+ middle={<MainContent />}
227
+ right={<SidebarContent />}
228
+ />
229
+ ```
230
+
231
+ ### Common Components
232
+
233
+ #### Button
234
+ Versatile button with loading states and variants.
235
+
236
+ ```tsx
237
+ import { Button } from 'topiray-auth-react'
238
+
239
+ <Button variant="primary" isLoading={isLoading} fullWidth>
240
+ Sign In
241
+ </Button>
242
+
243
+ <Button variant="secondary" icon="google">
244
+ Sign in with Google
245
+ </Button>
246
+ ```
247
+
248
+ #### AlertMessage
249
+ Dismissible alert messages for different states.
250
+
251
+ ```tsx
252
+ import { AlertMessage } from 'topiray-auth-react'
253
+
254
+ <AlertMessage
255
+ type="error"
256
+ message="Invalid credentials"
257
+ dismissible
258
+ onDismiss={() => setError(null)}
259
+ />
260
+ ```
261
+
262
+ #### SocialLoginButtons
263
+ Pre-configured social login buttons.
264
+
265
+ ```tsx
266
+ import { SocialLoginButtons } from 'topiray-auth-react'
267
+
268
+ <SocialLoginButtons
269
+ onSocialLogin={(provider) => handleSocialLogin(provider)}
270
+ providers={['google', 'apple', 'facebook']}
271
+ orientation="vertical"
272
+ isLoading={isLoading}
273
+ />
274
+ ```
275
+
276
+ ### Customizing Social Login Providers
277
+
278
+ You can customize which social login providers are displayed using the `authProviders` prop on both `SignInForm` and `SignUpForm`:
279
+
280
+ ```tsx
281
+ // Show only Google and Apple
282
+ <SignInForm
283
+ authProviders={['google', 'apple']}
284
+ onSocialLogin={(provider) => handleSocialLogin(provider)}
285
+ // ... other props
286
+ />
287
+
288
+ // Show all available providers (default)
289
+ <SignUpForm
290
+ authProviders={['apple', 'google', 'facebook']}
291
+ onSocialLogin={(provider) => handleSocialLogin(provider)}
292
+ // ... other props
293
+ />
294
+
295
+ // Show only Google
296
+ <SignInForm
297
+ authProviders={['google']}
298
+ onSocialLogin={(provider) => handleSocialLogin(provider)}
299
+ // ... other props
300
+ />
301
+
302
+ // Hide social login entirely by setting empty array or omitting the prop
303
+ <SignInForm
304
+ authProviders={[]}
305
+ // ... other props (onSocialLogin not needed if no providers)
306
+ />
307
+ ```
308
+
309
+ **Available providers:**
310
+ - `'apple'` - Apple Sign In
311
+ - `'google'` - Google Sign In
312
+ - `'facebook'` - Facebook Login
313
+
314
+ **Default behavior:** If `authProviders` is not specified, it defaults to `['apple', 'google', 'facebook']`.
315
+
316
+ ## Real-World Usage Examples
317
+
318
+ ### Complete Sign-In Page
319
+
320
+ ```tsx
321
+ import React, { useState, useEffect } from 'react'
322
+ import { useNavigate, useLocation } from 'react-router-dom'
323
+ import {
324
+ ThemeProvider,
325
+ defaultTheme,
326
+ TwoPanelLayout,
327
+ AuthCard,
328
+ SignInForm,
329
+ AlertMessage
330
+ } from 'topiray-auth-react'
331
+
332
+ // Import the CSS file
333
+ import 'topiray-auth-react/dist/topiray-auth-react.css'
334
+
335
+ function SignInPage() {
336
+ const navigate = useNavigate()
337
+ const location = useLocation()
338
+ const [error, setError] = useState<string | null>(null)
339
+ const [isLoading, setIsLoading] = useState(false)
340
+
341
+ // Get success message from registration
342
+ const successMessage = location.state?.message
343
+
344
+ const handleSignIn = async (email: string, password: string) => {
345
+ try {
346
+ setError(null)
347
+ setIsLoading(true)
348
+
349
+ const result = await signInAPI(email, password)
350
+
351
+ if (result.succeeded) {
352
+ navigate('/dashboard')
353
+ } else if (result.requiresTwoFactor) {
354
+ navigate('/2fa/signin', { state: { userId: result.userId } })
355
+ } else if (result.isNotAllowed) {
356
+ navigate(`/verify-email?email=${encodeURIComponent(email)}`)
357
+ } else {
358
+ setError('Invalid email or password.')
359
+ }
360
+ } catch (error) {
361
+ setError('An error occurred during sign in.')
362
+ } finally {
363
+ setIsLoading(false)
364
+ }
365
+ }
366
+
367
+ const handleSocialLogin = async (provider: 'google' | 'apple' | 'facebook') => {
368
+ try {
369
+ setError(null)
370
+ setIsLoading(true)
371
+
372
+ // Initiate social login flow
373
+ await socialSignInAPI(provider)
374
+ } catch (error) {
375
+ setError(`Failed to sign in with ${provider}`)
376
+ } finally {
377
+ setIsLoading(false)
378
+ }
379
+ }
380
+
381
+ return (
382
+ <ThemeProvider theme={defaultTheme}>
383
+ <TwoPanelLayout
384
+ rightContent={
385
+ <AuthCard>
386
+ {successMessage && (
387
+ <AlertMessage message={successMessage} type="success" />
388
+ )}
389
+ {error && (
390
+ <AlertMessage message={error} type="error" />
391
+ )}
392
+ <SignInForm
393
+ onSubmit={handleSignIn}
394
+ onForgotPassword={() => navigate('/forgot-password')}
395
+ onSignUp={() => navigate('/sign-up')}
396
+ onSocialLogin={handleSocialLogin}
397
+ authProviders={['google', 'apple']} // Only show Google and Apple
398
+ isLoading={isLoading}
399
+ />
400
+ </AuthCard>
401
+ }
402
+ />
403
+ </ThemeProvider>
404
+ )
405
+ }
406
+ ```
407
+
408
+ ### Two-Factor Setup with QR Code
409
+
410
+ ```tsx
411
+ import React, { useEffect, useState } from 'react'
412
+ import { useNavigate } from 'react-router-dom'
413
+ import QRCode from 'qrcode'
414
+ import {
415
+ TwoPanelLayout,
416
+ AuthCard,
417
+ TwoFactorSetupForm,
418
+ AlertMessage
419
+ } from 'topiray-auth-react'
420
+
421
+ function TwoFactorSetupPage() {
422
+ const navigate = useNavigate()
423
+ const [qrCodeDataUrl, setQrCodeDataUrl] = useState<string | null>(null)
424
+ const [sharedKey, setSharedKey] = useState<string | null>(null)
425
+ const [error, setError] = useState<string | null>(null)
426
+ const [isLoading, setIsLoading] = useState(false)
427
+
428
+ useEffect(() => {
429
+ generateQRCode()
430
+ }, [])
431
+
432
+ const generateQRCode = async () => {
433
+ try {
434
+ setIsLoading(true)
435
+ const result = await createAuthenticatorKeyAPI()
436
+
437
+ if (result.authenticatorUri && result.sharedKey) {
438
+ const qrDataUrl = await QRCode.toDataURL(result.authenticatorUri, {
439
+ width: 200,
440
+ margin: 2
441
+ })
442
+
443
+ setQrCodeDataUrl(qrDataUrl)
444
+ setSharedKey(result.sharedKey)
445
+
446
+ // Render QR code
447
+ setTimeout(() => {
448
+ const container = document.getElementById('qr-code-container')
449
+ if (container && qrDataUrl) {
450
+ container.innerHTML = `<img src="${qrDataUrl}" alt="QR Code" />`
451
+ }
452
+ }, 100)
453
+ } else {
454
+ setError('Failed to generate QR code.')
455
+ }
456
+ } catch (error) {
457
+ setError('Failed to generate QR code.')
458
+ } finally {
459
+ setIsLoading(false)
460
+ }
461
+ }
462
+
463
+ return (
464
+ <TwoPanelLayout
465
+ rightContent={
466
+ <AuthCard>
467
+ {error && <AlertMessage message={error} type="error" />}
468
+ <TwoFactorSetupForm
469
+ onNext={() => navigate('/2fa/verify')}
470
+ onCancel={() => navigate('/dashboard')}
471
+ qrCodeUri={qrCodeDataUrl}
472
+ sharedKey={sharedKey}
473
+ isLoading={isLoading}
474
+ />
475
+ </AuthCard>
476
+ }
477
+ />
478
+ )
479
+ }
480
+ ```
481
+
482
+ ## Theming
483
+
484
+ ### Using Built-in Themes
485
+
486
+ ```tsx
487
+ import { ThemeProvider, defaultTheme, darkTheme } from 'topiray-auth-react'
488
+
489
+ // Light theme
490
+ <ThemeProvider theme={defaultTheme}>
491
+ <App />
492
+ </ThemeProvider>
493
+
494
+ // Dark theme
495
+ <ThemeProvider theme={darkTheme}>
496
+ <App />
497
+ </ThemeProvider>
498
+ ```
499
+
500
+ ### Creating Custom Themes
501
+
502
+ ```tsx
503
+ import { createCustomTheme } from 'topiray-auth-react'
504
+
505
+ const corporateTheme = createCustomTheme({
506
+ colors: {
507
+ primary: '#0066cc',
508
+ secondary: '#6b7280',
509
+ background: '#ffffff',
510
+ surface: '#f9fafb',
511
+ text: '#111827',
512
+ textSecondary: '#6b7280',
513
+ border: '#d1d5db',
514
+ success: '#10b981',
515
+ warning: '#f59e0b',
516
+ error: '#ef4444',
517
+ info: '#3b82f6',
518
+ hover: '#f3f4f6',
519
+ active: '#e5e7eb',
520
+ disabled: '#9ca3af',
521
+ inputBackground: '#ffffff',
522
+ inputBorder: '#d1d5db',
523
+ inputText: '#111827',
524
+ inputPlaceholder: '#9ca3af',
525
+ buttonPrimary: '#0066cc',
526
+ buttonPrimaryText: '#ffffff',
527
+ buttonSecondary: '#6b7280',
528
+ buttonSecondaryText: '#ffffff',
529
+ buttonSocial: '#374151',
530
+ buttonSocialText: '#ffffff'
531
+ },
532
+ brand: {
533
+ logo: '/corporate-logo.png',
534
+ logoAlt: 'Corporate Logo'
535
+ },
536
+ customization: {
537
+ showFormHeader: true,
538
+ showSocialLogin: true,
539
+ showBackArrow: true,
540
+ showLogo: true,
541
+ roundedCorners: true,
542
+ animations: true
543
+ }
544
+ })
545
+
546
+ <ThemeProvider theme={corporateTheme}>
547
+ <App />
548
+ </ThemeProvider>
549
+ ```
550
+
551
+ ### Advanced Theme Customization
552
+
553
+ ```tsx
554
+ const advancedTheme = createCustomTheme({
555
+ colors: {
556
+ // Custom color palette
557
+ primary: '#7c3aed',
558
+ secondary: '#64748b',
559
+ // ... other colors
560
+ },
561
+ components: {
562
+ spacing: {
563
+ xs: '0.25rem',
564
+ sm: '0.5rem',
565
+ md: '1rem',
566
+ lg: '1.5rem',
567
+ xl: '2rem'
568
+ },
569
+ borderRadius: {
570
+ sm: '0.25rem',
571
+ md: '0.5rem',
572
+ lg: '0.75rem',
573
+ xl: '1rem'
574
+ },
575
+ typography: {
576
+ fontFamily: '"Inter", system-ui, sans-serif',
577
+ fontSize: {
578
+ xs: '0.75rem',
579
+ sm: '0.875rem',
580
+ md: '1rem',
581
+ lg: '1.125rem',
582
+ xl: '1.25rem',
583
+ xxl: '1.5rem'
584
+ }
585
+ }
586
+ },
587
+ customization: {
588
+ backgroundImage: '/custom-background.jpg',
589
+ leftPanelContent: <CustomBrandingComponent />
590
+ }
591
+ })
592
+ ```
593
+
594
+ ## CSS Custom Properties
595
+
596
+ The library uses CSS custom properties for theming. Make sure to import the CSS file first, then you can override these properties:
597
+
598
+ ```tsx
599
+ // First, import the CSS file
600
+ import 'topiray-auth-react/dist/topiray-auth-react.css'
601
+ ```
602
+
603
+ ```css
604
+ /* Then override custom properties in your CSS */
605
+ :root {
606
+ --topiray-color-primary: #your-brand-color;
607
+ --topiray-color-surface: #your-surface-color;
608
+ --topiray-font-family: 'Your Font', sans-serif;
609
+ --topiray-radius-md: 12px;
610
+ --topiray-spacing-lg: 24px;
611
+ }
612
+ ```
613
+
614
+ ## Integration Patterns
615
+
616
+ ### With React Router
617
+
618
+ ```tsx
619
+ import { BrowserRouter, Routes, Route } from 'react-router-dom'
620
+
621
+ // Import the CSS file once at the app level
622
+ import 'topiray-auth-react/dist/topiray-auth-react.css'
623
+
624
+ function App() {
625
+ return (
626
+ <ThemeProvider theme={defaultTheme}>
627
+ <BrowserRouter>
628
+ <Routes>
629
+ <Route path="/signin" element={<SignInPage />} />
630
+ <Route path="/signup" element={<SignUpPage />} />
631
+ <Route path="/forgot-password" element={<ForgotPasswordPage />} />
632
+ <Route path="/verify-email" element={<VerifyEmailPage />} />
633
+ <Route path="/2fa/setup" element={<TwoFactorSetupPage />} />
634
+ <Route path="/2fa/verify" element={<TwoFactorVerifyPage />} />
635
+ <Route path="/2fa/complete" element={<TwoFactorCompletePage />} />
636
+ </Routes>
637
+ </BrowserRouter>
638
+ </ThemeProvider>
639
+ )
640
+ }
641
+ ```
642
+
643
+ ### With State Management
644
+
645
+ ```tsx
646
+ // Using React Context
647
+ const AuthContext = createContext()
648
+
649
+ function AuthProvider({ children }) {
650
+ const [user, setUser] = useState(null)
651
+ const [isLoading, setIsLoading] = useState(false)
652
+
653
+ const login = async (email, password) => {
654
+ setIsLoading(true)
655
+ try {
656
+ const result = await signInAPI(email, password)
657
+ setUser(result.user)
658
+ return result
659
+ } finally {
660
+ setIsLoading(false)
661
+ }
662
+ }
663
+
664
+ return (
665
+ <AuthContext.Provider value={{ user, isLoading, login }}>
666
+ {children}
667
+ </AuthContext.Provider>
668
+ )
669
+ }
670
+ ```
671
+
672
+ ### With Form Validation
673
+
674
+ ```tsx
675
+ import { z } from 'zod'
676
+
677
+ const signInSchema = z.object({
678
+ email: z.string().email('Invalid email address'),
679
+ password: z.string().min(8, 'Password must be at least 8 characters')
680
+ })
681
+
682
+ function SignInPage() {
683
+ const [errors, setErrors] = useState({})
684
+
685
+ const handleSignIn = (email, password) => {
686
+ try {
687
+ signInSchema.parse({ email, password })
688
+ setErrors({})
689
+ // Proceed with sign in
690
+ } catch (error) {
691
+ setErrors(error.flatten().fieldErrors)
692
+ }
693
+ }
694
+
695
+ return (
696
+ <SignInForm
697
+ onSubmit={handleSignIn}
698
+ authProviders={['google', 'apple']}
699
+ // Pass validation errors to form
700
+ />
701
+ )
702
+ }
703
+ ```
704
+
705
+ ## TypeScript Support
706
+
707
+ Full TypeScript support with comprehensive type definitions:
708
+
709
+ ```tsx
710
+ import type {
711
+ ThemeConfig,
712
+ SignInFormProps,
713
+ AuthCardProps
714
+ } from 'topiray-auth-react'
715
+
716
+ // Custom theme with full type safety
717
+ const myTheme: ThemeConfig = {
718
+ colors: {
719
+ primary: '#0066cc',
720
+ // ... TypeScript will validate all required properties
721
+ },
722
+ // ... rest of theme configuration
723
+ }
724
+
725
+ // Component props are fully typed
726
+ const handleSignIn: SignInFormProps['onSubmit'] = (email, password) => {
727
+ // email and password are properly typed as strings
728
+ }
729
+
730
+ // Social login providers are strictly typed
731
+ const handleSocialLogin = (provider: 'google' | 'apple' | 'facebook') => {
732
+ // provider parameter is type-safe
733
+ }
734
+ ```
735
+
736
+ ## Accessibility Features
737
+
738
+ - **Keyboard Navigation**: Full keyboard support for all interactive elements
739
+ - **Screen Reader Support**: Proper ARIA labels and descriptions
740
+ - **Focus Management**: Logical focus flow and focus trapping in modals
741
+ - **High Contrast**: Colors meet WCAG contrast requirements
742
+ - **Reduced Motion**: Respects user's motion preferences
743
+
744
+ ## Browser Support
745
+
746
+ - Chrome 90+
747
+ - Firefox 88+
748
+ - Safari 14+
749
+ - Edge 90+
750
+
751
+ ## Contributing
752
+
753
+ 1. Fork the repository
754
+ 2. Create a feature branch
755
+ 3. Make your changes
756
+ 4. Add tests for new functionality
757
+ 5. Submit a pull request
758
+
759
+
760
+ ## Support
761
+
762
+ For questions and support:
763
+ - Create an issue on GitHub
764
+ - Check the documentation
765
+ - Review the demo application
766
+
767
+ ---
768
+
769
+ Built with ❤️ for the React community